Written by 4:23 pm Miscellania

Naming Things

One of the famously ‘hard things’ in programming is naming things – I’ve found following a few conventions in naming help you reason about a program. For example, variables should be named to describe what they are and functions for what they return.

Take this function:

function convertName(name) {
    const firstInitial = name.slice(0, 1);
    const otherInitials = name.slice(1).toLowerCase();
    return firstInitial.toUpperCase() + otherInitials;
}

This function is named for how it being used. What it returns is the string you pass it rendered in proper case. By naming the function convertName you describe just one use case – which makes it brittle. If in the future you need to process a different kind of string, say a Title you’ll choose between running convertName(title) or writing a function named convertTitle(title) that repeats the logic in another place in the app.

Let’s rewrite that function:

export const toProperCase = str => String(str)
     .toLowerCase()
     .split(' ')
     .map(s => s.charAt(0).toUpperCase() + s.slice(1))
     .join(' ');

What’s changed:

export

This is hinting that this function is tucked away in a file or folder with similar functions that are imported as needed throughout the app.

import { toProperCase } from 'helpers/strings';

const properName = toProperCase('example'); // Example
const properTitle = toProperCase('example title'); // Example Title

String(str)

Let’s avoid type errors by gracefully handling any input. There’s sure to be a Typescripty way of doing this that someone more enamored of Typescript can describe.

.toLowerCase()

Let’s take that string we’ve safely handled and send everything to lower case. This has the same effect has applying it only to the part of the string you want lower case, but requires fewer fiddly bits and as a bonus, allows us to handle strings with more than one word.

.split(” “)

Speaking of… let’s break the string up into an array individual words. “But what if there’s only one word?” You might ask. Well, we handle it in exactly the same way as a array of 2 words, 3 words… etc. “But what about zero words?” Same story, we just have an empty array to process.

.map(s => s.charAt(0).toUpperCase() + s.slice(1))

Here’s where we do the meat of the work, and it works pretty much like the original, except for the fancy charAt(0) that replaces the .slice(0,1) . Either is fine, but I like charAt because it is a little more descriptive of what you’re after which helps with code readability.

.join(‘ ’);

Finally, we put the word(s) back together into a single string. This method is similar to .split(” “) above in that it is failsafe for any number of words – as long as the thing you’re joining is an Iterable, you’re golden.

The goal of this refactor was to write code composed of functions that each do exactly one thing and are named intuitively and ready for reuse.

As homework, think about how you might rename this variable and function:

const findPokemon = getPokemon(this.props.input);

function getPokemon(name) {
     try {
         return pokemon.getSprite(name);
     } catch (e) {
         return null;
     }
 }
  • What name could you give the variable to describe what it is?
  • What name would describe specifically what the function returns?
  • How could the function handle errors and common edge cases in a graceful way?
  • Will the consumer of this code to be sufficiently confident as to what this function expects and what it will return?
Close