主题思想

代码应当易于理解
可读性:代码写法应当使别人理解它所需的时间最小化

把信息装到名字里

选择专业的词

选择专业的词,避免使用“空洞”的词;

  • get => fetchpage、downloadpage
  • size => Hegiht、NumNodes | 单词 | 更多选择 | | —- | —- | | send | deliver、dispatch、announce、distribute、route | | find | search、extract、locate、recover | | start | launch、create、begin、open | | make | create、setup、build、generate、compose、add、new |

避免泛泛名字

实在想不出来,可以描述这个实体的值或者目的名字。好的名字应当描述变量的目的或者所承载的值。

使用前缀货或后缀来给名字带来更多的信息

  • 带单位的值:变量是度量xx_ms、xxMs
  • 其他附带存在危险或者是意外的任何时候可以使用 xxx_password、html_utf8

    决定名字的长度

  • 首字字母缩略词和缩词

  • 在小的上下文里使用短的名字

    利用名字格式表达含义

  • 有目的地使用大小写、下划线

    避免使用误解名字

    阅读代码的应该理解写的本意,不会有歧义;

  1. 值的上下限:max/min
  2. 包含范围:first/last
  3. 包含/排除范围:begin/end
  4. 布尔值:is/has

    审美

    原则

  5. 使用一致的布局,让读者习惯风格

  6. 让相似的代码看上去相似
  7. 把相关的代码行分组,形成代码块

    技巧

  • 把代码按“列”对齐更容易浏览
  • 始终保持代码块顺序;在一个代码提到是a,b,c,在其他地方不是c、b、a

    注释

    注释的目的是帮助读者了解作者写代码时已经知道一些事情。
    什么地方不需要注释

  • 能从代码本身迅速推断事实

  • 可以使用代码表明语义,注释就没必要了

记录想法

  • 指导性批注
  • 代码中缺陷,使用TODO:或者xxx
  • 常量背后的故事

站在读者的立场上思考

  • 预料代码中那些部分,阅读者会产生疑问
  • 用注释来总结代码块,使读者不会迷失细节中

    言简意赅的注释

  • 避免使用不明确的英文,如:“this、it”

  • 尽量精确描述函数的行为
  • 在注释中明确挑选输入输出的例子说明
  • 声明代码的高层次意图,而非明显的细节

控制流变得易读

  • 写比较值判断,把改变值写在左边并且把更稳定的值写在右边
  • 可重排if/esle 语句中的语句块,正确/简单/有其他情况
  • 减少编程结构复杂,如三目运算符,do/while循环,
  • 嵌套代码需要更加集中精力去理解,每层新的嵌套都需要把更多的上下文“压入栈”。应该把它们改成更加“线性”的代码条件语句中参数顺序

    条件语句中参数顺序

    1. function test() {
    2. if(length >= 10) {
    3. }
    4. if(10 >= length) {
    5. }
    6. ....
    7. }

    对于大多数程序员,来说第一个判断,更易读一些

比较左侧 比较右侧
“被问询”的表达式,它的值更倾向于不断变化 用来做比较的表达式,更倾向于常量

if/else 语句块顺序

  • 首先处理正逻辑而不是负逻辑。如“if(debug) 而不是if(!debug)
  • 先处理简单的情况,最好能在可视屏幕内
  • 先处理正常逻辑,再处理其他异常情况

    提早返回

    1. function test() {
    2. if(xxx) {
    3. return
    4. }
    5. if(xxx) {
    6. return
    7. }
    8. ....
    9. }
    提早返回可以减少嵌套并让代码整洁,“**保护语句**”(在函数顶部处理简单的情况)

    减少循环嵌套

    判断使用continue
    1. function test() {
    2. let count = 0
    3. for(let i =0;i < results.length; i++) {
    4. if(ressult[i] != null) {
    5. count++;
    6. if(result[i].name !="") {
    7. console.log(results);
    8. }
    9. }
    10. }
    11. // 改成
    12. for(let i =0;i < results.length; i++) {
    13. if(ressult[i] == null) continue
    14. count++;
    15. if(result[i].name =="") continue
    16. console.log(results);
    17. }
    18. }

    拆分表达式

    解释变量

    1. function test() {
    2. if(line.split(':')[0].strip() == "root") {
    3. }
    4. // 改成
    5. const username = line.split(':')[0].strip();
    6. if(username == "root") {
    7. }
    8. }

引入“解释变量”来代表较长的子表达式,有三个好处

  • 把巨大的表达式拆成小段
  • 通过简单的名字描述子表达式让代码文档化
  • 帮助读者识别代码中的主要概念

    总结变量

    如果一个表达式不需要解释,可以把它装入一个新的变量中仍然是有用的。

    1. function test() {
    2. if(request.user.id == document.owner_id) {
    3. }
    4. // 改成
    5. const user_owns_document = request.user.id == document.owner_id;
    6. if(user_owns_document) {
    7. }
    8. }

    使用摩尔根定理

    1. !(a || b || c) == !a && !b && !c
    2. !(a && b && c) == !a || !b || !c

    变量与可读性

  • 减少变量:操作一个变量的地方越多,越难确定它的当前值

  • 减少每个变量的作用域,越小越好,把变量移到一个有最少代码可以看到的地方
  • 只写一次的变量更好

    抽取不相关的子问题

    “把一般代码和项目专有的代码分开”,大部分代码都是一般代码,通过建立一大组库和辅助函数解决一般问题,剩下的只是让你的程序与众不同的核心部分。
    可以使程序员关注小而定义良好的问题。

    一次只做一件事

    尽量把任务拆分到不同的函数中,在不同的代码段落中。

少写代码

  1. 从项目中小锤不必要的功能,不要过度设计
  2. 重新考虑需求,解决版本最简单的问题,只要能完成工作就行
  3. 经常性地通读标准库的整个API,保持对它们的熟悉程度