Skip to content

Instantly share code, notes, and snippets.

@karol-majewski
Created September 3, 2019 10:51
Show Gist options
  • Save karol-majewski/605a1645147dc0717ccb01361fc420c8 to your computer and use it in GitHub Desktop.
Save karol-majewski/605a1645147dc0717ccb01361fc420c8 to your computer and use it in GitHub Desktop.
How descriptive should function names be?

Background: we've had a conversation about using full words vs. single letters in function names. One argument against using full words was that it leads to long, Java-like names like getPropertyFromDictionaryOptionCurried.

The problem

Long names like getPropertyFromDictionaryOptionCurried are bad not because they are made of full words. They are bad because they are saying too much.

If single letters read more naturally than full words, then this would be an improvement:

getPropertyFromDictionaryOptionC

It still looks scary. Let's go one step further.

getPropertyFromDictOC

Instead of neutralizing the problem, we have created another one. We've shortened the name, but we have also made it obscure.

The solution

Let's start from the beginning.

getPropertyFromDictionaryOptionCurried

The fact this function accepts a Dictionary is expressed by its type signature. We don't need to repeat ourselves.

The same goes for Option. That's what types are for. We arrive at:

getPropertyCurried

Using curried as the suffix suggests that currying is something extraordinary. It's common practice to use suffixes when pointing to exceptions (for example, a synchronous function in an asynchronous environment might be suffixed with the word sync), but currying is hardly surprising in the JavaScript world.

The dominant pattern of this function is that it reads from an object. That's all it does. So that's what it should be named after.

getProperty

The fact this function is capable of dealing with different kinds of objects is a detail, not the dominant characteristic. We can communicate it by using a function overload.

A working example:

function getProperty<T extends object>(obj: T): <K extends keyof T>(key: K) => T[K];
function getProperty<T extends object, K extends keyof T>(key: K, obj: T): T[K];
function getProperty<T extends object, K extends keyof T>(obj: any, key?: any): any {
    switch (key) {
        case undefined:
          return (key: K) => obj[key];
        default:
          return obj[key]
    }
}

getProperty('Blob', window);
getProperty(window)('Blob')

Takeaways

  1. Focus on what the function does and let TypeScript pick the right overload.
  2. Shortening words hardly ever makes things better.
  3. If a function is universal, yet its name sounds specialized, then chances are an overload would be a better choice.

Bonus 1

The simple, the punchy, the easily remembered will be more effective in the long run than some long name that says it all, but in a such a way that no one wants to say it at all. — Kevlin Henney in Giving code a good name

Bonus 2

The Inverse Scope Law of Function Names.

Bonus 3

If you don't want people to use something, give it a longer name — Dan Abramov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment