| There's a tradeoff. It's important to approach rewrites and even legitimate breaking changes with the proper degree of maturity. A cavalier attitude to code quality is unhelpful and unprofessional, but gold plating a system out of a fear of change is almost as bad. I'd say the advice in the article is of mixed usefulness. Rewrites are serious business and merely embracing the idea that they are possible is not nearly as important as acquiring the skills, tools, and best-practices to do such things effectively. The fundamental problem that must be wrestled with when it comes to making big changes (major refactorings, rewrites, etc.) is not breaking things, it's risk. Everything about dealing with big changes is about risk management and risk mitigation. There are lots of ways to deal with making big changes though, here's a few bits of advice quickly: 1: Don't necessarily commit to the change prematurely. More so the larger the change. If you need to rewrite a complete application, system, or sub-system then consider keeping the new and old system in parallel. At the product level consider releasing a new product to compete with the old. It's easy to discount the value of maturity in a product but the value of real-world testing is immense even though often times its impact on a code base may not be incredibly obvious, especially if there are fundamental flaws which are evident. As an example, consider Microsoft Windows, which released NT-kernel and 9x-kernel versions of their OSes over a period of more than half a decade, allowing them to compete against each other and allowing the newer system to attain maturity before finally discontinuing OSes based on the old kernel. 2: Consider allowing breaking changes to be released. This is a fundamental tool that is necessary for anyone developing systems code whether it's kernels, servers, services, libraries, frameworks, etc. This is why it's important to version things, because you want to make sure that people have the choice to take an upgrade that includes a breaking change or not. 3: Get acquainted with all of the various techniques and tricks to deal with different forms of versioning. Library/framework versioning. API versioning. Service versioning. And make use of the tools and techniques which serve your use cases the best. For example, sometimes you need to completely change the way some functionality works which would result in client code having to be completely rewritten. In that case it usually makes sense to just introduce new functionality that just exists in parallel with the old ways of doing things rather than trying to press the new functionality into a form similar to the old or having to worry about versioning schemes and such-like. Also consider techniques like "feature flags" and staged rollouts of changes (every big software company from MS to Amazon to Google does this sort of thing and has built lots of tooling to support it). 4: Get skilled at refactoring, increase test coverage, and work step by step. 5: Formulate a development plan, the bigger the change the more formal the plan should be. Don't underestimate the effort necessary and don't skimp on things like QA. Also, have a backup plan in case the change does not go as planned. This is why it's often important to avoid premature commitment and to continue maintaining the old code, which you should set aside resources for as a risk mitigation technique depending on the nature and size of the change. 6: Read "Working Effectively with Legacy Code" by Michael Feathers and make use of the techniques described. |