Article summary
Much has been written about the technical challenges of rewrites. In one of his most famous pieces, Joel Spolsky argued that rewrites are almost never a good idea. On the surface, it seems illogical to spend a lot of time and money duplicating code that’s already working, and in a lot of cases, it doesn’t make sense.
Regardless of whether or not rewrites are a good idea, they happen, and when they do, addressing the non-technical challenges can be just as important as addressing the technical ones.
Some problems that appear to be of a technical nature can be solved in non-technical ways. The key to recognizing and solving them is realizing that software isn’t the solution to every problem. Often, all you have to do is overcome organizational issues or convoluted processes that arose in the past.
Organizational Issues
When an organization changes and the software system isn’t maintained to match, the two can diverge drastically over time. This divergence can lead to software that’s difficult to understand in the context of the business, and difficult to maintain or modify.
For example, a small organization might run its sales and billing out of one department. However, as the organization grows, it wants to split these functions into two separate departments. Making a change like this requires an organization to solve a host of business problems, including retraining employees, educating customers, and overcoming political issues when someone gets promoted over someone else, loses responsibilities, or has to report to an outside hire.
Rearchitecting the system to reflect the new structure is often very low on the list of priorities, if it’s considered at all, and it can be a significant undertaking. Something needs to be done, but properly decoupling sales and billing is a lot more expensive and time-consuming than simply adding a bunch of role checks all over the place. Opting for the faster and cheaper method will lead to a confusing system. End users may ask, “Why can I see things I’m not allowed to use?” And when developers have to remember to perform the role check each time they add a new feature, the defect rate will rise.
In this type of situation, the software may evolve to allow certain workflows that wouldn’t be possible if the concerns had been properly separated. You might hear a user say something like, “The system will allow sales to generate invoices if certain conditions are met.” Statements like these should raise red flags. It’s likely that in this situation, there really isn’t an organizational need for sales to generate invoices. The reason the system allows it to happen is because, at some point in the past, it was expedient to do so. The failure to rearchitect the coupling between the sales and billing functions made it trivial to implement, so it happened.
If edge cases like this exist for a long period of time, users can get used to them, and organizations may restructure themselves around them–even physically. Desks might be moved so that the special salespeople who also do billing sit closer to the billing department. A special color of paper might be used for this type of order. The cases where it’s appropriate for sales to invoice without going through billing might be expanded to the point that the organization starts to see it as an efficiency that must be maintained–an efficiency that grew out of a software wart.
Process Issues
Old software systems that grow organically over many years or decades may start to resemble Frankenstein’s monster. They might start out clean and well architected, but as business needs change and new pieces are bolted on (often in different languages, using different technologies, and written by different teams), the original architecture gets overshadowed and eventually ignored.
Systems that grow this way become harder and harder to modify. At some point, it may become easier to introduce hacks and workarounds to solve problems than to build the correct solution. Over time, these hacks and workarounds can become so ingrained in the minds of users that they eventually seem completely normal and logical.
One example is when text fields that are meant for one purpose are used for something else. For example, imagine that sales passes important information to billing by chunking a bunch of data onto the end of the address in the address field. Then someone in billing needs to read it, do something specific possibly outside the system, and erase the extra instructions before generating the invoice. Outsiders can usually spot these kinds of workarounds fairly easily, and replicating them in a rewrite is a big mistake.
Addressing These Issues
Sometimes, processes like these really are important and should be maintained, but they should always be examined carefully before you reproduce them in a rewrite.Try to trace the process back to its origin. Ask how it was done five or ten years ago. If you find out that the process started as an adaptation to work around a software limitation, it’s a good candidate for elimination.
You might run into an organization that’s convinced they can’t live without their awkward work-around. Before accepting that as reality, walk them through what a reorganized system might look like. Let them know that some of the roles and responsibilities in the sales and billing departments might have to change. Remind them that the short-term organizational friction they might experience will be far outweighed by having a system that is easier to understand and maintain.
Try to identify these trouble spots as early on in the development process as possible, and plant the seeds of a different way forward. Remind your client that it isn’t necessary to make a decision right away, but it’s a good idea to think about it.
I suggest using well-designed mockups or a working prototype with real data (instead of lorem ipsum or other randomly generated garbage data) along with multiple guided demos and walkthroughs to help them move ahead. Users sometimes get fixated on fake data and lose focus on the idea you’re trying to present.
It can also help to focus on incremental replacement. Sometimes, businesses believe that a rewrite is an all-or-nothing deal. Focusing on incrementally replacing functional areas can make it easier for people to envision process changes, while reducing the overall risk of the project. This can present its own set of challenges, but it’s worth considering.
It can take a long time to change someone’s perspective about something that they’ve been doing for many years. However, if all of the weird quirks of an old system are reimplemented in a rewrite, all you’re really doing is porting the old system to a new tech stack. The new system will end up being just as difficult to maintain as the original.
Instead, have these conversations early and often. Then work toward a rewrite that eliminates the baggage that bogged down the original system.