During my short career as a software engineer, I’m often surprised that many people in the industry are unaware of rules of thumb—heuristics— managers and programmers have discovered to better navigate almost any situation.
There’s always that new story about a team that was very cooperative but broke down and became hellish once it grew too much. Or your friend telling you a story of a surprising bug that took hours to solve and it turned out the solution has just a couple of lines away from where the code was edited last. And, of course, since most teams always operate under strict and unreasonable deadlines, there comes a time when the codebase becomes an untameable monster that only a few team members can vanquish.
But, even though Software Engineering is a recent discipline, there are many useful such heuristics that all programmers and managers alike should know and keep in mind.
What follows then is an (incomplete) recollection of anecdotes of my experience in a variety of software projects. I chose a set of rules that I’ve found over and over and will try to make sense of them in light of my experience.
Brook’s Law: Adding manpower to a late software project makes it later.
Brook’s law is the subject of his famous book “The Mythical Man-Month” . This is arguably the most important law in any project that involves communication and interactions between different people. But it is one that more often than not goes unnoticed. Humans are fallible and we believe ourselves to be better than average or to think that certain laws or rules don’t apply to us. Reality usually bites back.
I first saw this law in action during my first startup stint. As the company struggled to find some semblance of a product-market fit, we accelerated our pace but things were not done in a timely or planned manner. Aggressive dates and deadlines were given to investors putting a lot of pressure on the small engineering team. Being under pressure and struggling to find a clear path forward, the executives decided that what the project needed was more people to go faster. So, overseas contractors were hired.
You already know what happened next. The project had to be delayed. The newly added manpower needed to be trained and introduced to the team. New interactions meant new and more meetings.
Remember cooperation works but it is very hard to scale. As teams grow the time to manage it increases exponentially not linearly with each new member.
A good counter-example to this is Amazon’s “two-pizza teams”. By following a simple heuristic, Amazon tries to keep teams small and independent at all times. If a team can’t be fed by two pizzas, then it must be broken down. This ensures that the complexity of managing the team is kept to a minimum and progress can happen faster.
**The Law of Increasing Complexity: Complexity increases and structure
deteriorates under change.**
“This is the second law of thermodynamics applied to software systems."* - * Adrian Colyer**
Refactoring, the process of changing a program’s internal structure without changing its external behavior in order to organize it and make it more readable, is a practice that all programmers like but that most managers hate.
Why? On the one hand, refactoring helps reduce the entropy of a project. After many iterations, a program usually grows disorganized and chaotic. So refactors help to organize and bring back order into the program.
On the other, refactors take time and they need to be done multiple times during a project’s life. Hence, managers try to avoid them as much as possible. In their eyes, refactors don’t contribute to the end goal of a project.
But, delay refactors for too long, and the code will be harder and harder to read, entropy—disorder—will inevitably grow. The project will become difficult to navigate through. Programmers' frustration will grow. They will spend more time finding their way around the code than on actual coding. The team’s pace will inevitably slow down.
I’ve seen this law in action on two occasions. In both cases what started as a prototype ended up as the actual code serving customers. This, paired with the pressure the team had to ship more features, meant that there was no time for refactors. The codebase grew untamed like a wild vine grows if not trimmed. In the managers' view, there was no time for it. The project grew and grew until it became a sort of monster that only a couple of programmers in the team were able and brave enough to tame.
Failure to understand this law can mean disaster over the long run of a project. As the complexity grows, programmers will become more and more dissatisfied with the code to the point where they might not want to keep working on it. Managers will face increased friction and things will inevitably become slower. Some programmers will burn out and will switch projects, change teams, or leave the company altogether.
If not tamed, the Law of Increasing Complexity can mean the end of the project itself.
**Joe’s Law of Debugging: All errors will be plus/minus three statements of
the place you last changed the program**
I first came across this on “Coders at Work” by Peter Seibel. We must consider different types of bugs: those that arise during development because of a mistake on the programmer’s implementation of logic and those that appear after extensive use by users.
The first kind typically includes those functional bugs that suddenly appear just after a new release. In fact, the first thing I do when these bugs arise is to fire up an older version of the program. If the bug is not there, then it was introduced by the latest changes and that’s where I’ll look next. In almost all cases the bug is there, in the vicinity of the statements that you last wrote, edited, or deleted.
The second kind mostly evades this law. These can be bugs that for months or years go unnoticed and when they appear they are usually in obscure and old parts of the codebase.
While this law is very simple it is also very powerful. In my experience, it is all too easy to spend endless hours debugging a program without reflecting on where the code was last changed. Bear this in mind the next time you’re tasked with debugging a program.
As you embark on your next project, think about these laws. Most, if not all, will apply at some point. It seems almost inevitable and part of a project’s lifecycle. Software projects are always evolving and teams are usually in a rush and under pressure because planning and estimating work are hard.
As with all laws and rules though, don’t follow them blindly. Read about them, learn to recognize them and you might be able to keep your project going in the right direction most of the time.
- Programs, Life Cycles, and Laws of Software Evolution
- Laws of software evolution revisited
- Coders at Work
Thanks to John Lanza for reading and suggesting edits on drafts of this post.