Good software developers are no different than essayists

Okay, maybe the title is a bit misleading. Some essayists intentionally make their writings abstract and difficult to understanding. The point is, software developers should write their programs like how an essayist would write his papers. Computer programs are written to be executed by computers, but more importantly, they are written to be read by your fellow software developers. Surely no one enjoys reading code like this:

             k;double sin()
,cos();main(){float A=
0,B=0,i,j,z[1760];char b[
1760];printf("\x1b[2J");for(;;
){memset(b,32,1760);memset(z,0,7040)
;for(j=0;6.28>j;j+=0.07)for(i=0;6.28
>i;i+=0.02){float c=sin(i),d=cos(j),e=
sin(A),f=sin(j),g=cos(A),h=d+2,D=1/(c*
h*e+f*g+5),l=cos (i),m=cos(B),n=s\
in(B),t=c*h*g-f* e;int x=40+30*D*
(l*h*m-t*n),y= 12+15*D*(l*h*n
+t*m),o=x+80*y, N=8*((f*e-c*d*g
)*m-c*d*e-f*g-l *d*n);if(22>y&&
y>0&&x>0&&80>x&&D>z[o]){z[o]=D;;;b[o]=
".,-~:;=!*#$@"[N>0?N:0];}}/*#****!!-*/
printf("\x1b[H");for(k=0;1761>k;k++)
putchar(k%80?b[k]:10);A+=0.04;B+=
0.02;}}/*****####*******!!=;:~
~::==!!!**********!!!==::-
.,~~;;;========;;;:~-.
..,--------,*/

NOTE: The code above was copied from the website below. (It is actually pretty cool, but it is impossible to understand what it does.)

There are a few things that software developers should pay attention to when writing a computer program, they all revolve around the point that a software developer should help other software developers by reducing their cognitive load.

  1. Try to be as grammatically correct as possible (Sorry if I made any grammatical mistakes in this article)

There are several places in a computer programs where the use of English is necessary.

  • Your variables
  • Your comments
  • Your test cases

Spelling correctly and being grammatically correct makes your program more easily understandable. Occasionally, being grammatically incorrect slightly alters the meaning and the readers (software developers) are left staring blank into the screen and wonder what something means. It is also a more pleasant reading experience for other software developers. When a reader is annoyed (maybe because they have OCD, like me), it disrupts his mental flow and he might have to fix your poor language skills. Only then can he restart on reading your program.

2. Be explicit

This is more of a personal opinion, but I prefer explicit over implicit. Let’s say I want to return a JSON object with selected attributes from a data model. There are two ways to do it:

i. Implicit

user_json = user.attributes.tap do |attrs|
attrs.delete("first_name")
attrs.delete("last_name")
end

ii. Explicit

user_json = {
email: "dominic@gmail.com",
gender: "male"
}

In the first example, we grab all attributes from the user object and delete the ones we don’t want. There is no way to really know what attributes are we returning without looking at the database schema. In the second, we explicitly declare which key value pairs are included in the user_json object. It is much clearer and also safer to add/remove keys.

3. Be consistent

Maintaining a system’s conceptual integrity by giving consistent names to each concept is essential to allow other developers understand the system’s workflow. You cannot give the same concept two different names and expect new developers to understand they are the same thing. I swear to god I have seen this before. A bit of an OCD here, but I believe even having inconsistent namespaces is aesthetically displeasing.

4. DRY (Don’t Repeat Yourself) is not always good

“Don’t Repeat Yourself” is a popular methodology and I myself follow this principle to try and build as many reusable modules as possible. However, you must pay attention to when you *should not* blindly apply this principle to your code. For example, let’s say you have two different API endpoints that do the same thing (whether having two API endpoints to perform the same act is a good decision, that’s a separate discussion), it’s tempting to abstract the shareable code into a module because “DRY”. Later, more product requirements arrive and customization has to be added to each API endpoint because they are catered for different API clients. Since you already have your module extracted, you start hacking on top of your code with if else statements. Finally, your reusable module becomes a module that has too many hacks and *some* shareable code. If you run into situations like this, you might want to take a step back and consider repetition as a solution. Separating the code completely can at least make sure your customization for one API endpoint doesn’t introduce unwanted behaviors for another.

5. A good computer program has a “thesis”

A computer program is like an essay, which both have a “thesis”. Both a good computer program and a good essay has relevant “paragraphs” (modules) that are highly relevant to its thesis. To make your computer program easily understandable, you must reduce the ratio of noise to the program’s size. Throw away code that are irrelevant and focus on delivering code that is tightly knitted to the program’s use cases. However, I have to make it clear that having irrelevant code might be a product problem rather than an engineering problem.

6. Less lines of code is not always good

A computer program with less lines of code is usually easier to understand, but if it gets to a point where the message it wants to deliver gets lost, it is difficult for other developers to understand your program. This resonates with my point on trying to be explicit. While you should aim to write a program with as little lines of code as possible, you should also make sure the message the program delivers is crystal clear. If having less lines of code results in the message getting lost, it’s probably better to write more lines of code to make sure the message is clear.

7. Using commonly used functions reduces cognitive load

Each programming language has its own set of functions. Some are used more often and some are not, just like natural languages. For instance, the Chinese language has tens of thousands of characters, but you probably need to know only a few thousand to get by. I am sure there’s a reason for some functions to exist and there are their use cases, but I would argue that using the more commonly used functions makes your program more easily understandable unless using a specific obscure function is essential for whatever reasons (e.g. performance). Using more commonly used functions also reduce the chance for other developers having to google them while following the program’s flow, this act switches their attention from the program to the function itself. When they come back to the program after reading the documentation for a few minutes, they might have to pick up the logic again from ground zero.

Writing performant and bug-free computer programs is important, but it is also important to treat your code like an essay.

The best software developers are *almost* always good communicators because readability is on top of their priority lists. You don’t just write programs for yourself or your machines, but for other developers. Start treating your program as a communication channel so that your fellow developers don’t have to come to your desk often to understand your intention. You’re a software developer, and an essayist.

Like what you read? Give Dominic Wong a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.