July 27, 2006

Programming: Language and Thought

Programming is a difficult art to do well. I don’t mean the high level design or the specification of implementation patterns to use, I mean the actual “let me type up the implementation of this single procedure” effort. The problem lies in the need to have both structured, repeatable, consistent patterns of consideration and thinking, while simultaneously having a set of mental processes that lend themselves to innovation and unconventional insight. There’s the added difficulty caused by the fact that programming is often iterative in nature … you might add the portions of the code here, expect there to be interaction over there, and have to come back here to change things around based on behavior and expectation there.

Setting up a template of things to consider doesn’t work for many reasons, not the least of which is that, for the template to be useful across the board, it would have to be so generic and abstract that the concrete specifics of how to use it in a particular circumstance would allow the programmer so much flexibility that he’d dismiss the template entirely (which he would be inclined to do, since a template of what to think about would be offensive to him and his expensive training). Besides, if you have a template of steps to consider, you allow yourself to be constrained by that template, and innovation suffers.

Frankly, there is no solution. However, there are things that can be done to improve the situation by nudging the programmer’s mind in such a way that he considers certain aspects as part of his normal (and possibly unique) programming manner. The key is language and its use.

Words are referents that point to concepts. When you use a word, you’re indicating to a person that they should consider aspects of the concept. Multiple words might refer to the same concept, but indicate that different aspects of the concept should be considered relevant (this is one of the reasons that accurate use of language is important to unambiguous communication.) The structure of the language can also indicate a particular contextual framework in which the referred concepts should be evaluated.

Similarly, if you force a programmer to consider the language he is to use, or the structure he is to use, you can nudge his thought processes in such a way that he considers a particular necessary aspect of coding that he might otherwise overlook. As such, the person responsible for establishing a company’s (or API) coding style must consider areas in which he can provide this nudge. I’ll provide a few examples (please note that these are _examples_, and I will not enter into a debate about whether my particular example is the right or wrong way to do things.)

Classes, in general, reflect a conceptual entity. Therefore, classes should be named with the noun or noun phrase part of speech. By doing so, the programmer is forced to envision the thing and its intended context. Not only does this cause the programmer to more thoroughly evaluate that context (project business processes) allowing the team to identify deficiencies in specification, and also allows him to identify a meaningful hierarchy of related concepts such that a class hierarchy can be defined, but it also makes it easier for him to keep a mental image of the entity being modeled in mind as the coding proceeds.

Properties and methods have their own requirements and naming styles that can lend themselves to better development style. I’ll address these in the comments if necessary, but otherwise I’ll leave it as an exercise to the reader.

The Microsoft Visual Studio environment allows a developer to construct code “regions”, which are just delimited areas of code identified by a common name (with the ability to collapse everything down to a single node identified by that name.) If the coding standards require regions based on the access type of a particular property or method (e.g., #region Protected Methods), that reminds and encourages the programmer to evaluate what access level is actually appropriate, since recommended practice requires that you use the most restrictive that is reasonable.

There are times when resources must be closed or explicitly released (in the case of interacting with unmanaged code or GDI objects, given a few Microsoft GDI leaks), but programmers will frequently forget to consider this. If your coding style always requires that every code block be put in a Try … Finally structure (given that the Finally block is usually where you want to do that kind of clean-up), then the programmer is reminded in every procedure that he should evaluate whether that kind of clean-up is necessary. You don’t want it to be a Try … Catch or Try … Catch … Finally block, because this would encourage the programmer to unnecessarily handle exceptions, and this is not recommended practice.

Keep these techniques in mind, and consider them when documenting your own coding standards guides. Comments of other suggestions welcome, of course.