This article contains affiliate links. See my affiliate disclosure for more information.



Everyone wants to write clean code. There are whole books about it!

But you don't need to read a book to write cleaner code right now. There's one "trick" that every coder can learn to make their code less confusing.

✉️
This article was originally published in my Curious About Code newsletter. Never miss an issue. Subscribe here

The key is:

Every line does only one thing

One line, one task.

But don't go crazy with it.

Don't be like this.

Here's the main idea: Short lines of code require less brainpower to read than long ones. Code that's easy to read is easier to reason about. Programs with shorter lines are, in theory, easier to maintain.

But compact code can be cryptic. (Ever seen APL?) And just because you can split a line doesn't mean you should.

In some languages, you can assign two values to two variables on one line:

x, y = 2, 7

You could put both assignments on their own line:

x = 2
y = 7

But, c'mon. Do you really need to? How can you tell if a line should be split up?



It's not all about line length

Felienne Hermans opens her book The Programmer's Brain with an undeniable truth: "Confusion is a part of programming."

It probably means it's time to take a break.

Hermans' book (which I highly recommend) explains how your brain's three memory functions work together to understand code:

  • Long-term memory (LTM): Stores information for long-term retrieval, such as keywords, syntax, and commonly used idioms and patterns.
  • Short-term memory (STM): Stores new information for short-term retrieval (less than 30 seconds!), such as variable names and special values.
  • Working memory (WM): Processes information from LTM and STM to draw conclusions and derive new knowledge.

STM and WM are small. Both can only store about 4 to 6 things at a time! Overload them and you've got a recipe for confusion.

How your brain processes information.

That gives us a rule for deciding if a line of code is too complex:

💡
The Rule of Six: A line of code containing 6+ pieces of information should be simplified.

Here's an example in Python:

map(lambda x: x.split('=')[1], s.split('?')[1].split('&')[-3:])

Is that hard for you to read? Me too. There's a good reason why.

You have to know what map, lambda, and .split() are. The variables x and s, the strings '=', '?', and '&', the index [1], and the slice [-3:] all take up space in STM and WM. In total: ten things! Your brain can't keep up.

Or maybe yours can.

If so, you've got some good experience under your belt.

Your brain "chunks" syntax like s.split('?')[1] into "the part of the string to the right of the question mark." And you can reconstruct the code using information stored in your LTM. But you still only process a few chunks at a time.

So… we can identify when a line of code is too complex. Now what?



If code is confusing, break it

Break it into smaller pieces, that is!

There are two strategies I use to break up code. I call them SIMPLE and MORF.

The SIMPLE strategy adds lines of code to decrease cognitive load.

Let's apply SIMPLE to that nasty one-liner we saw earlier. Remove the second argument from map() and put it on its own line:

query_params = s.split('?')[1].split('&')[-3:]
map(lambda x: x.split('=')[1], query_params)

It still might be hard to read. There are seven things to keep track of in the first line:

  • query_params
  • s
  • .split()
  • '?'
  • [1]
  • '&'
  • [-3:]

But each line has fewer things to track than before. Your brain can process them more easily.

Apply SIMPLE again and move s.split('?')[1] to a new line:

url_query_string = s.split('?')[1]
query_params = url_query_string.split('&')[-3:]
map(lambda x: x.split('=')[1], query_params)

Compare that to the original one-liner. Which one is easier to process?

The MORF strategy takes a different approach and groups code into functions.

Here's what MORF looks like applied to our one-liner:

def query_params(url):
    return url.split('?')[1].split('&')[-3:]

map(lambda x: x.split('=')[1], query_params(s))

You can even combine MORF and SIMPLE:

def query_params(url):
    query_string = url.split('?')[1]
    return query_string.split('&')[-3:]
    
map(lambda x: x.split('=')[1], query_params(s))

You don't have to understand the code to feel the effect. Each line is easier for your brain to process.

There's a bonus benefit, too!

Once you know that your WM and STM aren't overloaded, you know that any confusion left over is due to missing information in your LTM.

In other words, SIMPLE and MORF don't just help you write cleaner code. They help you identify knowledge gaps that you can improve with practice!


I wrote plenty of code that violated the rule of six as a new coder, and even more often as an intermediate coder. Here are four other mistakes I made:

4 Things I Wish I’d Done Earlier As a Coder
And a lesson in reading code from Donald Knuth.

Dig Deeper

Read about the cognitive science behind the rule of six, and other ways to minimize or eliminate confusion while coding in Felienne Hermanns book The Programmer's Brain.

Get instant access from Manning*, or buy a print version from Amazon*.

* Affiliate link. See my affiliate disclosure for more information.



Exercise

Look at the code we ended up with using SIMPLE:

url_query_string = s.split('?')[1]
query_params = url_query_string.split('&')[-3:]
map(lambda x: x.split('=')[1], query_params)

One line still has over six "ideas" in it and should, according to the rule of six, be split up:

  • Which line?
  • What are the "ideas?"
  • How would you split it up?
  • Did splitting it up make a big difference?