Try as we might, our industry seems unable to completely shake off the notion that developer productivity can be measured in lines of code. I know of a certain large financial firm that prominently displays live statistics such as commit count and lines of code, broken down by developer. I guess this is supposed to motivate their army of developers to be more productive (along with a companion screen that displays their ever-shifting positions on the department org chart). Unfortunately, I think that we have a tendency to measure ourselves by this standard as well. Developers often feel that time spent doing something other than writing code is simply wasted. I am certainly guilty of this, especially when I can blame my lack of coding time on meetings and other “management” activities.
To resist this tendency, I try to remember that it is not our job to create code, but to create functionality that empowers the business to succeed. We don’t produce widgets – we figure out how to make widget production more efficient. To use an analogy that may be familiar to that large bank I mentioned above:
Functionality is an asset, but code is a liability.
As any good bank should understand, you want to maximize your assets and minimize your liabilities. In the same way that a bank needs to take in deposits (liabilities) to fund loans (assets), a development team needs to write code (liabilities) to create functionality (assets). As we know from recent experience, things can go very wrong at a bank if assets are overvalued, leaving their true value unable to cover the liabilities. Similarly, in development, the functionality delivered needs to cover the cost of the code – and not just the one-time expense of writing it, but the continuing expense of maintaining, modifying, configuring, deploying, and supporting it.
What can we do to make sure that we don’t lose all of our secured code deposits on a bunch of shaky sub-prime features?
On the asset side of the equation, try to perform a realistic cost-benefit analysis for each feature added. Most firms assess the cost purely in terms of developer time required to implement the feature. While this is important, it does not capture the full cost, which includes ongoing maintenance and support. Often projects can be done faster by cutting corners, decreasing the measured cost (time to delivery), at the expense of increasing (sometimes dramatically) the unmeasured cost (maintenance and support). To continue to stretch the metaphor, this behavior is akin to borrowing money from a payday lender to fund a sub-prime loan. As Raymond Chen says, features start with negative points and need to clearly prove that they are worth the cost to implement and maintain. Development should feel empowered to say that a feature is simply too costly and therefore should not be implemented.
On the liability side of the equation, we need to strive to build systems where common libraries and frameworks can be leveraged to quickly add new functionality with minimal new code required. At this site, we have gone into detail on some of these components – most notably configuration and service infrastructure. Generally, it is wise to adopt the “embrace copy and paste” philosophy of producing reusable infrastructure that empowers your team to quickly replicate (with slight modifications) existing functionality. Of course, an investment in infrastructure is not risk-free. To build infrastructure, you must pile up a lot of liabilities that are not directly related to new assets. To mitigate this risk (and help get buy-in from management), it is wise to build infrastructure only when it is needed to support the addition of new user functionality, and to resist the temptation to gold-plate. The infrastructure can evolve and grow more full-featured as the needs arise.
Hopefully, you have noticed a clear relationship between this article and the well-established concept of “technical debt“. The goal here is to expand upon the “technical debt” concept by noting that not only is “bad” code a liability, but that all code is a liability. Code should be scored on the value it adds (or indirectly empowers, in the case of infrastructure) versus its size, complexity, flexibility, and maintenance burden. Make sure you use your lines of code wisely, and pack as much potential value into each one as possible.
Disclaimer: I am not claiming to have invented this concept. I’m trying to put my own spin on a long history of articles describing it. Hopefully I’m adding something to the discussion, and not just regurgitating others’ ideas. Feel free to join the conversation in the comments.