原文链接:

https://medium.com/better-programming/a-useful-framework-for-naming-your-classes-functions-and-variables-e7d186e3189f

更新


[2021-1-3]

  • Initial release

[2021-2-5]

Changed

  • 更改文章标题

概述


原文链接:

https://medium.com/better-programming/a-useful-framework-for-naming-your-classes-functions-and-variables-e7d186e3189f

“在编程界, 命名规范是一个大的集合, 包含了众多的规则. 所谓的命名规范, 就是将一系列的字符排列组合为标识符, 用来表示 变量类型函数 以及源码和文档中的其它 实体.” —— Wikipedia

给一个东西命名确实很难!

这篇文章将致力于介绍 A/HC/LC 命名法, 希望这可以增强代码的可读性.

并且我将使用 JavaScript 来举例说明, 但实际上这种命名方式可以被应用到任何编程语言.

(P)A/HC/LC是什么?

实际上, (P)A/HC/LC 指的是使用下面的模式来命名一个函数.

1
prefix? + action (A) + high context (HC) + low context? (LC)

Prefix是什么?

prefix(前缀)增强函数的可读性.

- is

描述当前 context(语境) 的特征或状态, 通常是一个布尔值.

1
2
3
4
5
6
7
const color = 'blue'
const isBlue = (color === 'blue') // characteristic
const isPresent = true // state

if (isBlue && isPresent) {
console.log('Blue is present!')
}

- has

描述当前的 context(语境) 是否具有某个特定的值或者状态. 通常也是一个布尔值.

1
2
3
4
5
6
/* Bad */
const isProductsExist = (productsCount > 0)
const areProductsPresent = (productsCount > 0)

/* Good */
const hasProducts = (productsCount > 0)

- should

映射一个具有明确动作的条件语句, 通常也是一个布尔值.

1
2
3
function shouldUpdateUrl(url, expectedUrl) {
return (url !== expectedUrl)
}

函数的核心是Actions

Actions(动作) 是函数名的动词部分. 描述这个函数要做什么, 同样非常重要.

- get

获取数据

比如快捷的获取内部数据.

1
2
3
function getFruitsCount() {
return this.fruits.length;
}

- set

设置数据

比如将某个变量的值由 A 变为 B.

1
2
3
4
5
6
7
8
let fruits = 0

function setFruits(nextFruits) {
fruits = nextFruits
}

setFruits(5)
console.log(fruits) // 5

- reset

还原数据

比如将某个变量设置为其初始的值或状态

1
2
3
4
5
6
7
8
9
10
11
let initialFruits = 5
let fruits = initialFruits
setFruits(10)
console.log(fruits) // 10

function resetFruits() {
fruits = initialFruits
}

resetFruits()
console.log(fruits) // 5

- fetch

请求数据

通常是一个比较耗时的操作(比如: 异步请求).

1
2
3
function fetchPosts(postCount) {
return fetch('https://api.dev/posts', {...})
}

- remove

移除数据

逻辑上的删除, 某个数据可能只是被移动到了别的地方.

假设在搜索页面有一个筛选器, 可以通过 removeFilter 来移除筛选器中的某个值, 而不是 deleteFilter, 因为英语的表达方式更倾向于前者.

1
2
3
4
5
6
function removeFilter(filterName, filters) {
return filters.filter(name => name !== filterName)
}

const selectedFilters = ['price', 'availability', 'size']
removeFilter('price', selectedFilters)

- delete

删除数据

将某个数据彻底删除, 是物理上的删除.

可以想象如果你是一个文章审核员, 看到一篇很辣鸡的文章, 当你想彻底删除这篇文章并点击 删除文章 按钮的时候, CMS 会执行一个 deletePost 的删除动作, 而不是 removePost.

1
2
3
function deletePost(id) {
return database.find({ id }).delete()
}

- compose

组合数据

基于现有的数据来创建一个新的数据, 适用于字符串、对象和函数.

1
2
3
function composePageUrl(pageName, pageId) {
return `${pageName.toLowerCase()}-${pageId}`
}

- handle

处理数据

处理某个动作, 通常用来声明一个回调函数.

1
2
3
4
5
function handleLinkClick() {
console.log('Clicked a link!')
}

link.addEventListener('click', handleLinkClick)

最后是Context

context 是一个域, 指代当前函数的执行环境.

函数通常是处理某件事的一个动作, 所以注明函数所属的域, 或者至少注明一个预期的数据类型是很重要的.

1
2
3
4
5
6
7
8
9
10
11
/* 基于内置方法的纯函数 */
function filter(predicate, list) {
return list.filter(predicate)
}
/* 确切的表明这个函数是处理 posts 的 */
function getRecentPosts(posts) {
return filter(posts, (post) => post.date === Date.now())
}
/*
一些编程语言允许你省略 context, 比如在 JavaScript 中 filter 方法只存在于数组上, 所以没必要给函数添加 context.
*/

综上所述

3.png

命名参照表

变量命名的5个参考

本区块将着重介绍一些可以提高代码可读性的变量命名技巧.

4.jpeg

1. 遵循 S-I-D 原则

命名必须具备简洁(Short)、直观(Intuitive)、语义化(Descriptive)这三个特点.

1
2
3
4
/* Bad */
const a = 5 // "a" 没有什么含义
const isPaginatable = (postsCount > 10) // "Paginatable" 听起来很不自然
const shouldPaginatize = (postsCount > 10) // "Paginatize" 编造一个动词更加荒谬!

建议:

1
2
3
4
/* Good */
const postsCount = 5
const hasPagination = (postsCount > 10)
const shouldDisplayPagination = (postsCount > 10) // alternatively

2. 避免缩写

不要使用缩写形式, 这会降低代码可读性. 起一个简短并且语义化的名称可能有点难度, 但是不要让这成为你使用缩写的借口, 举个例子:

1
2
3
4
5
/* Bad */
const onItmClk = () => {}

/* Good */
const onItemClick = () => {}

3. 避免重复的上下文

如果命名中的 context 存在与否不会降低其可读性的话, 最好还是移除它:

1
2
3
4
5
6
7
class MenuItem {
/* 命名中的 "MenuItem" 与类名的域重复 */
handleMenuItemClick = (event) => { ... }

/* 去掉 "MenuItem", 看起来更简洁 */
handleClick = (event) => { ... }
}

4. 应该映射预期结果

1
2
3
4
5
6
7
/* Bad */
const isEnabled = (itemsCount > 3)
return <Button disabled={!isEnabled} />

/* Good */
const isDisabled = (itemsCount <= 3)
return <Button disabled={isDisabled} />

5. 考虑单数和复数形式

因为一个变量可能拥有单个或多个值, 所以命名的时候也要考虑单数和复数形式.

我写这篇文章是受到这个 Github 仓库的启发, 同时感谢大家的阅读, 编码愉快!