Every time a developer writes code they make decisions and trade-offs. They balance deadlines vs test coverage, security vs usability, performance vs code readability, and a myriad of other factors. Which leads to the question: is there some overarching factor they should optimise for?
Ask developers or the broader business itself, and you will generally get personal preferences or some notion of maximising the value to the business. Defining and maximising business value is critically important. Communicating what the business currently values and giving developers a framework to make those decisions is the primary role of technology leaders in any organisation.
If you delve into defining value, even deciding the right balance between short and long term value is a subjective minefield. The trade-off is effectively how much technical debt do we accrue vs the uncertainty of product market fit and the acceptance that your v1.0 is the first (imperfect) step towards maximising business value.
So how do we even start to quantify all these factors to determine a guiding principle for our developer, who is making all these decisions each day?
Letâs start with trying to measure software that is unequivocally delivering value to the business. Suppose we accept that âmatureâ software has not only had all the bugs, performance and security issues worked out, but has also found product market fit. In that case, we can consider mature software as software that is delivering value.
At AgriWebb we phrase this as: âYour code should be a love letter to the next developer.â It is the creed that a developer should use when making all those daily trade-off decisions.
David Horne CTO, AgriWebb
The most effective measure I have come across to quantify this is the code churn ratio as expressed by Yevgeniy Brikmanâs 10:1 rule. That is the number of lines of code that have been written and deleted to produce the current codebase, with the nice round 10:1 ratio being arrived on for mature software. That means that for every line of code currently in your master branch, 10 lines will have been written and deleted for the software to be mature and have reached a value delivering equilibrium between all the factors.
To quote from Brikmanâs article in relation to analysing the MySQL repository: âThatâs 58,562,999 lines of code churn to produce 3,662,869 final lines of code, or a 16:1 ratio for this ~23 year old repo. Wow! Roughly speaking, every single line of MySQL has been rewritten 16 times.â
So that is our baseline number of iterations it takes to reach a level of correctness, performance, security and product market fit that is producing value for the business: typically a code churn ratio of around 4:1 for a v1.0 and 10:1 for a mature codebase.
How does AgriWebb stack up? Across all our key repositories we have 1,412,670 lines of code but have written 11,261,374 in total, equating to a code churn ratio of 8:1. Woohoo, we are almost mature! At a repository-specific level, the metric checks out against what we see running the software day to day. Our billing system has a ratio of 17:1, and in practice it chugs along and does itâs job. Our event sourcing system has a ratio of 8:1 and while it is a core component of our system it is very much still a work in progress. Our mobile app has a ratio of 6:1, so still a way to go, which is reflected in the support cases we get from the mobile app.
Yay, software metrics that work! But how does this help us in our day-to-day trade-offs as developers? Let me answer that with another rule of thumb ratio, one from Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin: âthe ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. âŚ[Therefore,] making it easy to read makes it easier to write.â
In my personal experience it is likely higher than this, especially in an evolving codebase that is being actively refactored, but 10:1 is accurate enough to use and is a nice round number to boot. We have established that we write 10 lines of code to get to 1 line that actually delivers value, and that to write a line of code we need to read 10 existing lines of code for context. Meaning that we read 100 lines of code to ultimately produce 1 line that is delivering value.
Therefore, irrespective of how we define value and whatever other factors we want to consider, we should overwhelmingly bias towards code readability in any trade-off.
At AgriWebb we phrase this as: âYour code should be a love letter to the next developer.â It is the creed that a developer should use when making all those daily trade-off decisions.
As each developer is writing code they should be evaluating it through the lens of the next developer to work on it (who is often their future self). We donât want the next developer to be doing a git blame muttering âwho wrote this sh*&!â (only to see their own name, from six months prior). The desired state is that the next developer is able to quickly and easily open up the codebase, understand where they need to make changes, and have everything work seamlessly once the changes are made. A great measure of this is how quickly a new hire can be productive on the codebase.
This is not prescriptive on naming conventions, formatting standards or testing practices, although they can all help. It is a guide for code reviews. If a pull request is easy to understand and it is straightforward to see the effects of a change in review, it is a good sign. If it is hard to understand then a new developer coming in without the current context and experience will struggle.
If you can easily read your codebase your team velocity will increase, your defect density will decrease and you will be much more likely to reach that value-delivering level of maturity with a code churn ratio under 10:1.
If youâd like to follow my journey at AgriWebb, you can do so via LinkedIn here.