These are people acting with a lot of intention!

These are people acting with a lot of intention!

In Technical Debt, we defined technical debt as the work not done or the shortcuts taken when delivering a product. Technical debt can be accrued intentionally or unintentionally.  Intentionally accruing technical debt means that the developer or team has made a conscious choice and hopefully mitigated the risk. If the debt is accrued unintentionally, the level of risk is higher because the impacted is unknown. Looking into where the technical debt comes from can help us infer whether it was intentional or not.

The taxonomy of the sources of technical debt is as follows:

  1. Code that isn’t extensible will require significantly more effort to enhance or maintain.  A team I managed early in my career came across a module late one night that had to be rewritten from scratch because we could not extend the function in the face of a priority one problem (it is a long story and you will need to buy me a beer to hear it).  Concepts like design patterns, object orientation or modular programming will help the team learn how to make their code extensible. Good standards, code reviews and pair programming are tools to ensure this technical debt is avoided. Generally this type of technical debt is accrued unintentionally, and unless processes or work patterns (like pair programming) are in place it can ripple through a project increasing effort and increasing the risk to delivering maximum value to the customer.
  2. Code that is hard to understand is by definition hard to maintain.  I once had to test an old DOS COBOL program that was so large that it had embedded assembler calls that unpacked and repacked specific bytes so that each bit could be used as a variable.  This program was a horror story to understand and test therefore it was rarely enhanced. This ‘bit’ of technical debt was explicitly accrued due to a compiler limitation and the lack of will to upgrade.  This is easy for team members to causally to agree accept, and is usually coupled with the agreement to refactor in the near future (which never comes). The ease which this type of technical debt can be accrued means that it can accumulated unintentionally. The impact is usually only obvious when the team needs to maintain or enhance the code making future work more risky.   As with extensibility – code reviews, standards and pair programming are tools to reduce this type of debt.  I also suggest periodically adding refactoring stories to all project and application backlogs.
  3. Code that knowingly represents incomplete requirements is a type of technical debt that is a bit of gray area, and could arguably be considered a defect. In order for this category to be technical debt, the team (including the product owner) needs to knowingly decide not to develop a whole breadth of a requirement.  I have seen teams take this option to make specific delivery dates. Phasing projects, re-arranging release plans or breaking up user stories are approaches to using this tactic in a transparent fashion.  Doing is this by accident is a defect, and therefore the impact is unpredictable until it is noticed.
  4. Code, modules or applications that are difficult to implement costs everyone involved in the implementation and installation effort and aggravation. Implementation approaches like code usually have multiple possibilities (the hard way and the easy way). Development teams that include members of operations generally will stray toward the easy way, however choices are sometimes made in order for a team to make a date (e.g. compliance requirements or end of year processing are dates that generally aren’t negotiable) that pushes the team to toward the hard way and that accrue technical debt. Including operations personnel in the development teams (or minimally including operations personnel in reviews and demos) are tools to help avoid unconsciously accruing this type of technical debt. Assuming basic reviews, implementation standards and a trained or experienced team, this type of technical debt is generally accrued intentionally and the impact is predictable.
  5. Code that does not meet organizational standards (code or architecture) is generally intentionally accrued when teams are faced with an unmovable deadline. The ability to compare the code to standards makes the impact of not meeting those standards more predictable therefore less risky but only if the choice is made on purpose and transparently.  This type of debt can be accrued unconsciously only when standards are either not very well understood or are not applied consistently.  Make sure all team members are trained on the organization’s standards, hold reviews and make sure they are applied consistently.  One final note: good portfolio management and estimation of releases and projects are useful to ensure that teams do not start work with a due date that is too aggressive and will cause them to cut corners.
  6. Code that is not fully tested.  I was a quality assurance manager once upon a time.  In organizations that test last in their systems development life cycle, there will always be pressure to test less when a sprint is nearly over or a release is due. This form of technical debt, even thought it  comes perilously close to being a defect (or defects), is generally accrued unintentionally. The lack of predictable impact makes this type of technical debt more risky.  Techniques like test driven development, acceptance test driven development or behavior driven development are tools to avoid having to accrue this type of technical debt.

Technical debt can be a combination of intentional choices made by rational teams.  When we accrue technical debt unintentionally, we increase the risk.  That risk might not only affect the current project, but also our ability to enhance and maintain the code going forward. Knowing the sources of technical debt and how we can combat unintentionally accruing that debt is a positive step toward reducing risk and managing the technical debt backlogs all projects accrue.