Sooner or later, every software engineering organization is faced with the task of trying to evaluate the productivity of their team and the performance of its members. And invariably, the conversation turns into a discussion about whether, or how much, to measure code output as an individual productivity metric.
In the best case, this metric could be one dimension, of hopefully several, used to evaluate some classes of engineers — certainly more junior ones. In the worst case, it sets a perverse incentive that tracks negative value to the business.
I like to use this analogy: the objective of any state Department of Transportation is to provide a system that allows goods and people to efficiently move from one place to another. Highways cost money to build and maintain, so ideally these goals can be achieved with as few miles of highway as possible. Incentivizing more roadways independently of needs would be a waste of taxpayer funds.
Ultimately good software meets its requirements at the lowest overall cost, which usually correlates to the least amount of implementation code necessary. More code means more development, more code review, more human coordination, and more defects.
Computer scientist Edsger Dijkstra once said, “If we wish to count lines of code, we should not regard them as ‘lines produced’ but as ‘lines spent’.”
Dijkstra is saying that code is an expenditure. It’s a cost in terms of the time taken to write, test, deploy, and maintain, but also a cost in terms of the mind space it occupies in engineers’ brains — or the time it takes to understand it later after its writers have moved on.
A few points make this more clear:
- Is it possible that engineers produce lots of output but the team fails to meet its objectives? Yes.
- Would your team prefer to meet its objectives but own half the code to do so? Yes.
- Would we prefer to integrate a useful third-party library into the project, rather than trying to manually replicate its functionality in code? Yes.
- Do software design principles like modularity, reuse, and abstractions reduce the LOC necessary to meet an objective? Usually yes.
Code is powerful but ultimately a liability. The capabilities of the software are what bring value.
Good software architecture and design de-risks eventual implementations — their timelines, reliability, and cost. This is often through designing or sharing reusable components, isolating modules behind well-defined interfaces, and ensuring solutions strike the right balance between representing the problem domain and abstraction. Sometimes this results in the leverage of third-party or open-source code.
Poor design and a lack of coordination tend to result in fragmented, duplicated implementations across teams, which increases the overall maintenance burden for the organization and imposes heavy migration costs in the future.
Ultimately the goal of engineering teams is to meet the functional and non-functional requirements of the system at the lowest cost — and that usually means producing the least amount of code possible.
Risks associated with relying on code contribution are usually well-known, in spite of the fact that LOC and contribution measurement are cyclically popular. It can lead to:
- Inflated LOC change volume, from engineers trying to boost their own metrics
- Decreased collaboration, as engineers try to hoard implementations to themselves
- Neglect of work not directly coding: documentation, design, testing, code review, mentorship, and planning
- Poorer code reuse: the incentive exists to duplicate common capabilities, not to leverage them
All of these aren’t as good at producing quality code as much as they’re good at producing technical debt. The irony of this approach is that it creates an environment where increasing amounts of code are necessary to get anything done over time.
So what could be measured? Outcomes.
Setting quarterly+ goals (or OKRs) for engineers around the delivery of important outcomes, and measuring regular progress against them via project milestone delivery and peer feedback is the most reliable method I’ve seen.
Some of these goals or OKRs should ladder up to those of the team. This establishes a chain of impact lineage all the way up to leadership. If this system isn’t in place in your organization, well, that’s a whole separate post.
Code by itself has little intrinsic value. Relying on a metric just because it’s easily measurable is a distraction from the real evaluation: Are we getting done what needs to get done to succeed?
The value of code was originally published in Better Programming on Medium, where people are continuing the conversation by highlighting and responding to this story.