# Naming Stuff is Easy [TOC] --- Naming things is ~~hard~~. This sheet ~~attempts to ~~make it easier. ## Abstract All words are English. All words are exactly 4 ASCII letters. No proper names. Prefer words in common usage. Avoid homophones and near homophones. Prefer two-syllable words. Each word's first three letters must be a unique sequence (XXX-). Each word's last three letters must be a unique sequence (-XXX). Each word's first and last letters must be a unique sequence (X--X). The Damerau-Levenshtein distance between any two words is at least 2. Prefer words with positive connotations. Prefer words which are "interesting" (strong emotional valence) even if connotation is neutral or slightly negative. Avoid words with strong negative connotations. Represent initial letters somewhat equally when possible. Word list is sorted alphabetically. ### Avoid minting new names if you can Every name that has to be remembered is a drain on peoples’ mental space. As such, sometimes the best strategy is not to name something at all, but instead to piggyback on an existing name. ### Names should be informative Your starting point for understanding the nature of a system is often its name. They show up all over the place: documentation, machine names, mailing list names, source directories, config files, emails, and face to face conversations. A name is an opportunity to help people in all those contexts understand what your system does, and you should make the most of that chance. There are two basic ways to pack information into a name: making it _descriptive_, and making it _mnemonic_. > This is the **S - I - D** principle Mnemonic names, on the other hand, are names that give you a mental hook that helps you remember what a system does, without being enough to tell you the meaning. Mnemonic names are less informative, but they’re often shorter, and can carry a more distinct identity than a blandly descriptive one. ### Identity Example A sense of identity can be useful when you need to distinguish systems with similar purposes. 4 different systems that could have been called _alert-monitor_. Rather than calling them all _alert-monitor_, or, even worse, _alert-monitor{1..4}_, give them mnemonic names that carry distinct identites, like _watcher_, _eye_, _cateye_ and _oculus_. ### Less common systems should have more descriptive names When choosing an identifier in code, it’s good practice to pick a longer, more descriptive name when naming a more rarely used thing. You don’t want to waste precious mental space on remembering the meaning of something you interact with rarely. Conversely, short names that are less informative make the most sense for very common operations. The same principle applies to naming systems. In the systems case, however, it’s a little trickier to think about what it means for something to be “frequently used”. In particular, the audience of people you’re communicating to is more diverse with systems than with code, where your audience is the other developers working on the system. In the systems case, you should think not just about the primary users of your system, but more broadly about the devs, admins, support folk, and really anyone else who interacts incidentally with the system. All this said, descriptive names have downsides too. Descriptives names can be long, and long names impose their own mental cost – at some point people just stop being willing to read the paragraph you’ve embedded in the name. There are also platform-specific limits to name lengths for things like usernames and host names, which matters if you’re going to have users or hosts named after your system. ## Practice empathy Picking names is fun, but you shouldn’t let that lead you to waste other people’s time. We avoid picking cutesy names for identifiers in programs because it makes the code harder to understand and remember, and you should have similar concerns when picking names for your systems. This doesn’t mean you should never pick a fun name. But you should do so sparingly. ## Avoid churn Names, once chosen, are hard to change. The name gets itself embedded in more places than you can imagine, including other people’s brains. Once it’s out there, it’s often better to let it be than to rename it. But that very stickiness means you should put some effort into picking a good name, since you’ll probably be stuck with it for a long time. ## English language Use English language when naming your variables and functions. ```js /* Bad */ const primerNombre = 'Gustavo' const amigos = ['Kate', 'John'] /* Good */ const firstName = 'Gustavo' const friends = ['Kate', 'John'] ``` > Like it or not, English is the dominant language in programming: the syntax of all programming languages is written in English, as well as countless documentations and educational materials. By writing your code in English you dramatically increase its cohesiveness. ## Naming convention Pick **one** naming convention and follow it. It may be `camelCase`, `PascalCase`, `snake_case`, or anything else, as long as it remains consistent. Many programming languages have their own traditions regarding naming conventions; check the documentation for your language or study some popular repositories on Github! ```js /* Bad */ const page_count = 5 const shouldUpdate = true /* Good */ const pageCount = 5 const shouldUpdate = true /* Good as well */ const page_count = 5 const should_update = true ``` ## S-I-D A name must be _short_, _intuitive_ and _descriptive_: - **Short**. A name must not take long to type and, therefore, remember; - **Intuitive**. A name must read naturally, as close to the common speech as possible; - **Descriptive**. A name must reflect what it does/possesses in the most efficient way. ```js /* Bad */ const a = 5 // "a" could mean anything const isPaginatable = a > 10 // "Paginatable" sounds extremely unnatural const shouldPaginatize = a > 10 // Made up verbs are so much fun! /* Good */ const postCount = 5 const hasPagination = postCount > 10 const shouldPaginate = postCount > 10 // alternatively ``` ## Avoid contractions Do **not** use contractions. They contribute to nothing but decreased readability of the code. Finding a short, descriptive name may be hard, but contraction is not an excuse for not doing so. ```js /* Bad */ const onItmClk = () => {} /* Good */ const onItemClick = () => {} ``` ## Avoid context duplication A name should not duplicate the context in which it is defined. Always remove the context from a name if that doesn't decrease its readability. ```js class MenuItem { /* Method name duplicates the context (which is "MenuItem") */ handleMenuItemClick = (event) => { ... } /* Reads nicely as `MenuItem.handleClick()` */ handleClick = (event) => { ... } } ``` ## Reflect the expected result A name should reflect the expected result. ```jsx /* Bad */ const isEnabled = itemCount > 3 return <Button disabled={!isEnabled} /> /* Good */ const isDisabled = itemCount <= 3 return <Button disabled={isDisabled} /> ``` --- # Naming functions ## A/HC/LC Pattern There is a useful pattern to follow when naming functions: ``` prefix? + action (A) + high context (HC) + low context? (LC) ``` Take a look at how this pattern may be applied in the table below. | Name | Prefix | Action (A) | High context (HC) | Low context (LC) | | ---------------------- | -------- | ---------- | ----------------- | ---------------- | | `getUser` | | `get` | `User` | | | `getUserMessages` | | `get` | `User` | `Messages` | | `handleClickOutside` | | `handle` | `Click` | `Outside` | | `shouldDisplayMessage` | `should` | `Display` | `Message` | | > **Note:** The order of context affects the meaning of a variable. For example, `shouldUpdateComponent` means _you_ are about to update a component, while `shouldComponentUpdate` tells you that _component_ will update on itself, and you are but controlling when it should be updated. > In other words, **high context emphasizes the meaning of a variable**. --- ## Actions The verb part of your function name. The most important part responsible for describing what the function _does_. ### `get` Accesses data immediately (i.e. shorthand getter of internal data). ```js function getFruitCount() { return this.fruits.length } ``` > See also [compose](#compose). You can use `get` when performing asynchronous operations as well: ```js async function getUser(id) { const user = await fetch(`/api/user/${id}`) return user } ``` ### `set` Sets a variable in a declarative way, with value `A` to value `B`. ```js let fruits = 0 function setFruits(nextFruits) { fruits = nextFruits } setFruits(5) console.log(fruits) // 5 ``` ### `reset` Sets a variable back to its initial value or state. ```js const initialFruits = 5 let fruits = initialFruits setFruits(10) console.log(fruits) // 10 function resetFruits() { fruits = initialFruits } resetFruits() console.log(fruits) // 5 ``` ### `remove` Removes something _from_ somewhere. For example, if you have a collection of selected filters on a search page, removing one of them from the collection is `removeFilter`, **not** `deleteFilter` (and this is how you would naturally say it in English as well): ```js function removeFilter(filterName, filters) { return filters.filter((name) => name !== filterName) } const selectedFilters = ['price', 'availability', 'size'] removeFilter('price', selectedFilters) ``` > See also [delete](#delete). ### `delete` Completely erases something from the realms of existence. Imagine you are a content editor, and there is that notorious post you wish to get rid of. Once you clicked a shiny "Delete post" button, the CMS performed a `deletePost` action, **not** `removePost`. ```js function deletePost(id) { return database.find({ id }).delete() } ``` > See also [remove](#remove). > **`remove` or `delete`?** > > When the difference between `remove` and `delete` is not so obvious to you, I'd suggest looking at their opposite actions - `add` and `create`. > The key difference between `add` and `create` is that `add` needs a destination while `create` **requires no destination**. You `add` an item _to somewhere_, but you don't "`create` it _to somewhere_". > Simply pair `remove` with `add` and `delete` with `create`. > > Explained in detail [here](https://github.com/kettanaito/naming-cheatsheet/issues/74#issue-1174942962). ### `compose` Creates new data from the existing one. Mostly applicable to strings, objects, or functions. ```js function composePageUrl(pageName, pageId) { return pageName.toLowerCase() + '-' + pageId } ``` > See also [get](#get). ### `handle` Handles an action. Often used when naming a callback method. ```js function handleLinkClick() { console.log('Clicked a link!') } link.addEventListener('click', handleLinkClick) ``` --- ## Context A domain that a function operates on. A function is often an action on _something_. It is important to state what its operable domain is, or at least an expected data type. ```js /* A pure function operating with primitives */ function filter(list, predicate) { return list.filter(predicate) } /* Function operating exactly on posts */ function getRecentPosts(posts) { return filter(posts, (post) => post.date === Date.now()) } ``` > Some language-specific assumptions may allow omitting the context. For example, in JavaScript, it's common that `filter` operates on Array. Adding explicit `filterArray` would be unnecessary. --- ## Prefixes Prefix enhances the meaning of a variable. It is rarely used in function names. ### `is` Describes a characteristic or state of the current context (usually `boolean`). ```js const color = 'blue' const isBlue = color === 'blue' // characteristic const isPresent = true // state if (isBlue && isPresent) { console.log('Blue is present!') } ``` ### `has` Describes whether the current context possesses a certain value or state (usually `boolean`). ```js /* Bad */ const isProductsExist = productsCount > 0 const areProductsPresent = productsCount > 0 /* Good */ const hasProducts = productsCount > 0 ``` ### `should` Reflects a positive conditional statement (usually `boolean`) coupled with a certain action. ```js function shouldUpdateUrl(url, expectedUrl) { return url !== expectedUrl } ``` ### `min`/`max` Represents a minimum or maximum value. Used when describing boundaries or limits. ```js /** * Renders a random amount of posts within * the given min/max boundaries. */ function renderPosts(posts, minPosts, maxPosts) { return posts.slice(0, randomBetween(minPosts, maxPosts)) } ``` ### `prev`/`next` Indicate the previous or the next state of a variable in the current context. Used when describing state transitions. ```jsx async function getPosts() { const prevPosts = this.state.posts const latestPosts = await fetch('...') const nextPosts = concat(prevPosts, latestPosts) this.setState({ posts: nextPosts }) } ``` ## Singular and Plurals Like a prefix, variable names can be made singular or plural depending on whether they hold a single value or multiple values. ```js /* Bad */ const friends = 'Bob' const friend = ['Bob', 'Tony', 'Tanya'] /* Good */ const friend = 'Bob' const friends = ['Bob', 'Tony', 'Tanya'] ``` --- ## Tools https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-012-bytewords.md ``` 0x00: able acid also apex aqua arch atom aunt 0x08: away axis back bald barn belt beta bias 0x10: blue body brag brew bulb buzz calm cash 0x18: cats chef city claw code cola cook cost 0x20: crux curl cusp cyan dark data days deli 0x28: dice diet door down draw drop drum dull 0x30: duty each easy echo edge epic even exam 0x38: exit eyes fact fair fern figs film fish 0x40: fizz flap flew flux foxy free frog fuel 0x48: fund gala game gear gems gift girl glow 0x50: good gray grim guru gush gyro half hang 0x58: hard hawk heat help high hill holy hope 0x60: horn huts iced idea idle inch inky into 0x68: iris iron item jade jazz join jolt jowl 0x70: judo jugs jump junk jury keep keno kept 0x78: keys kick kiln king kite kiwi knob lamb 0x80: lava lazy leaf legs liar limp lion list 0x88: logo loud love luau luck lung main many 0x90: math maze memo menu meow mild mint miss 0x98: monk nail navy need news next noon note 0xa0: numb obey oboe omit onyx open oval owls 0xa8: paid part peck play plus poem pool pose 0xb0: puff puma purr quad quiz race ramp real 0xb8: redo rich road rock roof ruby ruin runs 0xc0: rust safe saga scar sets silk skew slot 0xc8: soap solo song stub surf swan taco task 0xd0: taxi tent tied time tiny toil tomb toys 0xd8: trip tuna twin ugly undo unit urge user 0xe0: vast very veto vial vibe view visa void 0xe8: vows wall wand warm wasp wave waxy webs 0xf0: what when whiz wolf work yank yawn yell 0xf8: yoga yurt zaps zero zest zinc zone zoom ``` ## Errata - Duncan ShortCodes (used in obfuscation) - Symbols