Chapter 96. Write “Readable Code”

Dave Farley

We have all heard that good code is “readable,” but what does that really mean?

The first principle of readability is to keep the code simple. Avoid lengthy methods and functions; instead, break them into smaller pieces. Name the pieces for what they do.

Automate your coding standards so you can test them in your deployment pipeline. For example, you could fail your build if you have a method of more than 20 to 30 lines of code, or parameter lists of more than 5 or 6 parameters.

Another way toward better readability is to take “readable” literally. Don’t interpret it as meaning “Can I read my code five minutes after I wrote it?” Rather, try to write code that a nonprogrammer could understand.

Here is a simple function:

void function(X x, String a, double b, double c) {
    double r = method1(a, b);
    x.function1(a, r);
}

What does it do? Without looking into the implementation of X and method1, you have no way of telling, programmer or not.

But if instead I wrote this:

void displayPercentage(Display display, String message,
                       double value, double percentage) {
  double result = calculatePercentage(value, percentage);
  display.show(message, result);
}

it would be clear what was going on. Even a nonprogrammer could probably guess from the names what is happening here. Some things are still hidden—we don’t know how the display works or how the percentage is calculated—but that is a good thing. We can understand what this code is attempting to do.

For simple examples like this, this kind of change looks too trivial to discuss, but how much of the code you see at work looks like this?

Taking naming seriously, combined with simple refactoring techniques, allows you to quickly gain deeper insight into what is happening in your code.

Here is another example, in this case from some real-world code:

if (unlikely(!ci)) {
    // 361 lines of code
} else {
    // 45 lines of 'else'
}

Highlight the unlikely(!ci) and create a new method called noConnection.

Highlight the 361 lines in the if statement and name it createConnection, and you end up with:

if (noConnection(ci)) {
    ci = createConnection();
} else {
    // 45 line of 'else'
}

Naming things sensibly, even if that means pulling out a function that is only used once in order to name it, creates clarity in code that is missing otherwise. It will also often highlight the fact that there are significant opportunities to simplify the code. In this example, there were five other places in the same file that could have reused the new createConnection method. I would take this further and rename ci to connection or something more appropriate.

Because we have improved the code’s modularity, this approach also gives us more options for further change. For example, we could now decide to hide some more of the complexity in this method and simply use the connection, whether created here for the first time or not:

ci = createConnection(ci);
// 45 lines of code

Make functions and methods simple. Make all names meaningful in the context of the problem you are solving: functions, methods, variables, parameters, constants, fields, anything!

Imagine your nontechnical grandpa or grandma reading the code: could they guess at what it was doing? If not, make the code simpler through refactoring, and more expressive through the selection of good names.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset