Refactoring --- from Working Prototype to Extensible Product
The three techniques that makes this easy!
You and your team has built a product that people want, and now they envision a ton of features to add. You’ve got here by pivoting several times, taking some shortcuts, and learning as you as fly. So while the product looks great, the codebase is hard to extend. This is exactly the time you want to refactor, not add features!
So for this month’s whiskey moment, Arlo’s sharing a case study from personal experience about three specific refactoring techniques that make the codebase extendable while adding features.
The period of rapid pivots leaves code with three common problems. It’s no one’s fault; they arise because we make the best code we can for a particular problem, then discover we need to pivot it to solve a different problem. When we finally find the right problem, the code is very difficult to change. The code seems terrible and devs want to throw it out as a prototype and now write the real product. But this is the worst possible time for a rewrite from the business perspective. Instead, we need to leverage our early adopters, and that means responding to feature demand quickly!
Here are the three most common problems and their solutions. Arlo’s talk describes how he applied each on a recent project.
Some capability turned out to be the most important. You can identify it because it is spread everywhere. That makes it very difficult to change - even to update the integrations with 3rd-party components. So the thing that is most important to change is also the hardest to change!
Extract a library in place, and then put a Port in front of it.
Don’t fully separate the library from the calling code. Keep the library in the same build, source control, and other systems. You can fully separate after you get some features built.
After later pivots, things that originally changed together now separately change. As a result, code that changes separately is tightly bound together.
Convert each concern to a phase in a data processing pipeline. Introduce an intermediate data representation that can be used by all steps of the pipeline.
Ensure the pipeline never modifies data. Instead, each calculation should always add new data to the intermediate representation. Because everything uses the same data structure, it is easy to insert new steps or change their order in the pipeline. This is not a final design, but is a great start. Finish the split later, after you’ve gotten more features built and the sequence has settled down.
The extensions we need to add now are different than the ones we expected before all the pivots. Now every time we add functionality, we have to add code in a bunch of different places - and often the same places each time.
Gather related code into one place using the gather component technique. This will create multiple categories of components. Then extend your product by adding new components to these categories.
Write unit tests for each component, then extract reusable tests for each category. Now each component has a base set of tests to ensure it meets the needs for its category, then extends that set for its particular behavior. This keeps you from forgetting some key requirement when you add a new component to a category. Don’t define sharp interfaces or other constraints yet! You can do that after you get some features out.
Recent Podcasts with Arlo!
How to Scale Software Teams
Art of Agile Development Book Club
Check out our About section for more podcasts in which Arlo has contributed.
Deep Roots Events
August 25 | Ask Me Anything! | Sign Up Now
Grab a seat at the proverbial bar and enjoy a short lightening talk from Arlo to set the stage, and bring your thoughts and questions to the table! Join for free!
October 10 - November 4 | Refactor Well with Naming as a Process (NaaP) | Register Now
Ready to up-level your refactoring skills with Arlo? Join our next workshop! Early bird pricing available through Sept 16. Limited seating.
"Previous refactoring kept going deeper and deeper down a rabbit hole, trying to understand before I change anything. Now it just flows."
"This is teaching me such a general skill. I apply it every day, in every language."
"Every software developer should learn this."
Thanks for reading Arlo | Refactoring with Depth! Subscribe for free to receive new posts and support our work.