Sorry, this is going to be long, but it's based on personal experience as both architect and developer on multiple rewrite projects.
The following conditions should cause you to consider some sort of rewrite. I'll talk about how to decide which one to do after that.
- Developer ramp-up time is very high. If it takes any longer than below (by experience level) to ramp up a new developer, then the system needs to be redesigned. By ramp-up time, I mean the amount of time before the new developer is ready to do their first commit (on a small feature)
- Fresh out of college - 1.5 months
- Still green, but have worked on other projects before - 1 month
- Mid level - 2 weeks
- Experienced - 1 week
- Senior level - 1 day
- Deployment cannot be automated, because of the complexity of the existing architecture
- Even simple bug fixes take too long because of the complexity of existing code
- New features take too long, and cost too much because of the interdependence of the codebase (new features cannot be isolated, and therefore affect existing features)
- The formal testing cycle takes too long because of the interdependence of the existing codebase.
- Too many use cases are executed on too few screens. This causes training issues for the users and developers.
- The technology that the current system is in demands it
- Quality developers with experience in the technology are too hard to find
- It is deprecated (It can't be upgraded to support newer platforms/features)
- There is simply a much more expressive higher-level technology available
- The cost of maintaining the infrastructure of the older technology is too high
These things are pretty self-evident. When to decide on a complete rewrite versus an incremental rebuild is more subjective, and therefore more politically charged. What I can say with conviction is that to categorically state that it is never a good idea is wrong.
If a system can be incrementally redesigned, and you have the full support of project sponsorship for such a thing, then you should do it. Here's the problem, though. Many systems cannot be incrementally redesigned. Here are some of the reasons I have encountered that prevent this (both technical and political).
- Technical
- The coupling of components is so high that changes to a single component cannot be isolated from other components. A redesign of a single component results in a cascade of changes not only to adjacent components, but indirectly to all components.
- The technology stack is so complicated that future state design necessitates multiple infrastructure changes. This would be necessary in a complete rewrite as well, but if it's required in an incremental redesign, then you lose that advantage.
- Redesigning a component results in a complete rewrite of that component anyway, because the existing design is so fubar that there's nothing worth saving. Again, you lose the advantage if this is the case.
- Political
- The sponsors cannot be made to understand that an incremental redesign requires a long-term commitment to the project. Inevitably, most organizations lose the appetite for the continuing budget drain that an incremental redesign creates. This loss of appetite is inevitable for a rewrite as well, but the sponsors will be more inclined to continue, because they don't want to be split between a partially complete new system and a partially obsolete old system.
- The users of the system are too attached with their "current screens." If this is the case, you won't have the license to improve a vital part of the system (the front-end). A redesign lets you circumvent this problem, since they're starting with something new. They'll still insist on getting "the same screens," but you have a little more ammunition to push back.
Keep in mind that the total cost of redesiging incrementally is always higher than doing a complete rewrite, but the impact to the organization is usually smaller. In my opinion, if you can justify a rewrite, and you have superstar developers, then do it.
Only do it if you can be certain that there is the political will to see it through to completion. This means both executive and end user buy-in. Without it, you will fail. I'm assuming that this is why Joel says it's a bad idea. Executive and end-user buy-in looks like a two-headed unicorn to many architects. You have to sell it aggressively, and campaign for its continuation continuously until it's complete. That's difficult, and you're talking about staking your reputation on something that some will not want to see succeed.
Some strategies for success:
- If you do, however, do not try to convert existing code. Design the system from scratch. Otherwise you're wasting your time. I have never seen or heard of a "conversion" project that didn't end up miserably.
- Migrate users to the new system one team at a time. Identify the teams that have the MOST pain with the existing system, and migrate them first. Let them spread the good news by word of mouth. This way your new system will be sold from within.
- Design your framework as you need it. Don't start with some I-spent-6-months-building-this framework that has never seen real code.
- Keep your technology stack as small as possible. Don't over-design. You can add technologies as needed, but taking them out is difficult. Additionally, the more layers you have, the more work it is for developers to do things. Don't make it difficult from the get-go.
- Involve the users directly in the design process, but don't let them dictate how to do it. Earn their trust by showing them that you can give them what they want better if you follow good design principles.