Code Life Cycle: Every Line is Technical Debt

The Problem

Programming in teams is hard: members favour their own code; ownership is important; once committed, code is hard to remove. Training new members is hard: they may not have confidence in their contributions; senior members my protect “their” work; all are afraid of pollution. It is desirable, but usually not practical, to have the following:

  • Freedom to experiment and make mistakes while learning, improving and contributing to production.
  • A small, flexible code-base (particularly vital in JavaScript).
  • Easily learnt and maintained tools.
  • Ability to keep maintenance interesting and evenly applied.

This is particularly applicable to teams working on languages like JavaScript. There are many approaches and styles that can be applied to a given problem. Less experienced members may fear making polluting mistakes, as will their teammates. And, despite their brilliance, most engineers would concede that the code they wrote today is superior to last year’s/last week’s/yesterday’s equivalent. We all live with past mistakes, everything decays over time.

Even with the most detailed foresight and planning, over the lifetime of a code-base, technical debt grows and maintenance becomes increasingly expensive. It is easier to add than remove; large applications are harder to learn; complexity leads to mistakes and introduces bugs. More code, more complexity, more bugs, more maintenance (less flexibility), more training for new team members, more developers and so on. It may not be possible to eradicate these flaws in the development process but there may be ways to reduce, or slow, their effects.

Freshness: a Possible Solution

Practises such as TDD, XP, code review, lint and quality control all aim to minimise the ravages of large teams and time on projects. However, these do little to keep the size of the code-base down. Less code is easier to manage, read, learn and maintain (as long as it stays small). As a concise, well formed, sentence is easier to read and understand; a brief but poorly worded passage is easier to discuss and edit. New developers should be encouraged to get involved and feel comfortable to learn via their mistakes.

In his article The Carrying-Cost of Code: Taking Lean SeriouslyMichael Feathers makes the case for a 3 month lifetime imposed on every line of code (at which point it would vanish from the repository). By being forced to completely rewrite applications over an over: it becomes impractical to make the code-base larger as there simply wouldn’t be time to cover it all.

This approach may be heavy handed, there would be cases where perfectly good code would be rewritten: preventing work in more valuable areas. However, over time requirements change; a perfect solution last week may become less so as the project’s focus shifts. These areas are also ideal for training, a developer can resolve a well understood problem (backed up with API contracts and unit tests) while colleagues can advise and support. Coupled with the easy branching, which tools like Git provide: rewriting, reviewing and merging/rejecting are straight forward.

Code can be graded by its “last modified” or “last reviewed” date, regular code reviews and the ability to monitor “freshness” would ensure all members of the team understand the mechanics of their project.

The more central the code the shorter the life-span. With JavaScript in particular, more code means poorer performance (whether it is time to download, execute or understand). The modules and functions that are called most frequently are those that need the deepest understanding. Conversely, repetitive “cookie cutter” functionality, typically found in areas such as views and templates, could be given longer to atrophy.

Reaching the end of a life-span doesn’t necessarily mean it has to be rewritten. If the code is still solving the problem it set out to, in the most efficient and readable manner, then its life-span can be extended. The code can be held up as an example of good practice and made the subject of comparison and code review.