Naming 101

7 min read Original article ↗

The most obvious rules. Duh.

Rick Mak

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

— Phil Karlton

On any given day, you will probably find my colleagues and me in the office, deep in discussion on how to best name for a certain method or variable. Maybe around evening, we’ll finally agree to disagree and just make a judgement call because, hey, we still need to ship our code by tomorrow.

Finding a good name isn’t a trade off between project management deadlines and programmers’ preferences. Naming isn’t just about technical conventions. Naming serves the practical purpose of handing over maintainable high level code to other development teams (i.e. for our clients) and quality APIs for our open-source serverless platform. A decade ago, before technical advances like WiFi, mobile, and cloud computing, our serverless platform was only a dream. But some things don’t change after a decade — things like how you choose a good name. So I’m just rehashing what we developers have known since Java, C, or even BASIC.

Symbols vs Names

Naming things in computer science is about giving a name to a concept. The concept can be common software design pattern like Singleton and Factory, or it can be a custom logic that we write code for. By giving a name to a concept, we make the concept concrete by defining the assumptions, the behavior, and the responsibility of the concept. A concept with a name is contained and no longer (as) vague.

Well, in theory, names aren’t needed — a symbol can also denote a concept. For example, in mathematics “+” (plus) or “=” (equal) are so well understood that giving them other names would just complicate things. If you love expressing things in symbols, maybe it’s time to get a pure maths degree. Programming is more than mathematics. How are we going to program using only symbols without looking up a textbook of documentation?

In programming, rolling your eyes is better than scratching your head.

That’s why naming is important: it helps to communicate a concept to another person (which can also mean your future self). When writing code, we want to focus on the logic without constantly breaking up our train of thought by looking up the documentation. During discussion with other developers, for example team members who rotate into a project, we want to refer to concepts without explaining its behavior all over again.

Therefore, a good name is a name that helps us communicate effectively.

  • Obvious — the concept is apparent just by reading the name
  • Unambiguous — the name is only associated with one concept, or that it is obvious the name is associated with a particular concept
  • Accurate — the name is correct in describing the concept
  • Consistent — the name follows certain convention or uses the same vocabulary to describe similar concepts

Follow Conventions

Let’s say we have a function called getAccessToken() . What could it do? Almost anything, like...

... returning an access token

... fetching the access token from underlying storage to get access token

... check with the server if the access token is still valid, and log the user out if the session timed out

... result in time travel

How do we know? The documentation should cover the implementation of the function, but it is not a good idea to constantly rely on documentation to deliver the meaning of the concept. It is one thing for a concept to be difficult to remember if we were to use a symbol, but it is very bad if the name doesn’t accurately convey the meaning of the function.

Convention is important here. Convention tells you what the get, or lack of get, actually means. If this function is part of a Java program, get tells you this function is a getter and should have no side effect. This convention is prevalent even outside Java. Convention in some languages discourage the use of get in name, but a function can still be considered a getter and should have no side effect.

Get Rick Mak’s stories in your inbox

Join Medium for free to get updates from this writer.

Being consistent means that if you use the name get in your function, you should implement the function with no side effect, which is what most developers expect when they call your function. They also expect your function to return quickly because they expect the function to simply return an internal state.

Don’t Use the Same Name

A good name isn’t good if it only factors in one or two principles in naming. For example, when we designed our data model for our serverless Chat SDK, we called our model for storing information related to a conversation…obviously, Conversation. Conversation is a good name, because it is obvious that this model encapsulated information about a conversation. Since this is most commonly used as a noun, there isn't much room for mistaking a thing for an action.

But as we were writing the code for our API, we needed to name another model that stores user-specific information of a conversation. It would be used, for example, to show a message unread count to the user for each conversation they’re a participant in. In database schema design parlance, this model is an associative entity storing the relationship between user and conversation, with association relation attribute like unread count. The convention is to name this model UserConversation (or user_conversation as a table name).

Independently, both Conversation and UserConversation are good names. However when both models are exposed in the API of the Chat SDK, two good names equals one bad combination. Our most frequently asked question by Chat SDK users was: What is the difference between a Conversation and a UserConversation?

Sometimes You Need to Break Grammar Rules

Conventions often say our name should be grammatically correct, but we sometimes need to break the grammatical rules in order to make our code readable and obvious.

var somethings []Something // somethings? this word doesn't exist!

No one knows what “Something” is, but one thing is painfully obvious: “somethings” is a collection of values with the type “Something”.

Code should be obvious, even if we need to break some grammar rules to get there. If the grammar rules get in the way when we try to make something as readable as possible, we will always strive for obviousness rather than correct grammar rules.

We can also call the variable “arrayOfSomething”, but this will not be as readable as simply “somethings”. I am not saying that “arrayOfSomething” is bad naming. It is a good choice to make the type of the collection obvious.

“Settings” is another example we encountered in one of our client projects. In English, we always use the word “Settings” to refer to configurations while the word “Setting” refers to a situation or circumstance. However, in programming convention, we add “-s” or “-es” to represent multiple items of something. If we call a unit of configuration as “Settings”, how should we call an array of such “Settings”? “Settingss” is just too odd and will not pass our pull request review.

That’s why we code like this:

type Server struct {
Settings []Setting // an array of Setting
}

That’s all I can think of for now. Give me a drink, and my memory will come back with more examples. In fact, some of our best exchanges and breakthrough ideas have come from ad hoc tasting sessions at our DIY whiskey corner.

The great thing about having fresh graduates working with developers who have 10+ years of experience is that we are constantly reminded about how readable our code is.

I’d also like to thank my Skygear.io colleague,

, for his input and helping me edit this piece.