The Broken Windows Theory
2/Oct 2011
The broken windows theory is a criminological theory first introduced in 1982 article by James Q. Wilson and George L. Kelling. The gist of it is given in this example: “Consider a building with a few broken windows. If the windows are not repaired, the tendency is for vandals to break a few more windows. Eventually, they may even break into the building, and if it’s unoccupied, perhaps become squatters or light fires inside.”
I have first found out about it when reading about zero tolerance policy in NY in early nineties. Some studies claim it was one of main reason for sudden drop of crime in NYC during Bratton/Giuliani era (if you’re interested in one of alternative theories - read Freakonomics, not sure if it makes more sense, but surely is more entertaining).
If you think about it, similar analogy can be applied to software. We start with a clean plate and build something from nothing. Everyone has seen examples of mature code bases. Do you think their current shape matches the initial plan?
I’m sure that everyone starting a new project have great hopes for it. It’ll be fast, clean & elegant. It usually is, for some period of time. Alas, as I mentioned before - code seems to have an expiration date, eventually, it rots. In the worst case, codebase becomes so riddled with hacks and workarounds it starts to crumble under its own weight and self implode. I’ve seen it happen a few times, old code has been pushed so far, it became almost unusable, you touch one place and it affects ten other areas. Now, it might not always be a tragedy. Code served its purpose, you probably cannot realistically expect to use same engine for 20 years. If you managed to shipped several titles, you should be happy, but maybe the time for more radical changes has come?
Let’s rewind a little bit, though. What can be done to prolong our code’s life? Why does it rot in the first place? Well, it starts nice & clean, but sooner or later, someone breaks the first window. If you don’t fix it quick, whole thing will slowly start falling apart. If your code base is messy, there’s less incentive to try & write the clean code (shouldn’t matter in the ideal world, but oh well, that’s human psychology for you). If there’s a 100 of hardcoded values, surely adding a new one doesn’t make things much worse, right? No one thinks about header organization, so instead of trying to consider if you can get away with forward declaration, people will just include everything. Now, if build time goes from 15 minutes to 15:30, it’s still harder to notice than 2 minutes -> 2:30 (that’s assuming someone actually times it). The list goes on.
One thing that seems to help is introducing layers. At the very bottom is project independent code that hopefully will be re-used. As we go up, code gets more & more specific (ie. system->engine->general game->specific game) and at the very top we have code that’s unique and most probably will never be used in its current shape. It’s obviously more important to keep the bottom clean, we care less about game specific stuff. This means, if you really have to hack it, at least try to hack it at the highest level possible, so that it affects as little modules as possible. Definitelly, do try to avoid introducing game specific solutions in lower levels. There’s a funny story in this Tony Hawk post mortem – it’s built on Apocalypse engine, game featuring Bruce Willis, so the code for the classes of skaters in Tony Hawk is called “CBruce”. Now, that’s just naming, I could care less, but it pictures what I’m talking about. I worked with engines where mana meant ammo, just because the first game done was an RPG (took me some time to figure this one out).
Other thing you can do is copying Bratton and introducing a zero tolerance policy. Now, we obviously shouldn’t go crazy here. Remember that the most important thing is still shipping a good game, not winning some code beauty award. If you have to take shortcuts - take shortcuts (…hopefully in one of the higher layers), code elegance is still just a mean, not a goal in itself. I still think most companies are a little bit too lenient when it comes to code quality. It’s hard to find the right balance, but it’s definitelly worth trying. Low hanging fruits:
static analysis,
dependency analysis (avoiding circular dependencies, lower layers depending on higher layers etc),
build time/size analysis,
automatic performance analysis
Those are areas which can be easily controlled automatically, but you won’t catch sloppy code this way, it requires a little bit more effort. One way to do it - code reviews. I know, touchy subject and I’m using it in the widest sense possible. It doesn’t have to be formal, scheduled, it doesn’t have to affect very checkin. If you’re interested in a more formal approach, check out altdevblog articles by Lee Winder - first one here, follow from there. It’s especially important with junior programmers/new hires. Not because they don’t know how to code, more because they’re not familiar with your engine and practices. When I first joined DE it took me some time to switch to their way of doing things. Having my lead show me what’s the more natural way to achieve what I wanted in their engine was really helpful. Knowing someone might have a look at your checkin has also an important effect of knowing he actually cares, you’re not in the wild and prevents you from getting sloppy. Ideally, it’s a team effort, if you notice a change that you think could be done in a better way – go discuss it with the author (one of you probably missed something). Ignoring little efficiencies and hacks from the very start usually results in lots of tears, hair loss and flat profiling graphs, where nothing seems to stand out yet the game runs like a dog (aka death by a thousand cuts).
Finally, as obvious as it may sound – it’s harder to break windows if they’re not there. In other words – make it difficult to break your code (yeah, easier said than done). Codebases get more complicated as they grow, so start simple. Remember also that usually new programmers will try to code in style similar to what’s already there. If it’s boost-like, their code most likely will be riddled with crazy constructs as well. Do not go crazy with generalization, it usually ends pretty bad and adding even the simplest feature means implementing 5 interfaces and handling 10 callbacks. For me, one of the most satisfying feelings is discovering I can extend/add new stuff just by making minimal changes to what’s already there.
Every code base starts simple & clean, how it’ll look after few years is affected by many factors. One of them is how you react when the first stone is thrown.
Old comments
admin 2011-10-05 01:37:29
Great minds think alike, eh? :) Actually, it’s a little bit embarassing, but after writing this article I found at least two others with roughly the same theme:
http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html,
http://pragprog.com/the-pragmatic-programmer/extracts/software-entropy
Hopefully this means there’s something to it.
Pierre 2011-10-04 15:56:58
Hehe, I’m glad I’m not the only one who mentions applying the broken window theory to code: http://www.codercorner.com/blog/?p=237
Arseny Kapoulkine 2011-10-03 17:13:28
Great post, thanks!
For me one of the most satisfying feelings is committing a -1k+LOC CL that adds new features/improves perf :)