My friends and family are under attack in Ukraine. Donate to protect them directly or help international organizations.

Naming functions consistently

June 16th, 2015

I believe that in order to write readable and maintainable code, we must name our functions in a consistent way. What I noticed by reading a lot of code, especially frameworks, is that developers use too many different verbs when naming functions. It's even worse when the verbs are meaningless, such as handle, execute, do, match, etc. I even find them on their own. Just one word. What does the method do() do? It gets even worse. Many functions don't use a verb at all: any, pattern, with, except, etc. A function performs a task, meaning that it must use a verb.

The Problem

I understand, we're trying to save a few keystrokes and find clever words in our rich English vocabulary. Those keystrokes you save today will be the massive technical debt of tomorrow. Using a rich vocabulary makes the same action have two different names depending on context. Many of us are not even native English speakers, myself included. It moves us further from standardization, which is at the core of computer science.

The Need to Be Explicit

Why do we need to be explicit? Because we're writing code that has to be readable by future us and by other developers. Imagine listening to a speaker who uses mostly fancy words that you don't understand. Sure, we can look them up in the dictionary, but that would get tiresome very quickly and slow us down. It's the same when reading code. Even if it's well documented, we'd have to refer to the documentation every other statement. If we choose better function names, we could read the code without skipping a beat.

The Solution

I use a few simple patterns when naming my functions. It has served me well, making naming a very easy task. I reduced the method of communication to its most basic elements common to all applications in order to create a universal language (high five if you get the Stargate SG-1 reference).

set, get. I typically use those when I want to access or modify the state of an object. I wouldn't use get to fetch data from a database. In fact, I never use the verb fetch. Fetch and get are synonyms and are therefore redundant. Examples: getSql, setContent.

find. When I need to get data from a list using some sort of criteria, I'll use the find verb. This replaces both fetch and match in most frameworks. How do I differentiate between get and find? In my book, get doesn't take arguments, with the exception of getOffset for a collection. Examples: findRecords, findRoute.

create. Whenever I need a new object, usually from a factory, I use a straightforward create verb. Example: createResponse, createSqlQuery.

call. Instead of dispatch, handle and other variations, if my goal is to determine how to call a function and how to inject arguments, I'd use a call verb. It's not a verb that I use often, but it's a very straightforward one for this situation. Example: callController.

Edit: is, has. When you need to retrieve a boolean, it makes sense to use these two instead of get.

There are some additional verbs that I use on collections, such as add and remove. Besides those, I have very little need for anything else. Notice my pattern: I'm moving data from one place to another, instantiating and destroying objects, searching for data and calling functions or methods. Those are the basics of programming. I'm not "handling" stuff. I'm doing basic computing operations.

Final Thoughts

If I can't use one of those verbs, I start by checking whether my function is doing too much stuff or is doing something in a strange way. This is my trigger for code smell. These verbs lead me to cleaner architecture, to more testable code and to maintainable applications.

If you use too rich a vocabulary for verbs, then there's a high chance that your application parts are not decoupled or are doing too much magic. If you reduce everything to more basic functions, then that would also lead to shorter call chains (a function that calls a function that calls a function). Shorter call chains also means easier to trace and debug. The advantages keep piling up and the application complexity keeps dropping.

Happy function naming!

Previous: Composer Security Checker Next: Converting a Joined Resultset Into a Hierarchy