Monday, August 4, 2014

Technical Debt

I'd like to take today's soapbox to explain the concept of technical debt.

During the development of an application a developer faces many decisions where he can choose to do what's right for the long term or what is expedient for the short term. For example, a programmer might fix a bug in a way that is quick to do but difficult to understand or he might re-write the code to fix the bug and also keep the code easy to understand. A typical developer makes these decisions multiple times per day. (I hope you trust your developers!) The path your developers choose determines things like how easy it is to add a feature, whether anything breaks when you do and how long the changes take to stabilize.

Every time a developers chooses to do things the quick way he slows himself (and everyone else) down in the future. The thing is, the harder he pushes the quicker things get done in the short term but the longer things take in the future. Over time he will be working very hard, taking all the shortcuts he can and not advancing at all.

Aspects of legacy code that slow you down are called technical debt. It works like ordinary, monetary debt. You can take shortcuts and spend more than you have for a while but if you keep doing it the interest will kill you.

Every project needs to hurry at some point. That's perfectly normal and it should be possibly to take on technical debt for a short while. However, if you keep doing that your software project will eventually stall; you'll reach project bankruptcy.

Technical debt is usually accrued by taking shortcuts, but this is not the only way. You can also get technical debt by changing the requirements. Every time you add a feature or otherwise change the behaviour of a piece of existing software it requires changing how that software works. If many changes are required then those required changes become technical debt.

On large projects, relatively simple changes can cause a cascade of modifications across the whole software project. For example, a new feature might require a change on the backend, which might require a change to the database, which might require a change to the database update script. A seemingly small change might cause a crisis level change by the time it hits the database. For example, supporting a characters with accents not expressible in CP-1253 would require upgrading the database to UTF-8.. which might not be easy if your database engine is very old. Suddenly a system that has worked fine for years becomes a big blob of technical debt.

On these large, long running projects, the hardest part of any enhancement is integrating with all the stuff that's already there. Not only that, but changing one thing triggers a cascade of changes everywhere. It's not an exaggeration to say that many large software projects tend to get stuck in the mud due to bad technical debt management. The way to avoid this is to have a plan to address at the technical debt pain points. (I've stolen this from Wikipedia):

Causes for technical debt

  • Business pressures, where the business considers getting something released sooner before all of the necessary changes are complete, builds up technical debt comprising those uncompleted changes.
  • Lack of process or understanding, where businesses are blind to the concept of technical debt, and make decisions without considering the implications.
  • Lack of building loosely coupled components, where functions are not modular, the software is not flexible enough to adapt to changes in business needs.
  • Lack of test suite, which encourages quick and risky band-aids to fix bugs.
  • Lack of documentation, where code is created without necessary supporting documentation. That work to create the supporting documentation represents a debt that must be paid.
  • Lack of collaboration, where knowledge isn't shared around the organization and business efficiency suffers, or junior developers are not properly mentored
  • Parallel development at the same time on two or more branches can cause the buildup of technical debt because of the work that will eventually be required to merge the changes into a single source base. The more changes that are done in isolation, the more debt that is piled up.
  • Delayed refactoring – As the requirements for a project evolve, it may become clear that parts of the code have become unwieldy and must be refactored in order to support future requirements. The longer that refactoring is delayed, and the more code is written to use the current form, the more debt that piles up that must be paid at the time the refactoring is finally done.
  • Lack of knowledge, when the developer simply doesn't know how to write elegant code

  • Have you had this experience recently?

    Continues in the next article: Why do You Seem to Always be Refactoring?

    No comments: