The Story of a System
The way I like to think about code is as a story of a complex system. It may be a long and involved story, containing many individual actors and characters, or scenes and locations. It may be a short-story, simple and easy to understand. Or it may be like a long, rambling rant, where the author has given very little thought into separating his ideas out into short, easy to read paragraphs or sections, or making a coherent argument. On some level, it’s undeniable that writing code does involve a lot typing commands to make the computer do something. But when working on larger projects, I find that conceptualizing the codebase as a story about a system is a good way to help ensure I follow best practices with the code that I write.
When I think about the story, I wonder who the characters are, and what purpose they serve in telling the story. Do the attributes and responsibilities given to this character make sense for their role in the story? When I create a new character, I think very carefully about their role, and when I am tempted to make that character do something that doesn’t make sense for that role, I know that it is time to either introduce a new character into the story, or question whether it is critical to telling the story. In this way, I can think of classes as a type of character, objects as an instance of that type of character in the story, and modules and components are the different scenes where the story takes place.
Embedded in stories are ideas, values, morals, and shared cultural assumptions. The requirements are the ideas that we are expressing in our code. These are what the characters should be doing in order to achieve our goal in telling the story. Stakeholders come to programmers with the requirements for their story. They will often have a general theme, they know what they would like their story to be about, but it is the job of the programmer to work out the details of the story, to ensure that it is coherent, and that everything flows together.
In doing this, the programmer acts as both an author and translator. Much like a ghost writer gathering key facts and information to write a story under the name of another author, the programmer gathers the key facts, ideas and themes that need to be conveyed in the story of the system they are creating on behalf of their client or employer. The most obvious difference between a programmer and a traditional author is the language that is being used. Programmers use computer-related languages to express their stories, but in most cases these are dialects based on the English language. Programmers understand the specialized vocabulary of the languages and dialects that they are working with, and are able to translate the ideas and themes expressed in the language of their clients into the vocabulary and dialects used when describing the story of a system.
If they have chosen to use a higher level language, the programmer must remember that their audience is other programmers. Other translators and the tools that they have built will eventually take the programmer’s story and translate it into a language more directly understood by the computer. The programmer should be cognizant of this, and should not go out of their way to use language or describe stories that will confuse the computer, and that can not be accurately and concisely expressed in other languages. But when writing their stories in higher level computer-related languages, the programmer should be thinking first and foremost about other programmers, who will be their primary audience reading and consuming the story in that language.
When it is understood that the primary audience is other programmers, it becomes very important to express the ideas and themes in the story in a way that is clear and obvious to the people who are reading it. When a programmer opens a source code file written in a high-level language, it should flow like a story, from top to bottom. Each source code file can be thought of as a chapter in the story. When another programmer takes a glance at it, they should immediately get the gist of what this chapter or part of the story is about. An introduction at the top of the file is very useful for helping them to quickly determine whether this part of the story is relevant to what they are looking to understand. When writing in a high-level language, the programmer should almost always be thinking about the comprehensibility of their story by the audience of other programmers who are reading it and continuing to develop the storyline.
An ideal scenario is when a programmer can open a source code file and immediately see the introduction expressing key themes for the chapter, followed by a clear beginning, middle and end, where the paragraphs or methods in each chapter and section naturally flow from one into the next, not unlike the way ideas and paragraphs should naturally flow from one into the other when writing in non-computer related languages. When describing a class or character in this way, with the beginning or main entry points at the top, the end or cleanup at the bottom, and the middle composed of many small paragraphs or methods each flowing into each other as much as possible, then other programmers will be able to open the source code file, and almost speed-read through the story while scrolling down, in a natural and intuitive way.
When structuring the story to optimize for comprehension and intuitive understanding in this way, it is important to use proper grammar and orthography. It is not about nitpicking, but about optimizing readability and understanding of the audience. If you stick to generally accepted grammar and spelling in the languages or dialects that you are writing in, and take the time to find the word that correctly conveys the idea you wish to express, your readers will not have to stop and try to decipher the meaning or guess at your intentions. For someone who is well-versed in a given language or dialect, improperly formatted or structured writing sticks out like a sore thumb, and is an unnecessary distraction for your readers. It looks sloppy and careless when the author can not take the time to proofread their composition. What the original author saves in time by not spending a few extra minutes to find the correct word, the readers lose many times over when they have to stop and think about the original intention.
Once a good story has been written, it can become timeless, or even adapted in many ways in which the original author never conceived. The story of the system may continue to be read many years into the future. If the future readers are left guessing at your intentions and cannot make sense of the story, then reading through it will be a very frustrating and tiresome experience for them. They will not be able to easily build on the story or adapt it for the future. If this is the case, they may decide your story is incomprehensible and non-sensical gibberish, and convince others that the story must be rewritten. This is not good for your reputation, and will cause others to incur unnecessary expense.
If you are able to conceive of your code like this, it becomes possible to write a complex story with many different scenes and characters, each interacting with each other in a way that is as easy as possible for other programmers to read and understand. They will be able to intuitively scan over the many different parts of the story and only stop to consider the details that interest them. If each idea is clearly expressed using proper grammar, orthography and the right words, then reading the story of the system can be a very pleasant experience, which other programmers will be able to build upon well into the future.