I have some strong views on code quality. One of my professional goals is to always attempt to improve my coding with the aim of producing better code. In this day and age, making software “less broken” is about the most I can hope for. I cannot foresee a time when written software becomes “perfect” / “bug free”. Maybe it will – I have learnt: never say never…
Anyway, this is an article akin to playing devil’s advocate. I am not particularly comfortable with what I suggest below. I have written it purely to get people thinking about the time and effort expended writing software. As always, I encourage your comments – positive or negative.
One of the odd things about the software industry, is that code “rots”. This is somewhat strange. Source code, written in text files does not “degrade”. Unlike organic reproduction, copying a file leads to a perfect reproduction. If you kept a copy of code written say twenty years ago, it would still be the same today as it was then. Things change rapidly in the computing industry. As a result, it is extremely unlikely that you could use that twenty-year old code on a modern computer. A different form of “rotting code” exists precisely because the code does change. Over time, countless little hacks or quirks can be added to an active code base that leads to obfuscation and “unhealthy” code.
The common technique to reducing code-rot is refactoring. By having comprehensive unit tests, refactoring exercises help keep a code base current and ensure that changes made do not lead to regression bugs. Working on a well-maintained code-base is a more pleasant experience for a developer. Well-maintained code is easier to extend and developers have less fear of making mistakes.
“Technical debt” is a term coined by Ward Cunningham and refers to the “price paid” for releasing code for the first time. He argued that a small debt was useful to incur, as it helped speed up the development process. It was okay to incur some debt as long as it was “paid back quickly” by refactoring the code.
“The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation…”
Productivity graphs show how progress drops away on poorly maintained projects. The longer the project runs, the harder it becomes to add features or fix bugs without causing other regressions. The solution to the problem is to avoid as much technical debt as possible. Following best practices will help achieve this goal. But is this done at too high a cost? Following best practices adds extra work and thus does slow down development early in the life-cycle of the project.
Not repaying technical debt will grind a software project to a halt. If you use an analogy of credtit card debt equating to technical debt, having the software project grind to a halt is the equivalent of declaring bankruptcy. Obviously, this is not a great outcome, but it is not the end of the world either.
What if your software has run the term of its natural life? Your software will have been written to meet a specific need. Maybe that need is no longer there. Maybe that need is now perfectly met, or the market has been saturated and sales have evaporated. Maybe every feature that could be added, has been added (including reading mail). If the project gets “sun-setted” does it really matter how much technical debt is left in the code base?
Not “doing things the best I can” is something I struggle with. “Doing the best I can” and “doing things well” do not necessarily mean the same thing. Obviously, the process of software development happens on a linear scale. Software tends not to be written “the best way” or “the worst way” but rather somewhere in the middle. If the process your team uses is close enough to “the best way” end of the scale to not be crippled by technical debt, then maybe that is good enough.