Legacy Code Already

Today I took some time off from Poker Copilot and contributed to BlazingStars instead. My task: add auto-detection of the current PokerStars theme to BlazingStars.

I have already done this in Poker Copilot. Therefore I took the existing Poker Copilot Java code and converted it to Objective-C, so that BlazingStars could also use it.

While doing this I noticed that the code seemed more complex than I would have expected. There were some strange clauses. One block checked two different locations for the PokerStars preferences. Another code block accommodates unusual theme names that don’t follow the typical pattern. I added each of these clauses after chasing down problems that users reported. Each problem only arose after thousands of people had downloaded and used Poker Copilot.

After less than two years, Poker Copilot has legacy code. Legacy code is a pejorative term in the software industry that originally applied to code from older, no longer supported systems, languages, or operating systems. Over the years, the meaning has expanded to refer any existing code that doesn’t use the latest, greatest technologies, or seems more difficult to understand than to rewrite.

In my opinion, legacy code is good code. It is code that has survived because it works. It is code that has had bugs removed and work-arounds added. It is code that can cope with unusual situations. It is code that stands behind many days, months, and years of application use. Rewriting legacy code usually leads in the short term to a less stable, less reliable system.

Having legacy code in the system also means one has to work somewhat slower. Fixing a problem means first understanding why the existing code has various clauses. It also means care must be taken when adding new features.

I try to reduce the negative impact of legacy code in my own projects by dividing coding time between cleaning up existing code and adding new features. When solving an existing problem I go through the following steps:

  1. Locate the problem
  2. Add a unit test that fails because of the problem
  3. Clean up the existing code to make it more understandable
  4. Make sure the full set of unit tests – excepting the one added in step 2 – still pass. If not, I return to step 3
  5. Fix the problem identified in step 2
  6. Make sure the full set of unit tests – including the one added in step 2 – pass. If not, I return to step 5