Programming With Style
Contents of Chapter 4
4 Psychological Principles
Psychology is the science of the mind, emotions, and behaviour. Since programming is an intellectual process, it is important to study these psychological elements to get a better handle on how people learn and retain information, as well as why certain principles of style are preferred over others. This chapter will illustrate that many elements of coding style have their foundation in human psychology as well as simple reason.
Aside from being an intellectual exercise, programming is also a very inward pursuit. In other words, if you want to be a great programmer, you must assume the onus of making yourself great -- no one can do it for you! Learning to be a good programmer involves not only understanding the syntax of a language and the steps of software construction, but also having a strong cognizance of how others think. Realizing the limitations of the human brain and trying to make code easier for yourself and others to understand, with fewer misinterpretations, makes you a more considerate programmer.[Oman 93] This type of coder is a valuable asset to any project.
Some programmers would argue that studying such abstract psychological principles is a waste of time. This is definitely a misconception. Elliot Soloway and Kate Ehrlich explain the significance of analysing these cognitive factors:
It is not merely a matter of aesthetics that programs should be written in a particular style. Rather there is a psychological basis for writing programs in a conventional manner: programmers have strong expectations that other programmers will follow these discourse rules. If the rules are violated, then the utility afforded by the expectations that programmers have built up over time is effectively nullified. The results from the experiments with novice and advanced student programmers and with professional programmers described in this paper provide clear support for these claims.[McConnell 93]
After investigating the principles outlined in this chapter, the rest of this handbook will describe an easy to follow set of coding style guidelines and standards for the C/C++, Smalltalk, Assembler, Scheme, and Lisp languages.
The development of good habits is one of the reasons why this handbook is so advantageous to students new to computer programming. In life, when learning a new task, it is important to perform it properly from the start. Bad habits, practised over a period of time, become very difficult to change in the future; for example, improper hand positioning when learning to play a musical instrument.[Oman 93] As far as computer science is concerned, by understanding how to write readable code from the beginning, you will develop good programming habits early and apply them without much conscious thought. Ultimately, programming with style will become a force of habit.
But what if you are an experienced programmer who has picked up poor habits over the years? The question of how to abolish harmful practices is impossible to answer directly. If I knew the key to eliminating bad habits, I would leave the field of computer science and make a fortune writing self-help books! In all seriousness, the best advice for conquering a self-defeating habit is persistence. Many psychologists believe that it is easier to replace a bad habit with a good one, than to eliminate it entirely.[Oman 93] While reading the remaining chapters, look for areas where your code could be improved and put forth an honest effort to follow the standard or guideline proposed.
4.2 Memory and the "rule of seven"
When examining psychological factors, it is appropriate to study the human memory model; that is, how we use memory to process and understand information. Memory is important because it dictates the human capacity for dealing with complexity. Related to this memory model is an interesting law of nature known as the "rule of seven." [Straker 92]
The notion behind the "rule of seven" is that the maximum number of chunks of information that an individual can simultaneously comprehend is on the order of seven, plus or minus two. This is closely related to short-term memory capacity. Interestingly, the "7±2" constraint seems to have been applied to newspaper columns, where each line of text usually consists of between five and nine words; this will be explained further in Section 4.6.
Keeping this rule in mind, we can define the three main types of human memory.[Straker 92] First, short-term memory acts as a quick but volatile cache for new information coming in. As mentioned, for the average person, the limit of this memory is usually confined to seven plus or minus two items.
After new information is gathered in the short-term memory it is moved into working-memory. Working memory operates like the main memory of a computer, in that it has a larger capacity and often better retention than short-term (cache) memory. In working memory, the information is pattern matched and integrated into the third type of human memory: long-term. Long-term memory is like a hard disk because it can be the slowest type of storage and potentially has unlimited capacity. Understanding how this memory model works is helpful when developing coding style standards.
The model of human memory will be used to support several coding style guidelines in coming chapters. For example, it is advisable to keep as much current information as possible visible, so that someone reading your code can effortlessly refresh their short-term memory; this can be accomplished by limiting routine size and complexity.
It has also been found that when memorizing a list of items, members at the beginning (when we start with a "clean slate"), and articles at the end (when we have plenty of time to integrate them) are best remembered.[Oman 93] For this reason, when coding, it is advisable to keep the most important details at the start or end of a list rather than in the middle. For example, it is preferable to provide a detailed heading comment to explain what a routine does rather than commenting every other line throughout the code of a routine.
4.3 Pattern recognition and filtering
In daily life, humans are constantly bombarded with information from their environment. Our brains have evolved to become quite adept at distinguishing variations from expected norms. We survive by using this ability to filter the world into recognizable, established, patterns. This idea can be applied to coding, where programmers may be able to understand code written in a similar style, but may find it exceptionally difficult to understand a program coded in a different style.[Oman 93] Clearly, this is an important point in support of coding standardization.
When attempting to recognize a pattern, the brain can sometimes deceive us. For example, if we see something that is very similar to a known pattern, the brain will often distort the image to recognize it as the expected item. To illustrate, have you ever glanced at someone and mistakenly identified them because you were not looking for differences, or because the dissimilarity in appearance was small? In programming, it is easy to mistake an identifier name for one visually similar.
Words are a type of pattern. When memorizing them, humans tend to identify each word with both a visual and audio characteristic.[Straker 92] Although this close association between the two attributes of a word make it easier to remember, it can also cause problems. For example, it is more difficult to remember a list of words that sound similar, as they are less easily distinguished in the mind. When programming, it should be remembered that identifier names that not only look alike, but also sound similar, may be easily confused.
"Chunking" is the term used to describe the dominant way that the human brain tends to absorb knowledge.[Oman 93] By definition, a "chunk" is a distinct piece of information that can be filtered into one of the 7±2 slots in short-term memory. The amount of information contained in each chunk can vary depending on the expertise of the person. For example, the original author of a routine may be able to read a complicated expression as one chunk, while a new reader must break it down into variables and operators, understand each of the small chunks separately, and finally, put them together into a single comprehensible chunk.
This principle makes block structured languages such as C and Scheme natural to use. Realize that, although assembler does not enforce a block structure, you should do your best to imitate structure in your code; this will be covered in Chapter 7. Regardless of the language being used, consider each program as a large chunk. This main chunk should be broken down into smaller and smaller chunks, each easily visible and logically distinguishable from the others. Following this advice will help to ensure your code is modularly structured, and easy to read, understand, and maintain.
4.5 Contextual factors
The brain is proficient at guessing patterns which are similar to known ones.[Oman 93] Patterns often contain details which seem redundant or unneeded:
This is a pattern. Thxs xs x pxttxrn. Ths s pttrn.
Although the intention of these three sentences is the same, they get progressively harder to comprehend as more and more information is removed.
Relating this idea to programming, if you remove some of the contextual elements which help to make code understandable, such as comments and thoughtful identifier names, the reader will have greater difficulty grasping the intent of your code. It is necessary to have enough surrounding information to be able to make sense of the individual lines of code, routines, and modules. In short, interpreting undocumented code requires extra effort.[McConnell 93]
The idea of context switching is another contextual factor worth mentioning. We have all experienced being rudely interrupted while trying to articulate an important point. By using a "mind stack" your brain remembers where you left off in your train of thought, so that you are able to continue later.[Straker 92] This stack is held in relatively volatile memory because, after a period of time, you often forget what you were in the process of saying. Combining this idea with the "rule of seven" supports the argument that deeply nesting statements, expressions, and data structures should be avoided because too many context switches can result in a "mind stack" overflow!
4.6 Eye movement
The final principle underlying many elements of style has to do with eye movement. When reading normally, our eyes tend to move from the left to right and top to bottom of each page. However, when reading quickly, the eyes usually scan downward only. Section 4.2 pointed out that newspaper columns have 7±2 words per row. This makes it easier for the reader to absorb the information. That is, the eye fills short term memory with a line of text, waits for the brain to process it and then moves on.[Straker 92] Eye movement must be taken into account when writing source code. For instance, since most code tends to be on the left side, an occasional detail on the right may be missed.
When reading something unfamiliar, we tend to peek ahead from our current position, or skip back to re-read a chunk. When looking ahead, if the text is consistently arranged, we relax and read along. If, on the other hand, the text ahead looks unclear we tense up, resulting in more misunderstandings. When programming, it is important to follow a consistent style to comfort the reader such that they can relax, and concentrate on the current fragment.[Oman 93] Providing markers is important for skipping back. For example, in this book, you can jump back to the beginning of a section by looking for a section heading, or a paragraph by looking for an indentation. Similarly, in programming, you should take advantage of white space, brace placement, and comment blocks to clearly distinguish statement associations.
4.7 Chapter summary
The ideas presented in this chapter support the derivation of coding guidelines and standards in the ensuing chapters:
· Psychology is the study of the mind, emotions, and behaviour.
· Some elements of style are based on these factors, rather than simple logic.
· A considerate programmer must understand these principles.
· It is important to learn good habits from the start; old habits die hard.
· To break a self-defeating habit requires a great deal of determination.
· Our memory model includes short-term, working, and long-term memory.
· Short-term memory is the most volatile, and must be refreshed often.
· The "rule of seven" suggests that code complexity should be minimized.
· We survive by recognizing patterns of information from our environment.
· Patterns (identifiers) that look or sound similar are easily confused.
· Coding standardization reduces the chance of misinterpreting source code.
· We read information in distinct pieces called chunks.
· The size of each chunk read depends on the expertise of the reader.
· Structured programming is especially well suited to "chunking."
· The chance of misunderstanding code increases as documentation is removed.
· We keep track of details through a "mind stack" of 7±2 short-term slots.
· It is important to keep complexity low to avoid a "mind stack" overflow.
· Avoid excessively nested data structures, statements, and expressions.
· Limit the number of arguments for each routine to less than nine.
· When readers look ahead, a consistent style comforts them.
· Markers should be provided to make it easier for the reader to skip back.
· Following a consistent coding style should be your overall goal.