Clean Code - Function and variable names

Clean Code - Function and variable names

Tips from Uncle Bob

·

5 min read

Robert C. Martin, often called Uncle Bob, is an American software engineer well known for his books on Clean Code and Clean Architecture.

This article is one of a series that I am writing as an introduction to Clean Code. It’s made of notes that I wrote while watching a series of video lessons that Robert gave about clean code. This one will focus on tips for function and variable names, from the first and second episodes.

You can find the 6 episodes' Youtube playlist here.

Names

Names are everywhere: files, directories, programs, classes, variables, methods, arguments,

We then have to be good at naming!

Most of the naming rules in Bob’s videos are from Tim Ottinger’s rules for variable and class naming.

Function names should be verbs

You don’t want nouns as function names. Function names should be verbs because functions do things.

Functions names should explain clearly what it’s doing.

→ Prefer using verbs for function names.

Explanatory variables

Described in the previous article.

Some variables should exist and be named only to explain a statement. You remove the complexity of a statement (an if for instance) by explaining it with the name of the variable.

→ Extract complex statements into well-named variables.

Reveal your intent

A name that requires a comment is a bad name. The name of a variable should tell us the significance of what the variable contains.

// BAD
let d: Int // elapsed time in days

// GOOD
let elasedTimeInDays: Int

Size of names

  • Rules for a variable name size: a variable name should be proportional to the size of the scope that contains it :

    • If the scope is very small, a single letter is fine (ex: for loops with i and j variables, you don’t want them to be any longer).

    • Inside if statement, loops or small functions, it should be very short, like a word.

    • In a class, instance variables have a larger scope, it should be longer, like two words.

    • Global variables have a huge scope, it should be very long to be specific.

Example: a variable storing an animation duration in a very short and specific method can be named duration because the context already explains it. But the same variable in a global scope should be more detailed, like headerBounceAnimationDuration.

  • Rules for a function name size: the exact opposite. The bigger the scope, the smaller the name.

    • We would not want to call the open function if it was called openFileAndThrowExceptionIfNotFound. We want a large scope function name to shrink because we are going to call it more, and it must be dealing with a high level of abstraction.

    • An instance function of a class should be a bit more specific, it will probably have a slightly longer name.

    • A private function called by a public function will have a longer name (see this article on clean code about extracting code). Then a private function called by a private function will have an even longer name…

    • Names get longer because functions become more precise. It does something very tiny and precise.

  • Rules for a class name size: same as functions.

    • Public classes have one-word names.

    • Subclasses have longer names.

    • Inner classes have even longer names…

→ For variables, the smaller the scope, the smaller the name.

→ For functions and classes, the bigger the scope, the smaller the name.

A good system of names

func getThem() -> [Int] {
    var list1 = [Int]()
    for item in items {
        if item == 4 {
            list1.append(item)
        }
    }
    return list1
}

This code is not complicated, but it’s not explicit. It reveals no intent.
The names do not explicitly reveal the context of the problem being solved.

func getFlaggedCells() -> [Int] {
    var flaggedCells = [Int]()
    for cell in gameBoardCells {
        if cell == CELL_STATUS.FLAGGED {
            flaggedCells.append(cell)
        }
    }
    return flaggedCells
}

Here only the names have changed. This naming system makes it easier to understand what the function does.

It also tells what program contains the function by giving context: this program is probably a game, a Minesweeper.

→ A good system of names tells you about the function you’re working on, but also about the entire context of the system.

Disambiguate

Code is full of optical illusions, and you have to fight against that.

func XYZControllerForEfficientHandlingOfStrings() -> StringController { ... }
func XYXControllerForEfficientStorageOfStrings() -> StringController { ... }

Would you pick the right function when using the code completion of your IDE?
Sometimes symbols can differ by only a few pixels.

→ Use the right names to disambiguate the situation.

Parameters with numbers

Do not use parameters with numbers, those are confusing:

func copyChars(str1: String, str2: String) { ... }

Instead, name the parameters to clarify the intent:

func copyChars(source: String, destination: String) { ... }

→ Instead of adding numbers to parameters, name them by their roles.

Use Pronounceable names

if you can’t pronounce it, you can’t discuss it.

Wrap up

Here were my few notes on naming from Uncle Bob’s lesson on Clean Code.

You can find my other notes on Uncle Bob's lessons here:

I hope this article has been helpful to you. If you have any questions or feedback about this article, don’t hesitate to contact me on Twitter!