Dark Corners and Social Forces
Last week I argued that because bugs hide in dark corners — that is, using tools in unusual ways tends to break them — there is social pressure on developers to avoid those corners. One important form of such pressure is stylistic restrictions, sometimes called "best practices." Such restrictions are sometimes imposed by tools that examine programs for violations, sometimes by code reviews, and sometimes in less formal ways.
An example of such a restriction might be: Never use an assignment as a condition. An example of a violation might be
if (n = f()) { /* do something */ }
It should not be hard to see what's wrong with this statement. As written, it assigns the value of f() to n and then compares that value with zero. However, its form suggests that its author might have intended to write
if (n == f()) { /* do something */ }
which compares the value of n with the value of f() without changing n. This second form is much more common than the first, which tempts the reader to believe that the author made a mistake.
It is probably wise to avoid using assignments in this way. However, if an organization elevates such avoidance to a formal rule, it creates new problems that I think may not be widely appreciated.
To see where the problem lies, consider a programming shop with a rule that all programs must compile without warnings. In effect, such a shop is telling its people not to program in C++, but rather to program in a dialect of C++ that is restricted by the compiler. Worse, the dialect is defined by a particular version of the compiler.
What happens if a new version of the compiler comes out with a warning that previous versions did not have? Now in order to comply with the no-warning rule, developers may have to change large amounts of code to avoid the new warnings. How many new bugs will those changes introduce?
There is another hazard of programming in socially-imposed dialects: In general, different organizations will have different dialects. As a result, it is possible that when one organization sends code to another, the recipient may have to change that code in order to conform to local standards.
In short, by trying to avoid dark corners altogether, we have redrawn the map of where we can travel — but we have done so differently for each different programming community. Instead of one well-defined language, we are now programming in many vaguely-defined languages.
At this point, you may be expecting me to decry this situation and argue that programmers should always feel free to program in whatever style they choose: After all, what is the point of a language standard if it doesn't define the language that we use? But that attitude won't work either, because obscure coding is more likely to encounter compiler bugs .
I think the most workable alternative is to let usage inform judgment: If you are thinking of solving a problem in an unusual way, you should have a reason for doing so. The more unusual the solution, the stronger the reason should be. As happens in so many other context, the choice of how to express ideas should be a trade-off among conflicting advantages and disadvantages, rather than a list of inflexible rules.

