Code can often be a liability instead of an asset.
This may seem like a strange and controversial statement. After all, clients literally hire me to write them code, and we devote so much of our time to writing code—how can code possibly be a liability?
But let’s consider the proposition for just a moment. Thinking about the purpose of code, it’s good to remind ourselves that the code is not itself the end goal and has no value by itself. Instead, what we care about is the impact made and the value generated from executing that code, whether from automating away toil, saving time, even enabling something previously not possible.
If we reflect deeper (and perhaps recall a painful past experience having to deal with “old” code), it might dawn upon us that code has cost beyond the initial cost of development. Code has to be maintained. Informed decisions may have to be made regarding code just by virtue of it being around. Could it in fact be possible that the largest cost component of code is not in the initial development cost but actually in the long-term cost of code maintenance?
One might protest: why should perfectly correct code require active maintenance? Why not just leave it alone?
But one might eventually concede, there is no such thing as correct code without the context in which the code is being applied. And the context changes constantly. That’s the thing about the external world: it changes frequently and considerably. As a consequence, functional code can quickly become outdated and incorrect as time goes on (“system drift”), and thus requiring continual upkeep to remain correct.
Let’s say we take a look and determine that the code is still correct, that it doesn’t need to be changed—does it still then have cost?
In order to determine (or even remember) what the code is doing and whether it needs updating, one must first read the code (or some representation of the code), and that unfortunately still costs human time (from future people—could be future you). And that time will be spent henceforth, forever. If that code didn’t exist, no time would be spent or wasted reading or considering it.
Of course, this isn’t a forced choice between having code or not having code. We can have more succinct, more readable code. Not all code that accomplishes the same task is equal. If there is cost to reading code, it follows that the more unreadable the code, the more costly it is. Thus, an important consideration of code quality is readability, and because code length is a large component of readability, it frequently means the least costly code is a version of the code that tends to be concise. It is as true for code as it is for writing. Brevity is the soul of wit, and succinct code is the thoughtful product of a good engineer.
Inherit an “old” codebase and the costs of existing code become especially apparent. Seemingly simple questions become really hard to answer: What is this code trying to do? Is this code correctly doing it? Can I trust this code to be correct in the current context? Is this code that I’m currently looking at even relevant? The more one has to read and understand, the slower it is to get productive and make modifications. But one must understand both the current state of the code and the context of the code in order to make informed and correct decisions about the code.
To summarize:
Code is a liability becomes code needs to be maintained, and maintenance is forever.
Code is a liability because future time needs to be spent reading the code. Even if no changes are made, there still exists a long-term, ongoing cost.
Given this, a helpful and guiding question then when writing code may be: what is the minimal set of code needed to get done what we need to get done? That may be all the code we should want to exist. Everything else must go.
In fact, I believe this to be true in all aspects of developing software. When adopting a new trendy tool or technology to include as a dependency in your system, one would be very wise to consider the potential long-term and ongoing costs. Think hard about the human cost, the cost of adoption of your team. Ask yourself the hard questions and consider the relevant timelines. Is the supposed gain worth the risk of building upon some cool, nascent, cutting-edge technology with an uncertain future? Would you be willing to do the hard work of supporting your usage of it if you were forced to? If you need your software to continue running, making good technology choices and building solid foundations will dramatically contain the lifetime costs of that software.
Thinking of code as a liability is a bit tongue-in-cheek (and invites a bookkeeping joke), but it can serve as a valuable mindset. Be careful of what you keep lying around in fear of losing a potential asset. Consider what would be called assets, and you may discover new liabilities. Be minimalist in the projects (and their ongoing costs) you take on and aim to build only what is worthwhile (hopefully, where the value far exceeds the costs). You may even find this mindset to be one broadly applicable beyond software development.