I was playing Tetris over the weekend when I realized it’s a great metaphor for managing technical debt.
To briefly recap, Tetris is a tile-matching puzzle game. The goal is to drop different-shaped blocks - fill up an entire row to eliminate it and earn points.
As the blocks fall, you must consider:
- How are the previous blocks currently arranged?
- Is there an ideal location to place the current block?
- What blocks are coming up next and how might they fit in?
Consider this example:
We have several options for placing this block (including some not pictured here). Note the three outlines of potential vertical placements - the block kinda fits there, but it doesn’t clear out any rows. Placing the block in any of those spots is a valid move and doesn’t jeopardize our short-term success, but it doesn’t help clear out the “debt” we’ve racked up earlier. Furthermore, if we continue making moves like this without addressing the lower blocks, we’re going to find ourselves struggling later on in the game.
We should also consider that upcoming block - the left side looks like a good spot, but we lose that option if we place the current piece on the left.
A better strategy is illustrated by that lower horizontal block placement. Note how placing the block here clears out two previous rows! Clearing out this previous “debt” will give us some breathing room and make it easier to place other blocks later on.
To quote Wikipedia:
Technical debt is “a concept in programming that reflects the extra development work that arises when code that is easy to implement in the short run is used instead of applying the best overall solution”.
Technical debt can be compared to monetary debt. If technical debt is not repaid, it can accumulate ‘interest’, making it harder to implement changes later on. Unaddressed technical debt increases software entropy. Technical debt is not necessarily a bad thing, and sometimes (e.g., as a proof-of-concept) technical debt is required to move projects forward.
There might be several different ways to implement a new feature; in doing so, one must also manage the technical debt using a similar thought process as playing Tetris:
- How is the codebase currently architected?
- Is there an ideal location to implement the current task?
- What features are coming up next and how might they fit in?
Doing so will make it easier to both maintain existing functionality and introduce new changes & features.