How to Get Coding Standards Right (and Wrong)
Editorial Note: I originally wrote this post for the NDepend blog. You can check out the original here, at their site. While you’re there, download NDepend and give it a try!
Nothing compares with the first week on a new job or team. You experience an interesting swirl of anticipation, excitement, novelty, nervousness, and probably various other emotions I’m forgetting. What will your new life be like? How can you impress your teammates? Where do you get a cup of coffee around here?
If you write code for a living, you know some specific new job peculiarities. Do they have a machine with runnable code ready on day one? Or do you have to go through some protracted onboarding process before you can even look at code? And speaking of code, does theirs square with elegant use of design patterns and unit testing that they advertised during the interview process? Or does it look like someone made a Death Star out of bailing wire and glue?
But one of the most pivotal moments (for me, anyway) comes innocuously enough. It usually happens with an offhand comment from a senior developer or through something mentioned in your orientation packet. You find yourself directed to the coding standards document. Oh, boy.
At this point, I start to wonder. Will I find myself glancing at a one-pager that says, “follow the Microsoft guidelines whenever possible and only include one class per file?” Or, will I find something far more sinister? Images of a power-mad architect with a gleam in his eye and a convoluted variable name encoding scheme in his back pocket pop into my head. Will I therefore spend the next six months waging pitched battles over the placement of underscores?
Ugh, Coding Standards
In this post, believe it or not, I’m going to make the case for coding standards. But before I do so, I want to make my skepticism very clear. Accordingly, I want to talk first about how coding standards fail.
Based on personal battle scars and my own experience, I tend to judge coding standard documents as guilty until proven innocent. I cannot tell you how many groups I have encountered where a coding standard was drafted, “just because.” In fact, I’ve even written about this in the past.
The Morale Trap
Probably the most obvious failure scenario that I see is the “coding standards as cudgel” one. In this situation, a strong personality or an “in-crowd” within the team uses the standards documents to bash everyone else into submission. The standard becomes not a means to any end, but an end unto itself.
When this happens, it can have a brutal effect on the team’s productivity. Friction and contentiousness mount. Morale for members of the team tanks. People feel that their jobs are overly-regimented and lack any need for creativity, leading to behaviors associated with learned helplessness. No amount of code readability can make up for this.
The Cargo Cult Trap
Part and parcel with learned helplessness becomes what I think of as “the cargo cult trap.” With an overzealously created, massive standards document, the team comes to worship at the altar of process. The standards document provides the illusion of guidance in all situations, and gives the team an inappropriate sense of air cover.
Oh, there’s a bug in my code, huh? Well, that’s unfortunate, but I did follow the standard, so I guess there was really no avoiding it.
Obviously (hopefully), nobody would be quite that obtuse, but you get the idea. When you have prescriptive guidelines for every conceivable scenario, successfully following all of those guidelines becomes the team’s main charter and challenge. This holds doubly true if the response to every bug is to mark up the standards document so it never happens again.
The Busywork Trap
The final, and perhaps least insidious, trap that I’ll mention is the busywork trap. Unlike the morale problems and outsized trust in the standards, this trap offers minimal outright damage. Instead, you have simple waste. This also probably occurs most commonly.
In this scenario, the coding standard is created and maintained, but ignored. Or perhaps the team does not entirely ignore it, but only selectively applies it or else only some of the team pays attention. Another, similar, situation occurs when the team lays out standards and guidance for rare or nonexistent situations.
I mention this trap because I’ve found it to be the most common. The team makes a good faith effort at standardizing, only to have that work largely go to waste.
So Where Does It Work? Where It Solves a Problem.
True to my word, I’ve certainly hammered on the “guilty until proven innocent” theme. I do this because I believe that prescriptive instruction (like coding standards) should happen not by default, but only to address a gap or shortcoming.
Has the team consistently introduced bugs and wasted troubleshooting time because half of the team uses an underscore prefix to mean one thing, and half another? Do newer members of the team consistently make a correctness or performance mistake in the code? Have folks consistently introduced dependencies between projects that create deployment problems?
If you have situations like these, then standardizing helps. Let a standard evolve out of need; you shouldn’t adopt one as a preventative measure.
Build a System
And that brings me to my final point here. I’d also argue that this may serve as the differentiator between my thoughts and those of others writing on the topic. If you must have coding standards, you need to automate them as much as possible. Automating them provides so many wins and inoculates against some of the traps.
A colleague once told me that it’s best to break bad news by building a system and blaming things on the system. As a consultant, this has proved immensely valuable to me, and it applies well in the domain of coding standards.
Coding Standards in Code, Not Word
If you really can’t stand camel case or brackets on new lines or whatever, don’t send nasty emails or get into arguments during code review. And don’t keep the standard in a Word document. Instead, add something to your build that fails or prevents checkins of code that fails to comply. Then it’s no one on the team holding judgment, but the tool.
This avoids contentiousness and it allows for a tight feedback loop. The team learns, and adopts new norms quickly. It also tends to put to bed (to some extent) religious wars about the standard via a manifestation of squatter’s rights.
What’s more is that automating the standard requires effort, so it tends to put a damper on cargo-cult standard adherence and busywork both. (Within reason) You’ve really got to want it to go into the build machine and add automation to boot a build back to the committing developer. That’s harder than sending an email or updating a document.
I mention this on the NDepend blog because I find NDepend to be invaluable in creating systems like this. It can effortlessly transcend considerations that are both cosmetic, like naming, and design-centric, such as rules about semantics and architecture. Not to mention that its CQLinq makes the possibilities virtually limitless.
NDepend is, in my opinion, the best tool for the job. But whatever tool you use, be sure to use a tool. Coding standards can help you eliminate repeat mistakes and create more maintainable code. But make sure that the medicine isn’t worse than the disease — make sure you automate.