What if instead of massive rewrites, we adopted monthly scheduled rewrites? An iterative process within an interative process.
Sofware rottens, no matter what. Unexpected changes in requirements or domain can result in code and system cripple, causing teams to slow down. Consequently the pace to deliver new features diminishes over time. This natural slow down is not taken into consideration when estimating delivery, since there’s a false assumption that team speed remains constant. Teams then face pressure to keep a pace that doesn’t reflect reality, creating a trend to avoid doing work that would potencially increase productivity.
This pattern is repeated and review after review the team tries to figure out why delivery speed is decaying, until delivery speed becomes too slow because of codebase complexity and a big change is needed. This big change have a huge impact, because we were expecting to deliver product features, but now we have to stop generating value for a huge time in order to refactor our code.
Recognizing this natural deceleration allows teams to plan accordingly and take action to ease their process. The strategy is to “rewrite as you go”, but that’s easier said than done. In order to do that we should recognize what problems do big rewrites solve and how.
By having a clean slate to work on and the knowledge of the current issues, a rewrite aims to generate simple solutions to the problems of the codebase while keeping its capacity to solve the domain problems. It does that mostly by trying to align the codebase’s complexity with the application’s problems complexity.
Big rewrites identify complex concepts of the domain that are not well represented - like business rules hidden in code - and solve this issue by abstracting it properly, creating a clearer visualization of the implications of the problem. They also seek and remove abstractions that don’t yield good returns given the complexity they add to the codebase, eliminating friction during development.
To avoid the situation where the team is already too slow and the need for a rewrite is imminent, we can leverage what we know about how rewrites increase productivity and apply it in a constant fashion. Once we stablish a deliberate practice of doing so and schedule it, this time would not be ignored when estimating delivery and we’ll be able to constantly improve our codebase as it gets inevitably worse with time.
It’s important to notice that this practice of rewriting should have a dedicated time. One can - and should - make improvements when delivering new features, but trying to accomplish greater improvements would likely delay the feature and complicate things. By having a dedicated space for rewrite work we can focus solely on improving the codebase without a feature deadline.
My team actually tried this approach, yielding very good results. We wouldn’t call it rewrites, but something like “things we hate in our codebase, addressed on friday mornings”. We would list potential improvements during the week and we tackled them every friday morning.
Of course the situation is different for every team, but I’d advocate for negotiating some time and dedicating it to rewrite sessions. Make some integration tests and try to understand why does this part of the codebase is slowing your team down. Try to implement it from scratch. Design a new solution from that will solve the same problem. Avoid big rewrites with smaller rewrites.