Programming: Naming

Good naming means good design

A tiger labelled “danger zebra”
This is what happens when you replace abstractions with descriptions… provided “snow tiger” is well defined in you project’s dictionary.

What is programming?

Your audience is not the machine

  • a compiler that will translate your instructions into lower-level code. The aim of compilation here is to provide you some abstraction through a higher-level language that will be more convenient to express what your application should do.
    Compilers — and the machine itself — don’t need to understand any meaning of what you are telling them. Even the most obscure and ill-designed code will execute smoothly, providing you comply with an expected syntax.
  • your colleagues, who need to understand the meaning of your code in order to maintain it. Unlike your compiler, all of them are different in terms of experience, skills, culture. To understand each other, you’ll have to agree on using additional abstractions over the programming language, related to design (good technical practices) and the business concepts handled by your app.

You’re not speaking

  • if the feedback is bad, the fact that the code “works” (while not being fully understandable), coupled to the delivery time expectations, might lead you to postpone the improvement of maintainability ;
  • even if the feedback is ok, that does not mean that someone — even you — might understand that code a few months later, when you’ll have forgotten the current context.

Writing for the unknown

  • what part of your code will be read. So you cannot bet on “nobody will try to understand that”.
  • who will read it. It could be a junior programmer, somebody without some required technical or business background.
  • when it will be read. It could be anytime from the day it was written to decades later.
  • why it will be read. It could be for bug fixing, refactoring, new feature development, testing or documentation. Each of those can require different info.

What to name?

  • identifiers: a program variable or constant name is nothing more than a label on a memory place, functions names are just the same (but with the different purpose of executing that memory place, with arguments pushed on the stack), classes are functions groups, and attributes are classes variables.
  • artifacts: files and directories are labels on disk addresses, as well as database identifiers (name, tables & columns, constraints, triggers, etc.) are labels on database file offsets.
  • documentation: names are also used in documents.

How to name?

Take time

In 2013 a discussion thread on Quora led to discover that naming things was the hardest task for half of programmers.

There are only two hard things in Computer Science: cache invalidation and naming things .

Add value

x1 = getUnitPrice()
x2 = getCount()
// You need to look for the assignments of x1 and x2
// to understand what "total" is about.
total = x1 * x2
up = getUnitPrice()
c = getCount()
// Is "up" the opposite of "down" ?
// Is "c" the speed of light?
total = up * c

State the what, not the how

  • totally: var string: String
  • partially: function func(param1, param2)
  • paraphrased: keymap = dict(). We already know that a dict is a key-value mapping.
  • added through prefixes or suffixes: customer_obj = Customer(), var v_name: string, const c_max = 20, function f_sayHello()
  • technical or business: customer: Customer. That doesn’t help more.
eventsArrayMap: Map<User, Event[]>
eventsByUser: Map<User, Event[]>
userHistories: Map<User, Event[]>

Be specific

  • you’ve been lazy, and didn’t bother to take the necessary time to devise a useful name.
  • what you are trying to name does too different things which cannot be grasped in a single and simple concept. For instance, if some component loads and parse files, then uploads data somewhere, then analyze the data, it is likely that you’ll give it a vague name such as Manager or Builder, because anything more specific would be too specific and fail to grasp some aspect of it. This is the “smell” of a poor application of the SRP, and means that you should probably split that component into separate, more detailed and more identifiables parts.

Format

  • camelCase (including PascalCase) is named after switching upper and lower case in Java, JavaScript/TypeScript, Swift.
  • hyphen-case (or “dash” case, or “kebab” case) in tag languages such as XML or HTML (or languages whose identifiers are used in such languages, such as CSS) because they are usually case-insensitive (and so placeHolder would be confused with placeholder if using camelCase) and because those languages do not usually support arithmetic operators such as - (this has raised new constraints about spaces around hyphens when performing subtractions in CSS’s calc()).
  • snake_case is named after using a dash on the “ground” in languages like Python or Rust. They allow to mimic a space between words where they are not allowed.

Avoid local duplicates

unitPrice = getUnitPrice()
quantity = getCount()
function computeTotal (unitPrice, quantity) {
return unitPrice * quantity // Which ones?
}
total = computeTotal(unitPrice, quantity)

Avoid isolated duplicates

class Block { 
contents: string
note: string
}
class Note {
title: string
blocks: Block[]
}

Be consistent

  • Define some naming rules that will help to avoid formal variations. For instance prefixes, suffixes, or words ordering: as english is the almost-ubiquitous language used to name identifiers, a common practice is to follow the qualifier-first rule of the english language. For instance a quick sort will be named QuickSort and not SortQuick. You could also decide a name schema for a family of types, like interfaces/protocols suffixed with “able” to denote a capability (as the famous Serializable, Cloneable interfaces that could apply to any Java object). Whatever you decide, always make sure to comply with it, since consistency will help readability.
  • Maintain a dictionary of business terms (applicative concepts) to be shared among the project team. Such a dictionary may not be limited to provide definitions, but also translations between different worlds such as marketing and development.

Be shareable

  • once again, avoiding multiple names for one single thing, thus reducing ambiguity. When it is not possible (because marketing names are different from technical names, for instance), a well-maintained dictionary of concepts should help, especially for newcomers.
  • Use canonical names whenever you can. Typically a component that follows a Design Pattern should be named after that pattern (modelAdapter, is better than modelNormalizer, authenticationProxy is better than authenticationInterceptor, documentVisitor better than documentExplorer, etc.) so that people aware of such patterns immediately understand the role of a component.

Files and directories

  • reading a class: each time you’ll open a file, you’ll see simpler code (one with only one concern) ;
  • writing in a class: when two developers update different classes, you will be sure there is no file merge to do.
  • loading a class: This will avoid the possibility of a something that depends is forced to load another class. For instance A.b:B tries to load B but the file where is B also defines a superclass or interface of A.

Be exact

Don’t re-state context

class House {
houseDoor: Door // redundant
}
var house = new House()
var houseDoor = house.houseDoor
class House {
door: Door
}
var house = new House()
var houseDoor = house.door

Collections

class Selection {
targets: Target[]
}
  • it only differs by one character from the singular version, which is easy to forget or misunderstand when communication with colleagues ;
  • the verb can have exactly the same form as the noun in english at the third person singular of the simple present tense. As a result, mySelection.targets could be interpreted as 3 different things: a collection of targetsfor (i of targets), an action of targeting—obj.targets(x) or a boolean getterif x.targets(y). The same goes for a number of nouns/verbs like models/models(), hits/hits(), note/notes(), documents/documents(), etc.
targetCollection: Collection<Target>
targetSequence: Target[] // Ordered
targetSet: Set<Target> // Unique
// Targets dictionary
targetByKey: {[key: string]: Target}
// The versions of a target
targetVersions: Version[]
// The versions of targets
targetsVersions: {[target]: Version[]}

Beyond names

If comments re-state the name, rewrite or remove the comment.

Conclusion

--

--

Software engineer for three decades, I would like to share my memory. https://javarome.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store