“Software is eating the world”. In his famous article written in 2011 Mark Andreessen wrote that “we are in the middle of a dramatic and broad technological and economic shift in which software companies are poised to take over large swathes of the economy”. He expected many more industries to be disrupted by software and was proven right. With recent breakthroughs in AI, we have not seen the end of all disruptions.
Mark Andreessen argued in favor of investing more heavily in software, recognizing the business value delivered. While the business benefits of software solutions are often recognized, software is expensive to create. Each 5K to 10K lines of code costs roughly 1 FTE to create. An average iphone app easily takes ~10-50K lines of code, a modern car uses 100M lines of code (source: code base sizes).
Software is also expensive to own. Even if there is no need to change functionality, the environment of the original software is subject to continuous change. New operating systems break functionality that worked perfectly for years. New hardware, even with the same features, requires software engineers to incorporate new drivers. With novel ways of breaching security, parts of the software need to be rewritten to be made secure. In my experience each 50K-200K lines of code needs roughly 1 FTE of maintenance on a yearly recurring basis.
If you have a 10 FTE team, creating between 50K and 100K LOC per year, you also have created the recurring need to sustain that code over the life time of that software. The first year, the team is super productive. The 2nd year they need part of their time to maintain the code they created in the first year 1 and so on. If you assume that maintenance is a function of code size, your innovation speed will move to zero! (i eleborate more on this in the gardeners dilemma)
There are several factors that make your code size larger than needed:
- Over-production: Some engineers are more verbose than others. It takes skills, time and review to create concise software. As Mark Twain said, “I didn’t have time to write a short letter, so I wrote a long one instead.”
- Over-abstraction: Software engineers may ‘over abstract’, e.g. create code that is highly configurable or create frameworks for reuse for future use cases. While this can be a real business requirement, it is often not required to meet the business needs. Code that needs to be configured or reused is more verbose than code tailored for specific use.
- Over-processing: Event based / asynchronous architectures are more verbose than a synchronous architecture. Not all real world problems require an asynchronous architecture and I believe the pattern is overused. Asynchronous architectures in addition may generate unnecessary runtime dynamics, creating expensive and difficult to diagnose quality problems.
- Over-branching: Business pressure is always high and many project teams need to enhance the same code at the same time to meet a deadline at the same time. So: what does the project leader request? Independence! I need my own branch and I need it now! Of course this introduces overhead of merging. Merges are expensive and complex. The split likely created the need to support more product variants. And there is a good chance that the code in the different branches when created in isolation is more bloated than when designed holistically.
As the years go by, not all requirements that the team originally was asked to implement are still required. Software technologies that once where ‘hot and new’ are now obsolete and novel paradigms allow you to express the functionality in a more concise way. Often, software stacks contain abstraction layers that have lost their value. As a result, most code bases are much larger than needed. I gave examples of code that is bloated but still functional. It is also possible that the code stack contains code that is not in use anymore at all (dead code). While seemingly harmless, reusing dead code in a new context can have substantial adverse business effects. For an example, read this interview with Kevlin Henney who argues that dead code needs to be found and removed.
The more code you have, the more errors you have. This does not scale in a linear way. If you double the code, you more than double the errors.The end effect of writing too much code is that you spend more time on maintenance than necessary and do not give your stakeholders enough of what they need.
How to break the negative spiral? The first step is to recognize the importance of monitoring the size of your code. You need to embed this in the team culture. Establishing a ‘minimalistic code’ culture will keep your teams in control of their code base. They can spot unexpected code size increases and challenge themselves on finding opportunities to reduce. Setting their own targets will stimulate teams to find and remove dead code where possible.
For larger code sizes this is a multi-year endeavor. But starting the journey can save many FTE’s in maintenance. Here are some of the methods I have seen succeed in reducing legacy code size:
- It starts with asking. Most software engineers have a good sense where the code stack is bloated.
- Measure your requirements and test coverage. Putting your code under test is the 1st step to reducing code size with confidence.
- Recover models from legacy code. Read this interview with TNO ESI’s Arjan Mooij to learn more.
- Raise the expressive power of the code: Use domain specific languages (where applicable) to express your intent in the most concise way.
- Use model-driven software engineering tools like Verum’s dezyne
Software is eating the world. But maintaining a legacy software code base that is larger than needed is eating your innovation speed.You need a code size down target for your team!
- because you need the innovation speed
- because you need the increase code quality
- because you need an healthy engineering culture
Please let me know successful ways you used to reduce your code stack!
(Reblogged from https://www.linkedin.com/pulse/why-your-team-needs-code-down-target-dirk-jan-swagerman/)