Here there be dragons.
In 1510, that phrase appeared on a globe warning sailors of potential dangers. Fast forward five hundred years and beasts are no longer in the uncharted wilderness, but rather in the software we’ve built.
In a recent article, Phil Ryan of Ergo Group uses the monster metaphor to describe inefficiencies in our codebases that lead to more systemic and operational problems.
“The real monsters you will face up to are actually all around you. They are the systems that shackle your organisation like an anchor.” - Phil Ryan
Ryan goes on to describe three different types of “monsters” that prevent modernization: vampires, which drain resources; hydras, which exponentially spread problems; and sirens, which are beautiful distractions.
Chances are, you can see these monsters somewhere in your organization. Technical debt often shows up as an operations issue. The question then becomes, what do you do about it?
Once a team is ready to make a change, inevitably they are faced with a decision point of which approach to take: rewrite or remodel?
In this post, we’ll look at the different approaches and help you take the first steps on deciding on which approach best works for you.
At the macro level, a rewrite is completely replacing a system from scratch. This usually comes with a time-sensitive hard cutover and optionally porting the data from the old system to the new system. But let’s take a moment to dive in a bit deeper and understand what those decisions mean.
Defining “from scratch”
Rewriting means you completely ignore the existing system: a completely new code base, often on a new tech stack, often with a new team. Rewrites are often seen as clean slates that will let you start from scratch or introduce newer technologies and techniques without having to worry about doing so within the confines of the existing system.
Defining “hard cutover”
A hard cutover is when you’re using the existing system one day, and then, on a designated time, you switch over to the replacement system completely. Users log off of one app, then they log onto another one that’s attempting to solve the same problem.
The process of upgrading a desktop application is usually a hard cutover process (whether or not the team rewrote it from scratch). You close version 2, install version 3, and launch version 3. You might have the option of going back to version 2 if things don’t work out with version 3, but often times this isn’t a feasible option.
Defining “port data from the old system to the new system”
Every application has a corpus of information that it’s organizing. “Porting the data” means that you are going to transform that information so that the same information is accessible by using the new system. The data will move from one system to another.
When the Basecamp team rewrote their application, they left the old one running. Users got to decide whether or not to continue using the old version of Basecamp or take the effort to move their projects to using the newer version of Basecamp instead. Basecamp did not provide any tools at launch to do this.
Remodeling is an iterative approach to system transformation. Since this is the type of work that Corgibytes specializes in, we’re naturally biased towards this approach. Parts of the application are transformed, a little bit at a time, until the team agrees that enough of the transformation has been performed. The end result is that after a couple of years it’s very possible that the entire system has been rewritten.
Your body uses this type of approach every day. At no point in your life is your consciousness required to shift to a new corporeal form. Rather, your cells are constantly dying and regenerating. The lining in your intestines is effectively “new” after just a week, your fingernails and skin gets renewed every few months, the hairs on your head are completely different every few years, and after about ten to fifteen years, even your bones and muscles are new. In fact, with the exception of a few core systems, such as specific cells in your heart and brain and eyes, your body is completely transformed every decade or so.
Defining “parts of the application”
Just as with your body, different parts of your application will change at different rates. Like your brain and heart, there are likely fundamental systems which may not need to change all that often. This is why you see so many businesses and governments still running systems that have COBOL, Fortran and even Assembler at their core. Smaller subsystems that have more integration points will likely have a larger pressure to update more frequently, like your stomach lining or dermis. One architectural trend right now is to break up each of these parts of a larger system (sometimes referred to as a monolith) and put it into a more manageable form such as a microservice.
Defining “a little at a time”
If you’re a musician who reads sheet music, then you’ve likely seen poco a poco in your pieces. This term literally means “little by little”. It usually follows a crescendo (increase in volume) or decrescendo (decrease in volume). This is the composer’s guidance to gradually make a change.
This is the approach that we like to take for transforming existing systems. Don’t focus on changing too many different aspects of the system at once. Don’t focus on changing any one aspect too drastically. Slow and steady with a crescendo as you start to see results is what ultimately wins the race.
Defining “until the team agrees enough transformation has been performed”
At some point, you’ll start to experience diminishing returns from your remodeling effort. This typically happens long before the entire codebase has been replaced and as a result, many aspects of the original system will stay in place. This ability to flex remodeling efforts up and down based on the needs of the business is one of the most compelling reasons we find for remodeling.
With a rewrite, it’s more of an all or nothing approach. Another way to view it is that a rewrite is bulldozing a house and waiting for the new one to be built and a remodel is transforming one room at a time. With the first approach, you might be able to go faster, but the switching cost will be higher. For example: you have to move out of the old house, have a place to live during the transition, and you’ll be super stressed when things get delayed. With remodeling, there’s much less pressure, you don’t have to move, and the costs are typically much lower in the long run. These are all factors that will be important to making your decision.
Rewrites typically fail: here’s why
In Ryan’s article, he asserts that spending time slaying the monsters is a worthwhile effort to enable your modernization effort to get off the ground. The question then becomes, what’s the best way to do that?
With a rewrite, you focus on killing the monsters, but you rarely acknowledge the systemic conditions that allowed them to materialize in the first place. Arlo Belshee uses a parable of cutting yourself in the kitchen to illustrate this point.
“The improve testing strategy says “we’re going to cut ourselves all the time. How could we notice that so that we don’t bleed out?”…
Safeguarding would instead ask “why are we cutting ourselves 3 times a day? Why is this kitchen so unsafe?”…
Safeguarding is to flatten the counter top.” - Arlo Belshee
Or, to use our monster metaphor:
An improve strategy (rewrite) slays the monsters individually and focuses on conditions to help us slay them faster. Safeguarding (remodeling) looks at systemic conditions and team dynamics in addition to the codebase. Over time, monsters just stop appearing.
When a rewrite makes sense
Several years ago, we worked with a startup CEO who was trying to figure out why the awesome developers she wanted to hire were passing on her company. As it turned out, her CTO was incredibly opinionated about using ASP.NET WebForms, mostly because that’s what he’d worked with over the course of his career. The problem was, her potential staff were looking for opportunities to build RESTful applications and that’s not really compatible with WebForms. Because there weren’t many users and the application wasn’t very mature, we suggested a rewrite using more modern frameworks. The CTO walked away from the project, a new one came in, and they’ve been scaling successfully ever since.
A complete rewrite may be the best path if your project has no, little, or few:
Focus on the business needs first
Before you decide to take the risky rewrite approach, we often recommend starting with the subsystem that’s causing the most amount of operational pain. Some common areas to focus on are:
- Customer support issues
- Failing (or difficult) deployments
- Takes too long to validate a release
- Changes are introducing bugs
- Unable to bring on new team members
By focusing on the business problems first, you’re naturally going to be addressing the systemic issues at the same time that you’re renovating your codebase. You’ll also have the added benefit of being able to increase the amount of money that you’re able to invest in your modernization effort. When you re-write, you have a fixed bucket of funds that you can commit to the project before it launches. This puts pressure on the team which can exacerbate problems instead of solving them. Remodeling takes a different tack. You start where you can have the highest operational impact. That positive change usually increases your revenue or decreases your operating costs. In either case, you’re now in a position to invest more into paying down your technical debt. Over time, this produces a healthy system of both code and people and can be a huge competitive advantage for organizations. It takes time and isn’t easy, but then again long-term benefits usually require short-term sacrifices.
Thoughts? Comments? We’d love to hear from you! Share your perspective in the comments and don’t forget to join us for an interactive webinar this Thursday, January 11th at noon eastern. Hope to see you there!