Jake Worth

Jake Worth

Variable Name Antipatterns Named and Explained

Published: April 03, 2023 • Updated: April 17, 2023 5 min read

  • naming

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

Let’s talk about variable name antipatterns!

I use the term ‘antipattern’ a lot on this blog. To make sure I’ve defined it at least once, an antipattern is a technique that seems good but has more bad consequences than good ones.

These are antipatterns because they often make sense in isolation and can propagate through a codebase, to the detriment of developer experience and maintainability of the codebase. If you’re interested in a similar take on this idea but from the ‘pattern’ perspective, check out Pick a Good Name on the Hashrocket blog.

Here are the antipatterns, written in JavaScript.

Antipattern: Shrt Nme (Short Name)

Bad:

const c = user.createdAt;

Better:

const createdAt = user.createdAt;

// or
const { createdAt } = user;

Short variable names are tempting, because who doesn’t like minimalism? Shorter names equal less code, equal faster rocket ship?

The problem with short names is that outside their assignment, they’re meaningless. What does c mean? If you’re further down the file or in another file that imports this constant, it’s unknowable. When I see the variable out of context, I want to have some idea what it means.

Even when the variable name has a common meaning, such as an enumerable index named i or idx, I think you’re better off with index.

Don’t use a short name unless a reasonable colleague would understand its meaning out of context.

Antipattern: Looonnng Name (Long Name)

Bad:

const userWhoHasTriedAndFailedToLogIn = this.user;

Better:

const loggedOut = this.user;

⛔️ Contradiction alert! Didn’t I just argue against short names? It’s a game of inches.

Long variable names are tempting because we don’t want to lose information. If this variable represents a user who tried to log in, shouldn’t our name reflect that?

Long variable names make long lines and can be difficult to read. They’re also notoriously good places to hide typos, if you care. I do prefer them to short names, but we’re looking for a middle ground.

Antipattern: Doppelgänger Names

Bad:

const userA = this.admin;
const userB = this.customer;

Better:

const admin = this.admin;
const customer = this.customer;

You find this antipattern in automated tests. userA and userB walk into a customer portal, complete purchaseA and purchaseB, acquiring itemA and itemB.

I call these Doppelgänger Names because they’re nearly identical, just one letter different, but they represent distinct ideas. userA and userB almost always have a distinction: a role, a creation date, or a count of associated records. If they’re both customers, but one is new and one is old, why not name them newCustomer and existingCustomer? Let’s preserve that meaning.

Another benefit of distinct variable names is readability. Your eyes can easily swap factoryA and factoryB; try that with yakima and columbus.

Doppelgänger names are also great hiding places for bugs. I’ve lost count of the tricky bugs I’ve resolved where multiple programmers failed to realize that a Jest mock of useProfileQuery cannot mock a function named useProfilesQuery (wait for it).

Antipattern: The Name That Knew Too Much

Bad:

// Inside a `ProductItem` component

<button onClick={asyncSubmitStripePayment}>Purchase</button>

Better:

<button onClick={handleClick}>Purchase</button>

I see this all the time in React code: a button in a small isolated component that when clicked calls a bizarrely-named callback like asyncSubmitStripePayment or maybeUpdateClickEventsInGTA. What’s going on here?

Through the magic of Props Drilling™, these functions were passed through intermediaries, renamed again and again the same name as the original function fathoms above. By the time we see the name in the product item context, it feels out of place.

I like prop names that are appropriate to their context, like this:

// Component definition
const ProductItem = ({ handleClick }) => {
  return <button onClick={handleClick}>Purchase</button>
}

// Usage
<ProductItem handleClick={asyncSubmitStripePayment} />

If we bring the button to life, we can have the following conversation:

  • Developer: Button, when I click you, what happens?
  • Button: I call a function called handleClick!
  • Developer: What does handleClick do?
  • Button: Not my problem.

Don’t let your names know too much about what’s happening in other realms.

Antipattern: Typed Names

Bad:

const usersArray = this.users;

Better:

const users = this.users;

Including types in a variable name is a convention in some languages. But in the many languages where it isn’t a convention, such as Elixir, Ruby, and JavaScript, resist the urge.

Typed variable names are like overly specific code comments. They crystallize the implementation right now, making future changes harder. What if this.users becomes an object? If we’re diligent enough to correctly change the variable name, now we’re not just changing behavior, we’re changing a name, too, for no reason.

If you must tell everyone the type of your variable, you might have an issue with a thing (users) having a name that’s surprising given its type (boolean or string). Solve that problem instead!

Make Renames Easy

In Make Renames Easy, I showed how I’ve made it trivial to rename variables in my code. A definite beginner-ism in programming is being afraid to rename things: “it works… I don’t want to break it by mistyping up a variable name!” Nobody wants that, so instead of never doing it, we make it foolproof.

Final Thoughts

Names are important. Renaming variables is one of my last passes during building and refactoring. Sometimes you can’t know the best name for a variable until the feature is complete. Even with work I’m very confident in, I always welcome feedback on variable names because it can be hard to see the best idea when you’re close to the work.

What are your thoughts on variable name antipatterns? Let me know!


Join 100+ engineers who subscribe for advice, commentary, and technical deep-dives into the world of software.