Naming

Great naming let us understand what the code means without inspecting its details. In fact, we should be able to understand an entire codebase just reading the names of classes, methods and variables, never looking at what they contain. This clarity is reached by naming classes, methods and variables after what they do instead of how they do it. The how can be looked up later if more details are needed by inspecting the content. The benefits are two:

  • names do not contain any noise
  • if the implementation changes, the name remains relevant

Let's consider the following class

class BiDimensionalCoordinates(private val x: Int, private val y: Int) {
  
  fun sumByXandY(addend: BiDimensionalCoordinates): BiDimensionalCoordinates {
    return BiDimensionalCoordinates(x + addend.x, y + addend.y)
  }
}

In the above code, both class and method names leak the how. Given the distinction we made about the what and the how, we can ask ourselves two questions. The first one is: if we remove the how from the BiDimensionalCoordinates names, does the class still express intent? Let's see.

class Coordinates(private val x: Int, private val y: Int) {
  
  fun sum(addend: Coordinates): Coordinates {
    return Coordinates(x + addend.x, y + addend.y)
  }
}

The answer is yes, as the above class still expresses clear intent, without even bothering the reader with the noise of the how. The second questions is: would the naming in BiDimensionalCoordinates still make sense if we were to switch to three-dimensional coordinates? Let's see.

class BiDimensionalCoordinates(private val x: Int, 
                               private val y: Int, 
                               private val z: Int) {
  
  fun sumByXandY(addend: BiDimensionalCoordinates): BiDimensionalCoordinates {
    return BiDimensionalCoordinates(x + addend.x, y + addend.y, z + addend.z)
  }
}

The answer is no. BiDimensionalCoordinates now does not express its intent anymore as it is lying to the reader: the names suggest two dimensions coordinates when they are actually three. However, the Coordinates class would still express its intent even when using three dimensions as shown below.

class Coordinates(private val x: Int,
                  private val y: Int,
                  private val z: Int) {
  
  fun sum(addend: Coordinates): Coordinates {
    return Coordinates(x + addend.x, y + addend.y, z + addend.z)
  }
}

As a final note for typed languages, be mindful that the return type of a method is part of its naming. A method sum does not clearly expresses intent if its signature is like the following: fun sum(addend: Coordinates): Int


Recommended reads

Teach me back

I really appreciate any feedback about the book and my current understanding of software design.