We all have faced numerous situations with the legacy code and brownfield applications. General feeling towards these is "there is too much development friction, it would be easier to scrap the code and start a new version".
For a long time I've been a believer in this approach as well. This "long time" actually goes towards the beginning of my development career. Yet. despite the urge to rewrite everything, most of the times the situation went to restraining myself and gradually evolving the codebase.
This path initially feels to be much harder than a simple rewrite, simply because there are more variables software architect has to consider (as we all know a person can keep in mind only 5 +/- 2 distinct entities at a time). There are a few solid advantages, though:
- Code stays in production-ready state. This keeps the business value at a steady level and does not break the communication loop.
- Evolving code guarantees that there will not be any missing features or other small-but-important details that tend to go missing in the first rewrite version.
- Evolving code will stay within the feedback loop of quality assurance teams and customers. This would make it much harder for the codebase to go astray (which tends to happen when we, developers, close up in our dens to write the next version from scratch).
- Pushing existing codebase is quite hard, due to all the momentum complex systems accrue. However, it creates a much better understanding of domain and applied technology at hand.
So the resume is "dropping legacy code is bad, evolving is better". How do we do it? . Here's a simple approach I've came to:
- Isolate logical portion of the code that has to be evolved in the iteration.
Ensure that the scope of iteration is limited and understandable. You might want to use Project Management templates while documenting the scope.
Documentation part might be extremely important (even if it is merely about a few paragraphs), since it helps to clarify and settle down vision of the iteration. Written document would also serve as a nice restraining factor preventing the scope creep.
Ensure that it is covered with unit tests and other types of tests, if applicable.
Implement the prototype
This might take some limited time (and a few rewrites), since we will be seeking for the right ideas and implementation concepts
Component-driven development will help.
- Merge the prototype
Write down for yourself somewhere:
- Lessons learned
Basically, code itself does not really matter. Ideas and logic behind it are the real value. I'm not talking about the "business value" at this point (which is the development driver and focal point), but rather about architecture, patterns and composition. They are unique for every single domain.