10 practices for writing readable code

Jason McCreary on September 18, 2018

I've been writing code for 20 years. During that time I've worked with 17 teams coding different languages to build hundreds of projects. These i... [Read Full]
markdown guide
 
 

Except for removing comments, the article reflects my thoughts pretty well, too. Code full of comments is arguably just as bad as code with no comments at all. But trickier parts of code need to be commented. No matter how obvious the implementation might be, it's important to document your intention. You never know when you'll get something wrong and if your intention is not written down, it will be impossible for the next person to determine when something goes wrong if it's because of the requirements or the implementation.

Also, while I have just found out about the rule of three, it turns out I have been advocating in its favour for years.

 

I've found a better way to pitch "remove comments": When you see a one-liner comment, there are two opportunities for its removal:

  1. if the comment is above the function or method definition, maybe the function can be renamed in a way that removes the need for the comment
  2. if the comment is within the function or method, maybe the code block that it's commenting can be extracted into its own function/method with a name that will reflect what the comment is trying to say

In this way our comments become reflected in the code itself, making the code more readable/understandable, more resistant to comment rot, and more meaningful to tools like IDEs.

One more statement: Not every comment can/should be removed, this is not absolutist advice.

 
 

It sometimes just is.

You can have something as simple as:

return x / 3;

and in the absence of a comment you can't tell whether that was supposed to divide by 3 or by anything else.
Of course, in this particular case you can use a suitable method name and not use a magic number. But I think you get my drift, sometimes the business logic itself is not self-explaining (i.e. explaining why a null check is present where it's not obvious why and whatnot).

A good rule of thumb is to comment about the 'why' and not the 'how' or 'what'. This means that the comments that are left are the ones that aren't obvious from the code.

Of course, as with anything there are exceptions, such as dealing with magic values from external sources or one that I've had to do recently: comment what a series of regular expressions were doing!

Another favourite of mine is when the production code has checks for something that's injected only for tests. To add insult to injury, those tests are usually called... wait for it... unit tests!

Otherwise, yes, that looks like a sensible rule.

 

Just a quick question, lets assume we have a method such as getUser(email,password). The return type is User. Assuming that there is no user matching that email and password(a very possible situation), what would you return if not null, to indicate there is no user?

 

Depends. Generally, returning null for objects is common practice. Specifically, I'd want to know what a method like getUser(email, password) does? It seems like it has more to do with login in which case, there's a lot that could be improved for readability's sake (naming, returns, symmetry)

 

It was just a example, more generally what if the method searches for something in a database. What should it return if it can't find the required object?

Something that could possibly better represent emptiness. For example, many ORMs return an empty collection when a query yields no results.

I see. So basically, this is something that needs to be thought about from the design level up, and not a simple change that can be done to a method(in most cases at least). I am familiar with the practice of returning an empty list rather than null. Definitely reduces the number of null checks that have to be done in other parts of the code.

Methods that return collections should never return null, ever. At the very least, an empty collection is returned. For plain objects, employ the Null Object Pattern. In case of Java, Optional class is what you should be looking for. πŸ™‚

This is exactly what I was looking for, how to handle plain objects. Thank you, Andre.
Will definitely be implementing these where possible.

There is the null object pattern for this situation, which returns something that shouldn't break your existing code and only requires minimal changes to your methods which return objects.

en.m.wikipedia.org/wiki/Null_objec...

 

Remzi Arpaci-Dusseau, my operating systems professor, stressed that maintainable code should be self-explanatory as much as possible. This touches naming, formatting, architecture, block size, basically anything that contributes to code appearance. That principle definitely aligns with your list.

 
 

Yes pretty much agree on all.

One of the reasons I like Go is that its compiler, linter and idiomatic rules solve most of these issues and more. Lets the dev focus on the business and less on these development issues that are long solved but still arent applied everywhere.

 

Oh yeah, Go is awesome with the predefined formatting and more expressive grammar. Much like Python or Ruby in those respective areas.

 

Empathy driven development... When everyone cares about the next reader of the code, amazing things start to happen within a team/organization.

The goal should be to reduce debugging time, not increase writing speed.

"Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (M. Fowler)

 
 

"Data clump" is such a good term. So evocative πŸ’―

I know I'm guilty of over-using null as a return value - and symmetry, especially in a large codebase, can be so elusive. Thanks for this high-level cheatsheet; good to keep these things top-of-mind! πŸ™

 

I usually like language that allow some optional type (like Rust or C++ through union types). It's a good element to indicate that "this piece of code may return in case all condition for it to appear are met". Same goes with other element.
This article is good and it's match perfectly with my obsession with semantic: the meaning should be directly observable from the code.

 

My real estate agent told us when bidding on a house, as you're coming up and the seller is coming down, once you get the same price back from the seller three times, it's take it or leave it. The Power of Three...

 
 

Nice article Jason!
I, too, think that readability is one of the most important qualities of the code, if not the topmost one.
I wrote an article about that.
dev.to/ice_lenor/design-your-code-...

 

Hi Jason, it might be a little bit off topic... but I'm glad to notify you that your article has reach the top 3 on Daily Now live feed. It means that thousands of developers from all over the world are being exposed to you content every time they open a New Tab on either Chrome or Firefox. Good job!

In case you haven't heard of Daily Now yet, you can check your ranking here: dailynow.co

 
 

Thank you for this article - I am working on a new project, implementing an API and was struggling with what to return for some of the operations. Your last practice - Symmetry in code is where the same idea is expressed the same way everywhere it appears - helped me settle on what I think will be the best approach.

 

Great article -- I think some of the "junior" devs need to read up more on articles like these!

 
 

This is a great article! Can it be translated into Chinese?

 
 
 

Great book. Believe it's on The Reading List. But while there are elements in each, no single book discusses all these practices. Heck, that's why I wrote one. :)

 
 
 

This is a great article! I never know about Rule of Three but now it makes sense.

 

Nice and concise. What bugs me currently when reading code are debug directives peppered inline with code. #if DEBUG...blah blah. Really makes it hard to read the real code.

 
code of conduct - report abuse