Many of us are capable of writing proficient syntax — but proficiency isn’t the same as mastery.
While programming paradigms such as object oriented and functional programming help make the code better to manage, maintain and understand, there is an under-addressed topic in the programming world.
And that topic has to do with the nature of language.
Let us begin
Code is a language. Everyone knows that but a lot of us don’t really understand what that truly means.
A language is a way we communicate with each other. It’s a way to transmit meaningful information through a medium. Language by itself is not as useful. It needs an audience — and when it comes to code, developers are the primary target.
Under traditional thinking, a programming language is the interface between the machine and the programmer. The programmer types the code and the machine compiles it to specifications.
But a programming language’s functionality is much more than this. It is also an interface between developers — or else we would all be coding in binary.
We are all visual thinkers and consumers
Clean code is designing a program that supports visual thinking. It’s the act of crafting code in a manner that allows people to digest information with a minimum conscious effort.
The level of ‘noise’ in code is measured through the ratio of useful information and irrelevant data. A piece of code may be technically correct but visually, it can appear noisy due to formatting.
Yes. Indentation matters. So does grouping relevant data together.
Take a look at this hypothetical Angular code.
Visually, it is very long and hard to capture quickly all the information in one quick glance. Our eyes probably stopped at around authService
and gave up from there.
Lets take a look at the same code but reformatted.
While it looks slightly better, the subject of authService
is prone to getting omitted from the comprehension process. This is because the first line is trying to tell the reader two very different things. It creates a blimp in the way we read, like an unnecessary road bump.
Here’s another version of the same code.
This may look fine but this.createForm()
gets lost due to domain association with the declared constructors.
Here’s an example of a well formatted code.
There is clear separation and the ) {
being on it’s own line allows for a visual break in between the constructor and the actual code.
This may seem trivial but imagine the first formatting iteration of the code over multiple files and lines. Not everyone will have large screens to view long lines of code. Formatting in code is a form of punctuation for human understanding. Machines don’t care but the person trying to understand your code does.
Formatting based on data relationship and domain can clean up noisy code by making it more human friendly.
the myth of complexity (aka agglutination)
Complex is not sexy. Nor is it smart. The ability to simplify the complicated is the true indication of a good developer.
There is myth that code has to look impressive to be good. However, what we often discover is that bad code often amount to a series of meaninglessness strung together in a web of complicated nothingness. This is another common form of noise.
Complexity often manifests in the form of names.
Agglutination is a linguistic process that strings together a series of single meaning words to spawn a new word. Programming uses a lot of agglutination that often end in words like object, component, manager, item and exception.
The final result discards physical contextual space. It pads out the name of the variable, function, class, declaration or reference with with unnecessary words. But developers do it because they think it’s convention.
Perhaps it is convention but that doesn’t always mean that it is efficient.
Names like AcessViolationException
and IndexOutOfRangeException
are unnecessarily long winded. If you were to trim it down to AccessViolation
and IndexOutOfRange
the words do not lose their meaning. The meaning is still undisputed.
However, use your judgement when it comes to certain names. If you were to knock of Exception
from ArgumentException
, the meaning gets lost. Removing Exception
from TypeAccessException
creates uncertainty by inferring a different meaning.
Call it by what it is
As developers, we have an unintentional love affair with creating long and complicated code.
Take a look at the following code:
if(
orderIdByCustomerId
.get(customer.getId())
.containsKey(order.getId())
){
...
}
The issue with this code is that it doesn’t communicate what it actually does. While it looks impressive and may work without issues, it doesn’t fulfill the communication needs required between developers.
You could put in a comment but good code is said to be able to explain itself.
Refactoring the example code to tell us exactly what is happening. It makes it a lot easier to trace bugs and communicate the business logic in a clear and succinct manner.
if(customer.canView(order)){
...
}
The code above is no longer a look up inside a map of a map but a permission check. It’s a clear expression of what is going on.
The real face of TDD
Developers see TDD and think ‘Test Driven Development’. While we all know what the acronym stands for, we don’t actually understand what it truly means.
When we write tests, we write them with a one for one relationship with the methods being tested. However, this doesn’t really tell us anything in general, except if the method works or not.
The point of test driven is that it’s driven by test — that is, cases and scenarios that corresponds to what would happen in real life. Testing if x = y
isn’t really useful. When you use the object that you’re testing as a whole, it gives your test case a richer reason for existing.
Good test driven development is defined by clear specifications of the required functionality. It doesn’t confuse itself with the individual components but takes a case to construct a whole.
Final words
Code is essentially a bunch of details put together to perform a particular purpose. If that purpose is lost, code becomes over or under abstracted.
Writing succinctly beautiful code is a language art form. If you think of code as a method of communication between developers rather than an interface to a machine, then it should make you more conscious towards how you write your code.
There is no one to impress and seemingly complicated code can only result in frustration. Well written code documents thought processes and the translation of business logic in an easy to digest manner. If a developer is unable to clearly express themselves in code, chances are, they’re also going to struggle writing clear and concise notes.
When code is truly self documenting, then it means that the developer has the ability to clearly communicate and translate business requirements. So keep it simple before you try to make it complicated.