Relative Sanity

a journal

Naming with Intent

There’s the old adage in software engineering that “naming things is hard”. One only needs to look at some code examples to understand where this idea comes from:

def v(inp)
  x = inp * 0.2
  "£#{x}"
end

What on earth is going on here? Luckily, there’s a comment:

# multiply input by 0.175 and return as a string
def v(inp)
  x = inp * 0.2
  "£#{x}"
end

Well that wasn’t much help. In fact, the comment has actively made things worse. Now we don’t know if the comment is out of date or if we’re looking at a bug. Let’s have a look at the git commit message:

0182937 fixes issues

In all cases here, what each snippet was doing was perfectly clear, but they were all missing any idea of why. Giving each of these entities a meaningful name would have helped. For example, if we rewrite the method above as:

# return calculated vat on the total for display
def vat_amount_for_display(inp)
  "£#{vat_amount(inp)}"
end

# calculate vat amount based on current rate
def vat_amount(inp)
  inp * 0.2
end

suddenly we can see exactly what’s going on. In fact, the code is so well named that we arguably don’t need the comments any more, especially with a couple of further tweaks to the names:

CURRENT_VAT_RATE = 0.2

def vat_amount_for_display(total)
  "£#{vat_amount(total)}"
end

def vat_amount(total)
  total * CURRENT_VAT_RATE
end

This is an example of Kent Beck’s “Intention Revealing Message” pattern, and hints at the power of good names. It also gives a few pointers as to what makes for a “good” name in the first place.

  1. A good name reveals intention
    We need to know not just what the thing does, but why it exists in the first place.
  2. A good name has limits
    In order to name something well, it might be necessary to split it into multiple things with good names, rather than trying to make a single name do too much work.
  3. A good name is self-explanatory
    Not to be confused with documentation, which expands on a good name with further context, short comments can be a hint that the name is not up to the task, either because it obscures intention, or because it’s trying to name too much.

These are not hard and fast rules. As with anything in software development, they present axes along which we can consider the tradeoffs. Not all short comments are bad: sometimes the best way to explain why the code does something unexpected is a simple clear line of explanation, rather than agonising for hours over how to reveal this with a clever variable name. Not all variables must be well-named: in the example above, how much did changing from inp to total really help? If it had been changed to x, would the code have been less clear? The more localised a name, the less critical it is to reveal its intention independent of its context.

So if it’s a tradeoff, how long should we spend naming things? When do we decide the trade is no longer worth it?

In my experience, when it comes to naming things, you should always spend a little longer than you think when coming up with a good name for something. I increasingly believe that this is a software Pareto Principle, where good names for things is a 20% effort for 80% of the benefit.

The pursuit of good names can flush out a lot of quality software patterns, and the upside should never be underestimated.