Technology

How To Decide What To Do With Your Legacy Code

Michael Feathers, author of “Working Effectively with Legacy Code” defines legacy code as “code that we’ve gotten from someone else.” He goes on to define it as “tangled, unintelligible structure, code that you have to change but don’t really understand” and “difficult-to-change code” and even “legacy code is simply code without tests” because “With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.”

Regardless of your personal definition of legacy code, the question that usually bubbles to the surface is: “What should we do about this legacy code? Should we throw it away and rewrite it or should we leave the existing code and build on top of it?”

Whether you are a business owner who outsourced your software development and now wants to hand it over to someone else to improve/revise it, or a development team that has inherited code from someone else, here are some tips to help you make heads or tails of your situation.

Before you decide what to do, you have to take stock of your situation. Ask these four questions:

  1. Is the code quality high? High quality code can be defined in various ways — .does the code have automated tests? Is it well-factored? Is it easy to read?
  2. Is the code written using a modern technology stack?
  3. Is the highest priority business goal short-term or long-term? For example, do you need to fix bugs right now? Or are you launching an MVP to test product/market fit, do a demo, grab attention of investors? If so, then your high priority goal is near term. But if the future is more important than the near term (like you’ve got an existing customer base and you’re using this software to improve the business over the next few years), you’ve got a long-term goal. Of course, the future is always important. But, there are always tradeoffs, and we have to be honest about what the the highest priority goal is at the moment.
  4. Are the developers who wrote the legacy code part of the development team moving forward?

The answers to these questions directly impact how to go about dealing with your legacy code base.

Let’s walk through four examples:

legacy-code-base

Company A

Company A has been in business for 14 years. They have a thriving business, thousands of customers, and a reputation as a high quality brand. In 2014, they went through a rebranding, which included building a new software platform. After the rebranding effort was complete, the executive team discovered that while the visual elements of the rebrand were successful, the “behind the scenes” elements were not so successful. The result: a software platform in production that thousands of existing customers were seeing daily that threatened to ruin the brand’s reputation.

Company A Status Quo

  • The code quality is decent, but it could be better.
  • Tests exist, but most were neglected and no longer work.
  • There are critical, customer-facing bugs in production.
  • The tech stack used is modern (Ruby on Rails 4.1, Javascript, HTML5).
  • The future is more important than the near term (that is, they have a tested, implemented idea with a large customer base, so it’s critical to maintain that customer base over time).
  • The business outsourced the software development along with the rebranding effort to a digital agency who hit a home run on the rebranding effort and fell short on the development effort. So the development team at the digital agency is no longer part of the development team moving forward.

 

Legacy Code Base Solution: Triage

For Company A, the solution is: Triage.

  • It’s important to fix the production bugs as soon as possible.
  • Fix tests that are specific to the product bug the company is fixing, and then move on to the next bug.
  • As tempting as it is, save the rest of fixing and adding tests for later (you’ll get to them soon but have to prioritize fixing customer-facing bugs since there is a brand reputation to uphold)

For a legacy code base situation like Company A, act as if you are in the Emergency Room. Your goal is to stabilize the code first. And your second priority is to invest in the future and implement tests, do refactoring, clean up technical debt. Resist the temptation to throw away the code and start over. That would take a lot longer and would leave production code with bugs in the hands of your customers. Also resist the urge to clean up tech debt first. Work on customer facing value-adds ASAP to get the product stable, and then assess. Add just enough automated tests to the system to make sure your new code works.

In a greenfield, or new code base, manual regression testing isn’t something we do. Instead, an automated test suite is built that can handle regression testing. However, manual regression testing, at least at first, is also important. Without a working test suite, expect bugs to be introduced, even into seemingly unrelated parts of the system. Having one or more people take on the “regression tester” role can help. Before each deploy to production, walking through the system in a staging environment can help lower the chance of introducing new bugs while fixing the old ones (the “whack-a-mole” problem).

In this case, the code is good enough to keep, and it’s built in a modern tech stack. So, it’s not necessary to migrate the code base to another tech stack or to rewrite it. In this scenario, Triage works best. 

Company B

Company B is a startup. They have a big demo coming up in three weeks, and they haven’t yet launched their MVP, so they have no customers. The issue here is, they rushed and now realize the code quality is low. As a result, each time they go in to add a new feature in hopes that they’ll get it done for the demo, they break three other things.

Company B Status Quo

  • The code quality is poor.
  • The code is written using a modern tech stack.
  • The future is less important than the near term (the demo is the goal, the company wants to get a piece of working software that will wow folks at the big event. The company wants to test an idea, generate feedback and wow investors. If they succeed in the short term, they’ll buy themselves runway to decide how to handle the legacy code for the future).
  • The developers who wrote the code are still on the team, which means they can go directly to them with any and all questions.

 

Legacy Code Base Solution: Intentional Technical Debt

Although the existing code is poor, there’s no time to rewrite it. Even if there was time, it wouldn’t be the way to go here. The goal is getting a working product ready for a demo. Someone that sees the demo isn’t going to look under the hood. Instead, they are going to make a decision to buy or invest in the product based on what they see in the demo.

So, the legacy solution here is to be very strategic about where to spend time:

  • Focus almost exclusively on customer-facing features.
  • Intentionally build up technical debt. Keep track of your tech debt, either with post-its on a wall, Trello, Jira.
  • After all, the purpose of the demo is to get feedback. Make the product work, and use the demo to learn, and then post-demo, address the features your target audience finds most compelling and tackle the tech debt then. With only three weeks to go, incurring tech debt is fine (and make sure you record the tech debt so there is a “later”).
  • Be very strategic about writing automated tests. Only write tests if they are going to make you finish features faster before the demo. Usually, investing in regression tests for the long run is important, but not here. If you can easily get a feature out the door without writing a unit test, do it. Worry about backtesting later. Taking on tech debt without tests is a recipe for bugs. But remember, the company has no customers, so you’ve got nothing to lose. Better to get feedback from your potential customers and investors than invest in quality. After all, you are likely trying to build high-quality code for something that possibly nobody wants.

Company C

Company C, like Company A, has been in business for over a decade. However, in this case, the code base is very old, and there is no “fire.” Instead, the company has been getting by with what they have, and there’s no immediate danger to the brand.

Company C Status Quo

  • The code quality is poor.
  • The code was written a very long time ago.
  • The future is more important than the near term.
  • There are no external or visible threats or fires to put out. (There’s plenty of pain around using the software, but they’ve learned to live with it.)
  • The developer who wrote the code is no longer employed by the company.
  • The catalyst for taking action is the vision of what a high-functioning web app could do to add new revenue streams for the business and help grow the company.

 

Legacy Code Base Solution: Rewrite

For Company C, the choice is to throw away the legacy code and start from scratch. The code is so brittle and so old that it would be a more expensive endeavor to have a team go into the existing code and learn it enough to be able to make sense of it. In this case, the company is more than happy to use the existing, old product for another few months while the new one is being built.

The legacy application is used in parallel to the new application as features are rolled out. This has an added benefit that the end users can see two systems side-by-side to give very useful and real time feedback on the new application.

Company D

Company D has been in business for over 30 years. They have many systems, some home grown, some purchased, many integrated with one another, and all in various states of effectiveness. One software application was written in Rails 1.2 several years ago. The code had full test coverage and was high quality. After it was written, it was used and continues to be used daily. However, it hasn’t been touched since 2007.

Company D Status Quo

  • The code quality is high.
  • The code was written a very long time ago.
  • The future is more important than the near term.
  • There are no external or visible threats or fires to put out.
  • The developer who wrote the code is no longer employed by the company.
  • The catalyst for taking action is the team that uses the product has a small set of new features they’d like added to the product.

 

Legacy Code Base Solution: Upgrade

In the case of Company D, a very light-weight, two- to three-week upgrade is all this code needs. With some smart refactoring, an upgrade to the newest version of Rails is a simple chore. There’s absolutely no need to throw away the existing code or to be too heavy handed here. In this case, a light tough is the most cost-effective solution.

 

In Summary

Each legacy code base scenario is unique. It’s difficult to decide whether or not to scrap a legacy code base that you’ve invested time and money into. On top of which, once you decide which path to take, you then must implement the decision. To learn what to expect along the way, read Top 4 Lessons Learned — What To Expect with Legacy Code Migrations

If you still have questions about the best way to handle your legacy code base, email me, I’m happy to walk through your situation with you and give some advice.


Check out these related posts

Top 4 Lessons Learned — What To Expect with Legacy Code Migrations

4 Mistakes to Avoid When Outsourcing Development