JS 优雅指南.2

原文发布与个人博客 lambdas.devhtml


接上文,在 JS 优雅指南 - 1 中咱们聊到了基础的 JavaScript 编程指南,包括如何可靠的声明变量、常量、函数、以及利用函数正确的构建逻辑,如今咱们思考改善代码质量的第一步,如何命名。git

在阅读代码之初,编码的风格与命名会比抽象方式、设计技巧更令咱们印象深入,不少时候也会为项目的风格定下基调。好比当你阅读一些算法工程师写的代码块,经常会见到 单字母变量反复的声明不知因此的赋值与拷贝累赘的条件判断 等等,咱们不能说这里有问题,由于他们的代码大多的的确确是能够正常工做的,甚至在性能或储存空间上有一些优点, 但这在工程,特别是大型工程中是不值得称道的。根据经验咱们能够这类代码归类为 "糊屎",充其量是 "糊" 了一滩高性能的 "屎"。程序员

如今咱们作的是脱离 "编程只不过是工具" 的阶段,脱离 "糊屎男孩",让机器面有喜色、富有人性,使阅读者在某个瞬间切实地感觉到创做者的思惟热情与审美哲学。github


1. 富有准确性的命名

事实上,你彻底可使用 doSomeThing 代替全部的函数,毕竟它们真的只是提供某些微不足道的功能,但当你有了多个甚至是成百上千的函数时,这是一个灾难。 这是一个浅显易懂的道理,即使是毫无经验的开发人员也会意识到命名爆炸的问题,他们隐约明白了什么是好的编程风格,但最后,甚至是大多数都止步于 doSomeThing 到 "优美" 的 某一站上。正则表达式

"这就够了" —— 他们这样告诉本身。算法

例 1, 命名只须要有必要的词,除非有必要,不然不要堆砌数据库

// bad
const theBook = {}
const _b = {}
const bookObj = {}
const newBook = {}

// good
const book = {}
复制代码

例 2,可读的条件判断编程

// bad
if (username && username.includes('prefix-')) {}

// bad
const prefix = username && username.includes('prefix-')

// bad
const availableName = username && username.includes('prefix-')

// good
const hasPrefixName = username && username.includes('prefix-')
复制代码

例 3,可读的函数markdown

当咱们要从网络上获取用户信息时,getUser 就不是一个准确的表达,get 过于宽泛,从数据库或网络、以用户名或 ID 都有区别,如今咱们能够先从 命名上思考它们的区别:网络

// bad
const getUser = name => {}
复制代码
// good
const fetchUsersByName = name => {}

// good
const findOneUserByID = id => {}

// good (any environment, any params)
const getUsers = (...params) => {}
复制代码

例 4,准确的表达

属性能够避免没必要要的描述,言简意赅:

// bad
const book = {
  bookname: '',
  length: '',
}

// good
const book = {
  title: '',
  pages: '',
}
func(book.title)
复制代码

注意单复数:

// bad
const book = findBooks()

// good
const books = findBooks()
复制代码

例 5,没必要要的约定

一般在示例或无心义的遍历中,咱们会把每个回调函数的参数写做 item / value / v 等等,这在一些场景的确可让阅读者忽略掉没必要要的描述, 专一于逻辑自己,但并不是老是合适的,特别是咱们须要表达状态时:

// bad
const titles = books
  .map(item => item.title)
  .filter(item => item.length > 0)
  
// good
const titles = books
  .map(book => book.title)
  .filter(title => title.length > 0)
复制代码

2. 观察与思考

观察是一个模糊的界定,能够尝试让同事朋友阅读你的代码,问问他们的感觉,哪些命名生硬,哪些词不达意,哪些是感同身受的。 一个可学习的方式是在 github 上阅读代码,你也能注意到开发者们情绪的波动,这里真的须要这些定义吗、这里有必要写的这么短小吗、这是否是太 OC 了…… 试图理解开发者创做时想法是很天然的,这些情绪的波动能让你明白他们大约处于编程、人生、情感的什么状态,有助于你深入的理解接口与设计。

在一个项目中见到 created 时,即可以知道这调用在 create 以后 (而非以前或之中),依次类推即可以有 destroyed 或其余函数,若是项目来自是富有经验的开发者, 这些细节会帮助你在代码中极快的理解做者的构思。

又如在 暴雪的官方 API 文档 中能够见到 GetRewardSpell 接口,既然有 reward spell, 咱们能够推断天然是有 GetRewardXPGetRewardMoney 一类接口,而它们的参数天然也相差很少。真的是这样吗?不,彻底不是, 当你阅读几十分钟的文档后才会明白,这些接口创造之初或许有一些设计,但在各个版本的补丁与不断的重构后已面目全非,尽管命名的结构相差无几参数却截然不同。 在不断的阅读后将你开始注意到从新命名的接口、参数、返回值彷佛正在朝某个方向改进,他们彷佛在修补一些问题。

在阅读 暴雪界面源码 后咱们更能注意到这些细节,一些界面功能被改变了,程序员们只能被迫去修改这些接口, 同时想要与原有的保持的一些同步,有时也会衍生出一些新的接口,它们被置于一些结构体中,随着时间的推移能够推理, 将来的一些接口也会被移入这些结构体 —— 这就是咱们对于命名的观察与思考。我曾经见过有人说 "狗是人类的朋友,taobao 的文档连狗都不如", 这就是他观察的结果了,虽然使人不那么开心。


3.巧妙与投机取巧

咱们能够判定 巧妙 是优雅命名中重要的一部分,如在 rvm 与其余一些命令行工具中的 uninstall 就是 implode,这有点意思,是吧。但事实上我见到 绝大多数的巧妙不过是 "投机取巧",他们苦心孤诣的做品是一大段没有说明的八进制、二进制代码,一堆三元堆砌的单行逻辑,一些谐音名字,不合时宜地正则表达式等等,这 并不漂亮,这是歧路。

例 1,自做聪明的谐音

// bad
const markdown2html = template => {}

// good
const markdownToHTML = template => {}
复制代码

例 2,能够语义化的正则

代码并不是越简短越好,多数场景下咱们须要尽量的避免长篇累牍,但必要时,可使用命名和语义化的代码块来试图说明逻辑:

// bad
const isUser = /^name/.test(user.name) && /^http/.test(user.blog)

// good
const isUserName = user.name.startsWith('name')
const isUserBlog = user.blog.startsWith('http')
const isUser = isUserName && isUserBlog
复制代码

例 3,优美

// bad
const hasDirOrCreateDir = path => {}

// good
const ensureDir = path => {}
复制代码
// bad
const moveCursorToLastLine = () => {}

// good
const cursorUp = () => {}
const cursorDown = () => {}
复制代码

连接

相关文章
相关标签/搜索