|
| 1 | +--- |
| 2 | +title: "Naming cheatsheet【转】" |
| 3 | +date: 2022-04-08 |
| 4 | +draft: false |
| 5 | + |
| 6 | +description: Naming cheatsheet |
| 7 | +author: kettanaito |
| 8 | +tags: ["命名", "转载"] |
| 9 | +--- |
| 10 | +[原文](https://github.com/kettanaito/naming-cheatsheet) |
| 11 | + |
| 12 | +# Naming cheatsheet |
| 13 | + |
| 14 | +- [English language](#english-language) |
| 15 | +- [Naming convention](#naming-convention) |
| 16 | +- [S-I-D](#s-i-d) |
| 17 | +- [Avoid contractions](#avoid-contractions) |
| 18 | +- [Avoid context duplication](#avoid-context-duplication) |
| 19 | +- [Reflect the expected result](#reflect-the-expected-result) |
| 20 | +- [Naming functions](#naming-functions) |
| 21 | + - [A/HC/LC pattern](#ahclc-pattern) |
| 22 | + - [Actions](#actions) |
| 23 | + - [Context](#context) |
| 24 | + - [Prefixes](#prefixes) |
| 25 | +- [Singular and Plurals](#singular-and-plurals) |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +Naming things is hard. This sheet attempts to make it easier. |
| 30 | + |
| 31 | +Although these suggestions can be applied to any programming language, I will use JavaScript to illustrate them in practice. |
| 32 | + |
| 33 | +## English language |
| 34 | + |
| 35 | +Use English language when naming your variables and functions. |
| 36 | + |
| 37 | +```js |
| 38 | +/* Bad */ |
| 39 | +const primerNombre = 'Gustavo' |
| 40 | +const amigos = ['Kate', 'John'] |
| 41 | + |
| 42 | +/* Good */ |
| 43 | +const firstName = 'Gustavo' |
| 44 | +const friends = ['Kate', 'John'] |
| 45 | +``` |
| 46 | + |
| 47 | +> 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. |
| 48 | +
|
| 49 | +## Naming convention |
| 50 | + |
| 51 | +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! |
| 52 | + |
| 53 | +```js |
| 54 | +/* Bad */ |
| 55 | +const page_count = 5 |
| 56 | +const shouldUpdate = true |
| 57 | + |
| 58 | +/* Good */ |
| 59 | +const pageCount = 5 |
| 60 | +const shouldUpdate = true |
| 61 | + |
| 62 | +/* Good as well */ |
| 63 | +const page_count = 5 |
| 64 | +const should_update = true |
| 65 | +``` |
| 66 | + |
| 67 | +## S-I-D |
| 68 | + |
| 69 | +A name must be _short_, _intuitive_ and _descriptive_: |
| 70 | + |
| 71 | +- **Short**. A name must not take long to type and, therefore, remember; |
| 72 | +- **Intuitive**. A name must read naturally, as close to the common speech as possible; |
| 73 | +- **Descriptive**. A name must reflect what it does/possesses in the most efficient way. |
| 74 | + |
| 75 | +```js |
| 76 | +/* Bad */ |
| 77 | +const a = 5 // "a" could mean anything |
| 78 | +const isPaginatable = a > 10 // "Paginatable" sounds extremely unnatural |
| 79 | +const shouldPaginatize = a > 10 // Made up verbs are so much fun! |
| 80 | + |
| 81 | +/* Good */ |
| 82 | +const postCount = 5 |
| 83 | +const hasPagination = postCount > 10 |
| 84 | +const shouldPaginate = postCount > 10 // alternatively |
| 85 | +``` |
| 86 | + |
| 87 | +## Avoid contractions |
| 88 | + |
| 89 | +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. |
| 90 | + |
| 91 | +```js |
| 92 | +/* Bad */ |
| 93 | +const onItmClk = () => {} |
| 94 | + |
| 95 | +/* Good */ |
| 96 | +const onItemClick = () => {} |
| 97 | +``` |
| 98 | + |
| 99 | +## Avoid context duplication |
| 100 | + |
| 101 | +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. |
| 102 | + |
| 103 | +```js |
| 104 | +class MenuItem { |
| 105 | + /* Method name duplicates the context (which is "MenuItem") */ |
| 106 | + handleMenuItemClick = (event) => { ... } |
| 107 | + |
| 108 | + /* Reads nicely as `MenuItem.handleClick()` */ |
| 109 | + handleClick = (event) => { ... } |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +## Reflect the expected result |
| 114 | + |
| 115 | +A name should reflect the expected result. |
| 116 | + |
| 117 | +```jsx |
| 118 | +/* Bad */ |
| 119 | +const isEnabled = itemCount > 3 |
| 120 | +return <Button disabled={!isEnabled} /> |
| 121 | + |
| 122 | +/* Good */ |
| 123 | +const isDisabled = itemCount <= 3 |
| 124 | +return <Button disabled={isDisabled} /> |
| 125 | +``` |
| 126 | + |
| 127 | +--- |
| 128 | + |
| 129 | +# Naming functions |
| 130 | + |
| 131 | +## A/HC/LC Pattern |
| 132 | + |
| 133 | +There is a useful pattern to follow when naming functions: |
| 134 | + |
| 135 | +``` |
| 136 | +prefix? + action (A) + high context (HC) + low context? (LC) |
| 137 | +``` |
| 138 | + |
| 139 | +Take a look at how this pattern may be applied in the table below. |
| 140 | + |
| 141 | +| Name | Prefix | Action (A) | High context (HC) | Low context (LC) | |
| 142 | +| ---------------------- | -------- | ---------- | ----------------- | ---------------- | |
| 143 | +| `getUser` | | `get` | `User` | | |
| 144 | +| `getUserMessages` | | `get` | `User` | `Messages` | |
| 145 | +| `handleClickOutside` | | `handle` | `Click` | `Outside` | |
| 146 | +| `shouldDisplayMessage` | `should` | `Display` | `Message` | | |
| 147 | + |
| 148 | +> **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. |
| 149 | +> In other words, **high context emphasizes the meaning of a variable**. |
| 150 | +
|
| 151 | +--- |
| 152 | + |
| 153 | +## Actions |
| 154 | + |
| 155 | +The verb part of your function name. The most important part responsible for describing what the function _does_. |
| 156 | + |
| 157 | +### `get` |
| 158 | + |
| 159 | +Accesses data immediately (i.e. shorthand getter of internal data). |
| 160 | + |
| 161 | +```js |
| 162 | +function getFruitCount() { |
| 163 | + return this.fruits.length |
| 164 | +} |
| 165 | +``` |
| 166 | + |
| 167 | +> See also [compose](#compose). |
| 168 | +
|
| 169 | +### `set` |
| 170 | + |
| 171 | +Sets a variable in a declarative way, with value `A` to value `B`. |
| 172 | + |
| 173 | +```js |
| 174 | +let fruits = 0 |
| 175 | + |
| 176 | +function setFruits(nextFruits) { |
| 177 | + fruits = nextFruits |
| 178 | +} |
| 179 | + |
| 180 | +setFruits(5) |
| 181 | +console.log(fruits) // 5 |
| 182 | +``` |
| 183 | + |
| 184 | +### `reset` |
| 185 | + |
| 186 | +Sets a variable back to its initial value or state. |
| 187 | + |
| 188 | +```js |
| 189 | +const initialFruits = 5 |
| 190 | +let fruits = initialFruits |
| 191 | +setFruits(10) |
| 192 | +console.log(fruits) // 10 |
| 193 | + |
| 194 | +function resetFruits() { |
| 195 | + fruits = initialFruits |
| 196 | +} |
| 197 | + |
| 198 | +resetFruits() |
| 199 | +console.log(fruits) // 5 |
| 200 | +``` |
| 201 | + |
| 202 | +### `fetch` |
| 203 | + |
| 204 | +Request for some data, which takes some indeterminate time (i.e. async request). |
| 205 | + |
| 206 | +```js |
| 207 | +function fetchPosts(postCount) { |
| 208 | + return fetch('https://api.dev/posts', {...}) |
| 209 | +} |
| 210 | +``` |
| 211 | + |
| 212 | +### `remove` |
| 213 | + |
| 214 | +Removes something _from_ somewhere. |
| 215 | + |
| 216 | +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): |
| 217 | + |
| 218 | +```js |
| 219 | +function removeFilter(filterName, filters) { |
| 220 | + return filters.filter((name) => name !== filterName) |
| 221 | +} |
| 222 | + |
| 223 | +const selectedFilters = ['price', 'availability', 'size'] |
| 224 | +removeFilter('price', selectedFilters) |
| 225 | +``` |
| 226 | + |
| 227 | +> See also [delete](#delete). |
| 228 | +
|
| 229 | +### `delete` |
| 230 | + |
| 231 | +Completely erases something from the realms of existence. |
| 232 | + |
| 233 | +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`. |
| 234 | + |
| 235 | +```js |
| 236 | +function deletePost(id) { |
| 237 | + return database.find({ id }).delete() |
| 238 | +} |
| 239 | +``` |
| 240 | + |
| 241 | +> See also [remove](#remove). |
| 242 | +
|
| 243 | +### `compose` |
| 244 | + |
| 245 | +Creates new data from the existing one. Mostly applicable to strings, objects, or functions. |
| 246 | + |
| 247 | +```js |
| 248 | +function composePageUrl(pageName, pageId) { |
| 249 | + return (pageName.toLowerCase() + '-' + pageId) |
| 250 | +} |
| 251 | +``` |
| 252 | + |
| 253 | +> See also [get](#get). |
| 254 | +
|
| 255 | +### `handle` |
| 256 | + |
| 257 | +Handles an action. Often used when naming a callback method. |
| 258 | + |
| 259 | +```js |
| 260 | +function handleLinkClick() { |
| 261 | + console.log('Clicked a link!') |
| 262 | +} |
| 263 | + |
| 264 | +link.addEventListener('click', handleLinkClick) |
| 265 | +``` |
| 266 | + |
| 267 | +--- |
| 268 | + |
| 269 | +## Context |
| 270 | + |
| 271 | +A domain that a function operates on. |
| 272 | + |
| 273 | +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. |
| 274 | + |
| 275 | +```js |
| 276 | +/* A pure function operating with primitives */ |
| 277 | +function filter(list, predicate) { |
| 278 | + return list.filter(predicate) |
| 279 | +} |
| 280 | + |
| 281 | +/* Function operating exactly on posts */ |
| 282 | +function getRecentPosts(posts) { |
| 283 | + return filter(posts, (post) => post.date === Date.now()) |
| 284 | +} |
| 285 | +``` |
| 286 | + |
| 287 | +> 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. |
| 288 | +
|
| 289 | +-- |
| 290 | + |
| 291 | +## Prefixes |
| 292 | + |
| 293 | +Prefix enhances the meaning of a variable. It is rarely used in function names. |
| 294 | + |
| 295 | +### `is` |
| 296 | + |
| 297 | +Describes a characteristic or state of the current context (usually `boolean`). |
| 298 | + |
| 299 | +```js |
| 300 | +const color = 'blue' |
| 301 | +const isBlue = color === 'blue' // characteristic |
| 302 | +const isPresent = true // state |
| 303 | + |
| 304 | +if (isBlue && isPresent) { |
| 305 | + console.log('Blue is present!') |
| 306 | +} |
| 307 | +``` |
| 308 | + |
| 309 | +### `has` |
| 310 | + |
| 311 | +Describes whether the current context possesses a certain value or state (usually `boolean`). |
| 312 | + |
| 313 | +```js |
| 314 | +/* Bad */ |
| 315 | +const isProductsExist = productsCount > 0 |
| 316 | +const areProductsPresent = productsCount > 0 |
| 317 | + |
| 318 | +/* Good */ |
| 319 | +const hasProducts = productsCount > 0 |
| 320 | +``` |
| 321 | + |
| 322 | +### `should` |
| 323 | + |
| 324 | +Reflects a positive conditional statement (usually `boolean`) coupled with a certain action. |
| 325 | + |
| 326 | +```js |
| 327 | +function shouldUpdateUrl(url, expectedUrl) { |
| 328 | + return url !== expectedUrl |
| 329 | +} |
| 330 | +``` |
| 331 | + |
| 332 | +### `min`/`max` |
| 333 | + |
| 334 | +Represents a minimum or maximum value. Used when describing boundaries or limits. |
| 335 | + |
| 336 | +```js |
| 337 | +/** |
| 338 | + * Renders a random amount of posts within |
| 339 | + * the given min/max boundaries. |
| 340 | + */ |
| 341 | +function renderPosts(posts, minPosts, maxPosts) { |
| 342 | + return posts.slice(0, randomBetween(minPosts, maxPosts)) |
| 343 | +} |
| 344 | +``` |
| 345 | + |
| 346 | +### `prev`/`next` |
| 347 | + |
| 348 | +Indicate the previous or the next state of a variable in the current context. Used when describing state transitions. |
| 349 | + |
| 350 | +```jsx |
| 351 | +function fetchPosts() { |
| 352 | + const prevPosts = this.state.posts |
| 353 | + |
| 354 | + const fetchedPosts = fetch('...') |
| 355 | + const nextPosts = concat(prevPosts, fetchedPosts) |
| 356 | + |
| 357 | + this.setState({ posts: nextPosts }) |
| 358 | +} |
| 359 | +``` |
| 360 | + |
| 361 | +## Singular and Plurals |
| 362 | + |
| 363 | +Like a prefix, variable names can be made singular or plural depending on whether they hold a single value or multiple values. |
| 364 | + |
| 365 | +```js |
| 366 | +/* Bad */ |
| 367 | +const friends = 'Bob' |
| 368 | +const friend = ['Bob', 'Tony', 'Tanya'] |
| 369 | + |
| 370 | +/* Good */ |
| 371 | +const friend = 'Bob' |
| 372 | +const friends = ['Bob', 'Tony', 'Tanya'] |
| 373 | +``` |
0 commit comments