A Tale of Two Failures

It was the best of times, it was the worst of times.  The company hired contractors to do maintenance work so that the full time developers can write a new system, the company hired new developers to write a new system stuck original developers with the maintenance work.

When software has been bankrupted by tech debt, a common strategy is to start over.  Just like financial bankruptcy, the declaration is a way to buy time while continuing to run the business.  The software can’t be turned off, someone has to keep the old system running while the new system is built. Depending on your faith and trust in your current employees you will be tempted to either hire “short term” contractors to keep things running, or hire a new team to write the new system.

The two tactics play out differently, but the end result is the same, the new system will fail.

Why Maintenance Contractors Fail

Contractors fail because they won’t have the historical context for the code.  They may know how it works today, but not how it got there. Without deep business knowledge their actions are limited to superficial bug fixes and tactical features.  The job is to keep the lights on, not to push back on requests or ask Who, What, Where, When, Why.

Since the contractors are keeping the lights on for you while current employees build a new system, they aren’t going to care about the long term quality of the system.  It’s already bad, it’s already going away, why spend the extra time refactoring.

Contractors won’t be able to stabilize the system and buy your employees enough time to build the new system.  Equally bad, sometimes the contractors *will* stabilize the old system which becomes an excuse to cancel the new system and not restructure your debts.

Why Hiring a New Team Fails Too

The flip side is to leave the current team in place and hire a new team to write the new system.  This is super attractive when you suspect that the original team will recreate the same mistakes that led to disaster.

This tactic fails because the new team won’t have the historical context for the code.  Documentation and details will be superficial and lack all of the critical edge cases. All of which delays the project.  Meanwhile, your original team will become extremely demoralized.  

If they couldn’t keep things running before, wait until you tell them their whole job is to keep things running.  The most capable members will quickly leave and you’ll have to pull developers from the new team onto the old system.

You’ll end up pulling the new developers onto the old team and praying they don’t see it as bait-and-switch.

Don’t split on Old vs New

Both tactics fail because the teams are divided between old vs new.  In the end it doesn’t matter who is on which team, because you need old *and* new to be successful.

Keeping the team together ensures that everyone has context into how the system works and has skin in the game.

Instead of splitting old vs new, find a way to split the system in half.  Have each team own half the old system responsibilities, and one of the two new systems.  This gives everyone a stake in keeping the old system alive, a chance to work on the new system, and reduces the business risk of either team failing.

Once you find a way to split the responsibilities in half, you might even find a way to make iterative improvements, it’s your Best Alternative to a Total Rewrite!

I wouldn’t have done it this way.

I confess to having said, “I wouldn’t have done it this way.”  The phrase seems like a polite way of trashing the current system architecture while implying that you know the correct design.

You might get a snicker and feel smart and clever, but you’re creating problems for yourself and your project.

It puts the original programmers on the defensive.  

You may be politely trashing their design, but you’re still trashing their design.  Instead of listening to you describe your superior solution, the original programmers are going to be thinking of arguments defending their work.

The Business People Don’t Care

The managers and executives in the room didn’t care about how the original programmers designed the system.  They don’t care about how you would have designed the system. They want to know what you’re going to do about their business problems.

It leaves the listener questioning your intent.  

Are you changing the design because you don’t like it, or because it needs to be done?  You never want anyone wondering if you are proposing a refactor or rewrite because of style.

Your way might not be possible

I once used PostgreSQL as a noSql system because all the other AWS options had row size limits that were too small.  For years after new developers would tell me that I should have used different technologies. I would explain the size constraint, and more often than not, show that AWS still had constraints that would prevent us from using the technology.

Instead of trashing the original design, try these two approaches instead:

Talk about the business problem with the current design.

“The current design won’t scale to the levels we need.”  Maybe it won’t scale because it was a bad design, maybe it was a massively successful MVP.  Either way, you need to replace it to go forward.

Be positive

“The current design was a great way to get started.”  If the original design was an abject failure, no one would be asking you to rebuild or expand it.  Acknowledge that, whatever its shortcomings, the original design moved the business forward.

Acknowledge your ignorance

“I don’t know what the original requirements were, but the current design isn’t a good fit for our needs”.  It’s useful to know why past choices were made so that you don’t miss requirements, and people are much more likely to tell you if you’re the first to admit you don’t know.

“I wouldn’t have done it this way” is an old developer cliche.  The developers who inherited your work are probably saying it about you right now.