Get an incremental solution to a gnarly technical problem every month.

Most technical debt problems in Legacy code are too big to solve. After all, you’ve already solved all the ones that were small enough to solve, given your organization, code, tooling, and techniques.

Every month, the Code by Refactoring newsletter picks one gnarly problem. Our gnarly problems in 2021 will be focused on getting your code ready for DevOps.

Each newsletter:

  1. Frames a DevOps blocker so that everyone can understand the underlying problem.
  2. Provides a step-by-step solution that you can start without permission and continue with the full team.
  3. Describes the results you can expect at the business level, to support your conversations with leadership.
  4. Show how to demo your results in a way that will excite your Product Owner and Executive Leader.

DevOps #4: Extract Components to Edit Independently

Other People Keep Messing with My Code! I was working with a company that had about 100 teams in the same product. Each had a different purpose, so each changed different code. However, it wasn’t as clean as that makes it sound. Each team found itself making contributions across a quarter of the product. Each change impacted the work of a few other teams. Each method or class was shared among 2–4 teams — but it was a different 2–4 […]

DevOps #3: A Roadmap to Escape the Monolith

Our Code is Hopelessly Entangled With the Monolith! We really want our code to be a set of services. That unlocks CD and DevOps. However, our code is currently a long ways away from being Service Oriented so we will get to services incrementally. Our first target is Continuous Integration (CI). We think of CI as a system to rapidly find mistakes so that we can correct them. However, the power of CI comes from an unexpected source — team […]

DevOps #2: Enable Unit Tests

Our Unit Test Suite Hurts! TDD, CI, and DevOps assume that unit tests have the following traits: Domain relevant: Test one thing the user cares about and could describe. One Way to Fail: Can only fail for one reason, which is its assertion. Independent: Execute only the code they verify. You don’t need to update the test if anything else changes. Cover Functionality: The set of tests as a whole cover all behaviors of the system. This is bug coverage, not code coverage. But […]

DevOps #1: Automate Yourself with Checklists

I Can’t Automate This! Many years back I inherited a 30-year-old legacy code base. We were to clean up the C++ and make it work on modern hardware. However, the first step was to get it to even compile. Before us, building the product required 3 specialized build engineers, each with individual knowledge and unusual machine configurations. Each would remap the source, compile, get a partial success and set of failures, then pass it on to one of the other […]

Use Data to Split a God Class

Don’t Make Me Touch Ordering! The PM thought the feature was simple. And it should have been. Unfortunately, it requires making a tiny change to payment processing. And payment processing is part of the Order system…which is one monster class. More than half of our code depends on Order to do something. Each part of that code depends on the Order for a different set of responsibilities. Although there are patterns, the Order class’s sheer size and number of responsibilities […]

Isolating Dependencies with Ports and Adapters

My Service Interaction Tests are Slow and Fragile! Any legacy system needs to connect with other systems. However, coding and verifying changes in your legacy system requires the following things.  Simulate remote faults and verify your response. Verify that what you send to the remote system will cause it to do what you want it to do. Know when a release, rollback, or failover of the other system will change a behavior that you depend on. Change your released code’s […]

Creating and Shipping a Chimera

My product is written in the wrong language! Legacy systems tend to be old, and thus written in languages and frameworks that were available at the time they started. It’s no one’s fault, but the code is in the wrong language. This causes: Slow development. Difficult testing – my tech predates the TDD movement. Reinvention – libraries for new techniques are written in new languages. Difficult hiring – my tech predates most developers. More bugs – my tech needs more […]

From Hard to Easy: Changing Database Schema

I hate changing the database! Legacy databases present two challenges: Bad schema that is hard to change. Too much logic in the database. Both delay stories and generate bugs. Both waste your time and each will require thousands of person-hours to fix. We need to find a way to pay that cost incrementally; preferably divided among all the developers on the project. First let’s divide the problem in half by ignoring the logic for now. After all, lots of logic […]

Start Fixing a God Class

All I want to do is edit the freaking document! Unfortunately, so does everything. CDocument is central to what we do. Users think of documents, and so does the UI. Every piece of code reads the CDocument class…unless it modifies CDocument. And now I need to unit test my code. Also, I want to ship my team’s code independently of the other team. But every single feature touches CDocument. Many of them change CDocument – or one of the 6 […]

Make Tests Independent

I changed a piece of code and 75 tests broke… It was a simple feature. I just added a GDPR approval checkbox when creating a new account. And suddenly half our tests broke. Tests for reporting, tests for core features, all kinds of tests for all kinds of things. Because every one of them needed to create an account. So I added a default to the test mocks. I updated lots of expecteds. I added a startup step to some […]