Every experienced software developer at least once came across code that needed to be rewritten. Code that was originally meant for a smaller functionality set, then grew over time without any cleanups and finally eroded up to total unmaintainability. Code that degraded like a piece of rotten meat as Uncle Bob would call it (cleancoders).
It is easy to get budget for a rewrite when a software module finally reached the point where it can be proven that a rewrite will pay off in the short term. When it is on top of all bug statistics, when each bugfix comes with new regressions, when all developers cry out ‘oh no’ when the module’s name is mentioned, when most unit-tests remain deactivated (if there had been any).
But isn’t it too late when it has come so far? Shouldn’t a reasonable software architect go against this long before this singularity of irreversible erosion? Before it is easy to get the budget? Off course, and off course there are two basic actions: refactor or rewrite. Refactoring by using the principles of Fowler’s Book ‘Refactoring’ and Martin’s SOLID and Clean Code principles can be a total cure. This limits the domain for rewrites to code that is so rotten, so far away from the rest of the application, that a rewrite will be cheaper than a refactoring.
An example: In my experience a lot of embedded projects reuse code modules from a time where principles like OO and SOLID weren’t so popular to embedded programmers. A typical sign of this style is code that is written in C++, but reads like C. It is typical for C programmers that were forced to use C++ but resisted to think object orientated and used objects like a code module. Not to mention that such modules usually won’t have class-based unit tests. An I also observed a high degree of unnecessary inner redundancy in such code.
When the rest of the system’s code is written in an object oriented way, or even SOLID based with lots of instance injection and comprehensive class-based unit testing, a C-Style module really doesn’t fit into the code base and often (not always) such modules are candidates for becoming the next piece of rotten meat.
Back to our choice: refactor or rewrite. Can a C-Style module reasonably be refactored into SOLID OO code? To my experience this migration would be too far. Off course one would copy’n’paste some of the beef code when a rewrite is made. But a step-by-step refactoring would in most cases take longer and lead to inferior results when the technological distance is so huge.
However, if you decide to rewrite such modules to keep the overall code base at a comparable level and to prevent total erosion before it happens, you need to get the budget, or at least the commitment of the stakeholders. And usually they won’t be amused when you propose a rewrite in advance, because there is no short term benefit, and your stakeholders are assessed and also incentivized mainly by short term goals. They want to have new features and when you suggest invisible cleanups you’re suspected of behaving uneconomical, right? An ivory tower architect that decides based on the TNTWIWHDI criterion. Just ignore that kind of arguments, in the long term you won’t be able to do anything against it anyway, see it as a sign that you’re doing your job right.
Things become difficult when you will be confronted by the simple economic approach of estimating the lifetime of the module, the amount of maintenance cost in this lifetime and then to compare this against the cost of a refactoring (plus the lower maintenance cost of the refactored module) and against the cost of a rewrite (plus its maintenance cost) including the cost for making the rewrite as mature as the module to be rewritten. In my experience this approach will almost always lead to the decision of not starting a rewrite. But as we all know, software modules always live longer than expected, have more complexity than originally thought, are reused in more products than planned in the beginning etc.
Therefore my recommendation is to avoid this kind of short-term, naive economical discussions and to answer this by showing up the bigger complexity. A rewrite has the following benefits (in cases like above when the rewrite is faster than a refactoring):
- Fighting code erosion is a constant effort. Like a mechanist cleans up her/his workbench every day or so, also code has to be cleaned up regulary. The pitty is that a rotten workbench is easily visible and the need for cleaning it up is easily explainable. Explaining why non SOLID code is rotten to a superior, who wrote his last line of code back in the C era, is just impossible. So don’t go into the details of the current piece of work, this will only be used against you. Stay abstract, explain that a constant budget is necessary for the continuous fight against code-erosion and that you – the software architect – are the only one that decides where to spend it for. Clarify that if this budget is missing in a few years a complete rewrite of everything will become necessary, which can ruin everything (I like to mention the company ‘Nokia’ with their Symbian OS in this context).
- Avoid to call it a rewrite. In fact it is not that everything will be invented from scratch. The knowledge behind the code (which usually has more value than the code itself) remains in the new module and also the beef-parts of the code will remain – but be in another structure. You will find it a lot easier when you call the rewrite a reorganization. When you emphasize the aspect that existing functionality and existing code-snipplets are just moved into a structure that is more compatible to the rest of the application. And in fact this is usually not a lie.
- Don’t brag with the great innovations you’re going to apply in the newer, greater version. This makes you suspicious of using self serving technology (or TNTWIWHDI). It is best to avoid unwanted attention an not to initiate conversations about this topic. And by the way, this will also protect you from subconsciously ordering (or even implementing) rewrites that might be somewhat related to your own ego, because you had such a great idea of how this piece of code could be made better.
- If your organization allows this: Don’t ask for permission. If you ask questions, you might get answers that won’t help you. If you have a budget for continuous refactoring, great, then just do it. However, I personally would speak to some programmers about the sense of a rewrite because this is (depending on the module) a decision with a significant impact and during the first months the module’s degraded software maturity will cause effort. You better establish a firm commitment by the developers before starting to combat for budget.
- The last argument is: Developer fun. In a scientific context I once read “The brain runs on fun” and I agree tho this. Creating an atmosphere of creativity and fun is an important task for a software architect and having a relatively clean code base and state-of-the-art coding methodology is a key element for developer fun. However this argument is only applicable in companies who value software developers as an important resource. Traditionally in the field of embedded software the value of software developers is not utmostly high because the company sees at first the visible machine development. The thinking is like this: “Great, now we built the machine, we also need a little bit of software to run it, and we need a manual and a transport package off course, that shouldn’t be forgotten. Just copy the software-image into SAP right beside the manual …”. Ok, this way of thinking has changed over the past years because companies realized that software can provide USPs and that software nowadays consumes a big amount of the machines budget. Maybe it is a good idea before talking about developer fun to draw attention to the importance of software in todays devices. However, this argument is dangerous and can be used against you.