forked from extern/naming-cheatsheet
352 lines
8.5 KiB
Markdown
352 lines
8.5 KiB
Markdown
<p align="center">
|
|
<a href="https://github.com/kettanaito/naming-cheatsheet">
|
|
<img src="./naming-cheatsheet.png" alt="Naming cheatsheet" />
|
|
</a>
|
|
</p>
|
|
|
|
# Naming cheatsheet
|
|
|
|
- [Naming convention](#naming-convention)
|
|
- [S-I-D](#s-i-d)
|
|
- [Avoid contractions](#avoid-contractions)
|
|
- [Avoid context duplication](#avoid-context-duplication)
|
|
- [Reflect expected result](#reflect-expected-result)
|
|
- Naming functions
|
|
- [A/HC/LC pattern](#ahclc-pattern)
|
|
- [Actions](#actions)
|
|
- [Context](#context)
|
|
- [Prefixes](#prefixes)
|
|
- [Singular and Plurals](#singular-and-plurals)
|
|
|
|
---
|
|
|
|
Naming things is hard. This sheet attempts to make it easier.
|
|
|
|
Although these suggestions can be applied to any programming language, I will use JavaScript to illustrate them in practice.
|
|
|
|
## Naming convention
|
|
|
|
Pick **one** naming convention and follow it. It may be `camelCase`, or `snake_case`, or anyhow else, it does not matter. What matters is for it to remain consistent.
|
|
|
|
```js
|
|
/* Bad */
|
|
const pages_count = 5
|
|
const shouldUpdate = true
|
|
|
|
/* Good */
|
|
const pagesCount = 5
|
|
const shouldUpdate = true
|
|
|
|
/* Good as well */
|
|
const pages_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 = postsCount > 10 // "Paginatable" sounds extremely unnatural
|
|
const shouldPaginatize = postsCount > 10 // Made up verbs are so much fun!
|
|
|
|
/* Good */
|
|
const postsCount = 5
|
|
const hasPagination = postsCount > 10
|
|
const shouldDisplayPagination = postsCount > 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 expected result
|
|
|
|
A name should reflect the expected result.
|
|
|
|
```jsx
|
|
/* Bad */
|
|
const isEnabled = itemsCount > 3
|
|
return <Button disabled={!isEnabled} />
|
|
|
|
/* Good */
|
|
const isDisabled = itemsCount <= 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) |
|
|
| ---------------------- | -------- | ---------- | ----------------- | ---------------- |
|
|
| `getPost` | | `get` | `Post` | |
|
|
| `getPostData` | | `get` | `Post` | `Data` |
|
|
| `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 whether it should do that right now.
|
|
> 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 getFruitsCount() {
|
|
return this.fruits.length
|
|
}
|
|
```
|
|
|
|
> See also [compose](#compose).
|
|
|
|
### `set`
|
|
|
|
Declaratively sets a variable with value `A` to value `B`.
|
|
|
|
```js
|
|
const 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
|
|
const fruits = initialFruits
|
|
setFruits(10)
|
|
console.log(fruits) // 10
|
|
|
|
function resetFruits() {
|
|
fruits = initialFruits
|
|
}
|
|
|
|
resetFruits()
|
|
console.log(fruits) // 5
|
|
```
|
|
|
|
### `fetch`
|
|
|
|
Requests for a data, which takes time (i.e. async request).
|
|
|
|
```js
|
|
function fetchPosts(postCount) {
|
|
return fetch('https://api.dev/posts', {...})
|
|
}
|
|
```
|
|
|
|
### `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 erazes 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).
|
|
|
|
### `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 is its operable domain, or at least an expected data type.
|
|
|
|
```js
|
|
/* A pure function operating with primitives */
|
|
function filter(predicate, list) {
|
|
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`
|
|
|
|
Represent minimum or maximum value. Used when describing boundaries or limits.
|
|
|
|
```js
|
|
/**
|
|
* Renders 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
|
|
function fetchPosts() {
|
|
const prevPosts = this.state.posts
|
|
|
|
const fetchedPosts = fetch('...')
|
|
const nextPosts = concat(prevPosts, fetchedPosts)
|
|
|
|
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']
|
|
```
|