A single broken window is all it takes for a building to quickly transform into a decrepit abandonment of graffiti, crumbling walls, and many more broken windows. And software is the same.
A friend recently gifted me a book called, The Pragmatic Programmer, and it mentions the broken windows theory in Chapter 1. I’ve heard the concept before but it never occurred to me to apply it to software, although now that I think about it, it makes a lot of sense.
If you don’t know what the broken windows theory is, it goes like this: If a single window in a building is broken and left unfixed, that building will soon have all of it’s windows broken.
There are a few theoretical explanations for why this happens.
The actual theory is a little extreme in my opinion by labeling persons who litter or break windows as criminals and following the trajectory all the way to murder and other terrible things. But one factor is called social norms and conformity. Basically a well kept, orderly neighborhood sends a signal to people that the area doesn’t tolerate criminal activity. So criminals are less likely to be unlawful in the area.
A broken window left unfixed is a signal to criminals that the community lacks cohesiveness or care, which makes criminal behaviour, like littering, spray painting walls, breaking more windows or much worse more likely to happen.
I’m from a small town of 30k people in the middle of rural Ontario so the extremities that the theory goes into are just outside my world a bit, making difficult to relate.
But I remember being a kid, and it was a common thing for us to throw rocks at the old Cooper building by the skate park. Some of the windows were really high, so at age 11, being able to throw a rock high enough with enough force to smash a hole through the glass was like a right of passage.
But there is no way we would have done that if the building wasn’t abandoned! We weren’t criminals! Or at least we didn’t see it that way. We were kids who saw a signal. The signal was, “it’s ok to throw rocks at these windows” so we did.
The Pragmatic Programmer probably does a better job at explaining this than me. But in simple terms, entropy is the tendency for things to decay over time. And software is not immune to it, as I’m sure we’ve all experienced.
Some times we call it code rot or technical debt. Both are different names for the same thing and they’re what happens as software ages. The more developers come and go off a project, the more code changes are made, the more features are added, and requirements change the more mess ends up in our code.
We end up with documentation that’s out of date, copy pasted code that doesn’t get cleaned up, unused temporary variables, magic numbers and strings. We end up with half-baked ideas, we do the same thing in 3 or 4 different ways depending on the age of the code you’re looking at. Tests get skipped or left failing and parts of code become to coupled which makes testing harder and change riskier. Bugs get left unfixed because they’re too difficult to track or understand.
There are a ton of resources out there on technical debt and how to avoid it. We can learn how to communicate to management and stakeholders what it is for one. We can practice good software design principles, refactoring and TDD.
But the idea of broken window theory is that non of this matters if we allow broken windows into our code and leave them unfixed. And this is just a connection I hadn’t made until I started reading this book and it really resonated with me.
Girl and boy scouts are taught to leave a campsite cleaner than when they arrived. Good programmers are taught this too. I’ve always just practiced the girl/boy scout principle thinking that it was a good way to gradually clean up legacy code. But I think it’s deeper than that.
It’s about fixing broken windows. Because if they’re left unfixed for too long, other developers are more likely to break them too. The broken windows are signals that communicate it’s ok to leave this code undocumented, or this really long method, or this return type untyped for now because I can’t figure out TypeScript.
It’s easier to let quality slip when there are signals around you telling you it’s ok.
I’ve seen this happen on basically every project I’ve been involved in, which is more than I can remember off the top of my head. We need to avoid broken windows.
And we can’t always prevent broken windows from happening. But we can make sure as a healthy, cohesive team, we work together to fix them as soon as possible.
A broken window in software is really anything we know as a code smell, management smell or really anything we’re not proud of. And this doesn’t have to be issues with just the code either. It can be issues in our CI/CD pipeline, development processes or management too.
I want to focus on just the code since it’s what most developers have the most agency over.
A broken window in code can be as simple as formatting code one way in one part of the project, but over in another it’s formatted another. As soon as a developer comes across that, they’ll stop caring about consistency. White space changes in PR’s will become a constant, and people will probably complain or get frustrated or argue until they just stop caring.
It can be larger than that too. It can be things that are more difficult to solve like an unideal design, or leaving an implementation too complicated.
Really anything that is considered a code smell is a broken window. I’m cautious about labeling anti-patterns as broken windows since some of them can be debated and justified on a case-by-case basis but if your team unanimously agrees that a pattern is anti 🐜🐜🐜… then leaving it unresolved is a broken window.
So is there anything we should start doing differently?
I first want to say that I believe in not allowing perfection to be the enemy of good. I’m not about to go off the deep end and start over engineering and abstracting everything because I suddenly have a zero tolerance for broken windows in my code.
I don’t want to be that guy.
That said, I think it gives me a new perspective why things like code linting and formatting are so important. And they’re easy things to implement so we should just always have those things set up.
I also will start thinking a bit more about the code I leave behind. I’m always doing a cost-benefit analysis when I decide to leave a chunk of code as-is when I’m not 100% happy with it. But now I have a new thing to consider when I do that analysis. Is this a broken window? How will this effect the quality of the code the next developer writes? How will it effect the quality of the code I write the next time I see this?
What do you think? Did you already think like this? Or is this a new perspective? I’m curious to learn how this will or has effected the decisions you make when you leave code behind. let me know in the comments! Or tweet me, my DM’s or always open!