Code is meant to be read. You can say that it’s meant to do a task or solve a problem. You could even argue that the code is meant to be compiled or transpiled into byte code and make the computer go beep-boop. No! Clean code is meant to be read, and we came up with a bunch of different programming languages and techniques in order to make it easier to write, read and understand what is written.
Yes, there is horrible code out there, there is code that cannot be understood easily, or at all, but the same is true for fiction. If the working of the code is so hidden behind the style of writing, then it is not a good code. It might be working code, but that’s up to compilers and optimizers, but it’s not good code. So leave the crazy creativity to Picasso and other eccentric artists.
For such code it’s up to scholars to judge the code and have high-brow discussions about the merits, but for a normal reader, we want our code to be without metaphors and weird abstractions.
Take Ulysses by Joyce as a parallel. Critics acclaim it as one of the best books of the 20th century, but nobody knows what it’s about, it’s barely readable, and it completely deters normal users. Yet, after gaining recognition as a great writer following Ulysses, he wrote Finnegans Wake, which, to many, seemed even worse.
There are many articles out there dealing with how to write clean code and coding styles, but here I plan on doing something a bit different. Doing parallels between writing fiction and code. We’ll see how that works out.
How can code have a rhythm?
As well as a paragraph of a fiction book, code also needs to have a rhythm when reading. Here’s an example:
This sentence has five words. Here are five more words. Five-word sentences are fine. But several together become monotonous. Listen to what is happening. The writing is getting boring. The sound of it drones. It’s like a stuck record. The ear demands some variety.
Now listen. I vary the sentence length, and I create music. Music. The writing sings. It has a pleasant rhythm, a lilt, a harmony. I use short sentences. And I use sentences of medium length. And sometimes, when I am certain the reader is rested, I will engage him with a sentence of considerable length, a sentence that burns with energy and builds with all the impetus of a crescendo, the roll of the drums, the crash of the cymbals–sounds that say listen to this, it is important.
Gary Provost
In code, the main method of achieving rhythm is by using whitespaces and line breaks. It improves code readability, offers readers hints about where a logical break occurs, and indicates when the thought process concludes. Take the following as an example.
public void CheckReadAccess(int userId, int sectionId)
{
var user = getUserData(userId);
var section = getSection(sectionId);
var crudPermission = checkUserPermissions(user, section);
return crudPermission.Contains(Permissions.Read);
}
Do you see what I mean. Yes the code is clean, understandable, but it doesn’t flow. It doesn’t highlight the important stuff. Just contrast how much more understandable to code is with a few line breaks.
public void CheckReadAccess(int userId, int sectionId)
{
var user = getUserData(userId);
var section = getSection(sectionId);
var crudPermission = checkUserPermissions(user, section);
return crudPermission.Contains(Permissions.Read);
}
Clean code rule: Chekhov’s gun
One must never place a loaded rifle on the stage if it isn’t going to go off. It’s wrong to make promises you don’t mean to keep.
Anton Pavlovich Chekhov
Chekhov’s gun is a narrative principle that states everything you mention in a story must be necessary for the story. For example if you mention there’s a rifle hanging on the wall, then it should be used to move the narrative on.
While it directly translates to code; delete usings, variables, functions and properties that you don’t use; I want to modify it a bit. Don’t declare a variable and then not use it for 200 lines of code. We’re well past old style C where you had to declare variables at the beginning of the function.
By keeping the first mention and usage close together and consistently doing so, you’ll tell the reader that the variable serves a purpose, indicating its importance and that it will see use soon.
public void DoSomething()
{
int count = 0;
// ...
// some 50 lines of code later
// ...
if (a)
{
count = whatever();
}
else if (b)
{
count = somethingElse();
}
else
{
count = nowForSomethingCompletlyDifferent();
}
}
public void DoSomething()
{
// ...
// some 50 lines of code later
// ..
int count = 0;
if (a)
{
count = whatever();
}
else if (b)
{
count = somethingElse();
}
else
{
count = nowForSomethingCompletlyDifferent();
}
}
Don’t try to be (much) smarter than your reader
If you come across a very convoluted piece of logic, then extract it into a method and sensibly name the method. Don’t just randomly have x ^= y ^= x ^= y;
in your code.
If this micro optimization is really what you need, then extract it into a method and name it SwapVariableValues. On a side note, see how I gave a very obscure piece of code, but I explained it at a later point. Don’t do that. It would have been much better to have what the line does before I write it, but it’s here as a recursive example.
For the love of god and all that is holy, use clear names for variables
I’m sure you’ve read books where the names of the characters confuse you. They receive names starting with the same letter, or, to make matters worse, they have a very similar collection of letters. Gimli, Gloin, Groin, Farin, Borin, Nain, Oin, Gloin, Thorin, Thrain, Nain…. It gets very confusing. Avoid naming lists as list1, list2, list3 unless you use them in the same code block and they interact in a meaningful way.
Also, use conventions, don’t name iterators outerLoopIterator and innerLoopOperator when i and j will do.
Name the functions with what they do, ensuring code clarity!
Clean code rule: Show! Don’t tell.
using (SqlCommand command = new SqlCommand())
{
// set long timeout
command.CommandTimeout = timeout;
}
using (SqlCommand command = new SqlCommand())
{
command.CommandTimeout = longTimeout;
}
Don’t direct and command every ounce of attention
When reading code, especially quality code a comment indicates that the code itself is not clear enough, and you cannot express the needed clarification through code refactoring. It could be some design decision or something else. Don’t put ridiculous stuff in the comments. So if it’s superfluous it breaks the flow of reading and readers will ignore them if it happens too often.
// Get the cleaned up string. Remove everything that isn’t a letter on number
string cleanString = stripNonLettersAndNumbers(dirtyString);
Just remember reading a drama and there are so many stage instructions that you have to constantly do a context switch.
Clean code rule: Don’t overcrowd your scene
If there are too many things happening and too many conditions in your code the reader will lose focus and hate you. If you can keep your code clean by moving some things around, then do it!
public void Whatever()
{
if (a)
{
doSomething();
if (b)
{
doSomethingElse();
}
}
}
public void Whatever()
{
if (!a)
return;
doSomething();
if (b)
{
doSomethingElse();
}
}
Pick a style and stay with it
Pick a bracketing and casing style and enforce it. I can personally swap easily between them, but if they change mid-class it throws me off balance. Doesn’t really matter much, unless you have a company/team coding practice. Enforce it! With pre-commit hooks and sticks if needed.
In conclusion
You’re not writing the code for yourself. You’re writing it for someone to review, read, change and understand it. That someone might be you in the future. Trust me, in a couple of months you won’t remember most of the code you wrote.
Be nice to your readers, and don’t make them want to stop reading.