BING
Surmon's digital vihara
OG

简洁编码指南

3,472 characters, 9 min read2017/04/11 PM4,805 views

#就三点:

  • 编码风格:忌简忌繁、统一风格
  • 编码结构:模块化、函数式、易读性、复用元素的抽象
  • 编码过程:扩展能力、测试

#编码风格

保持良好的编码风格

  • 不要刻意简写难以理解的表达式,也不要嵌套过于冗余的函数
  • 缩进统一、命名统一、标符统一、文件结构统一... 一切能以标准量化的的都需要拿标准约束
  • Lint 等 QA 约束工具是必须的,用工具来实践程序正义

更详细的编码规范,可以来这: Developer code guide

#编码结构

Spaghetti code (面条代码)的特征

  • 代码没有组织,且多处出现重复的代码块

    • 一般是封装粒度不够造成
  • 多个代码块之间高度耦合,跳来跳去,使其难以调试

    • 函数抽象程度不够
    • OOP 理解不深刻
    • 典型的命令式编程
  • 代码不会分解成条件块或标签,使其难以阅读。

    • 到这个程度就不知道代码写的有多糟了

避免面条代码的方法

  • 需要复用的代码一定要封装
  • “模块化” 不仅仅是文件意义的模块化,而是指逻辑单元的模块化,比如函数;当然现在大部分框架、库、平台... 都有自己成熟的模块化系统,在模块化的基础上尽量取得平衡
  • 函数的模块化和封装要尽量地 “函数式”,不依赖外部变量,不改变外部变量,有输入,有输出,不过度嵌套,中间量清晰易读
  • 避免全局变量和类成员传递数据,函数内部更应该优先使用局部变量和参数变量
  • 优秀的代码是不需要注释的,所以命名本身很重要很重要

优秀的代码组织应该是清晰的树状结构,自上而下分解任务, 自下而上完成任务。

#编码过程

防止 over-engineering (过度设计)

过度设计是指,太过于考虑今后代码的扩展性、复用性,或太过于考虑测试的便利性,导致系统被过度设计为难以理解、难以重用的复杂结构。

世界上有两种 “没有 BUG” 的代码。一种是“没有明显 BUG 的代码”,另一种是 “明显没有 BUG 的代码”。

第一种情况,由于代码复杂不堪,加上很多测试,各种 coverage,看起来测试都通过了,所以就认为代码是正确的。

第二种情况,由于代码简单直接,就算没写很多测试,你一眼看去就知道它不可能有 BUG。

你钟爱哪一种?

防止过度设计的方法:

  • 先把眼前的问题解决掉,解决好,再考虑将来的扩展问题
  • 先写出可用的代码,反复推敲,再考虑是否需要重用的问题
  • 先写出可用,简单,明显没有 BUG 的代码,再考虑测试的问题

代码规范可以参考上面链接就可以了,可以根据自己的情况修改规范以建立自己的标准,下面分享一些平日较为不易理解的代码片段。

#隐式转换

==!= 操作符会在需要的情况下自动转换数据类型; ===!== 不会,它们会同时比较值和数据类型,也称为严格比较。

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
[10] === 10 // false [10] == 10 // true '10' == 10 // true '10' === 10 // false [] == 0 // true [] === 0 // false '' == false // true (but true == "a" is false,因为true隐式转换为字符串为'1') '' === false // false

#赋值判断

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
// 正常流程 var a if (b) { a = b } else { a = c } // 三目运算 var a = b ? b : c // 利用短路运算判断赋值 var a = b || c

#数据类型判断 typeofinstanceof

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
/* typeof 会返回一个变量的基本类型,针对数组和对象均返回 'object' */ typeof 666 // 'number' typeof Date() // 'string' typeof [] // 'object' typeof {} // 'object' typeof false // 'boolean' typeof new Function() // 'function' typeof undefined // 'undefined' typeof null // 'object' /* instanceof 仅检测对象的原型链是否指向构造函数的 prototype 对象 由于 JavaScript 中万物皆对象,故一切用 new 关键字实例的对象最深原型永远指向 Object */ 666 instanceof Number // false new Number(666) instanceof Number // true new Number(666) instanceof Object // true '666' instanceof String // false new String('666') instanceof String // true new Object() instanceof Object // true [] instanceof Object // true [] instanceof Array // true new Date() instanceof Date // true new Date() instanceof Object // true

#快速求和

          
  • 1
  • 2
  • 3
// eval 能做的事真的太多了 var nums = [1, 2, 3, 4, 5, 6...] console.log('和:', eval(nums.join('+')))

#简写判断

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
// 标准判断(推荐) if (a) { b() } // 简写 if (a) b() // 利用短路运算简写 a && b() // 或者(极力不推荐) var foo = 10 foo == 10 && doSomething() foo == 5 || doSomething()

#with 作用域

          
  • 1
  • 2
  • 3
  • 4
var obj = { name: 'xxx' } with (obj) { console.log(name) // 'xxx' }

#复杂的流程控制

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
// 一种不太好的情况 if (a) { doSomethingA() } else if (b) { doSomethingB() } else if (c) { doSomethingC() } else if (d || e) { doSomethingDE() } else if (f) { doSomethingF() } //... // 可以用switch/case来代替 switch (true) { case a: doSomethingA() break case b: doSomethingB() break case c: doSomethingC() break case d || e: doSomethingDE() break case f: doSomethingF() break default: doSomethingDefault() break }

Creative Commons BY-NC 4.0 https://surmon.me/article/33
1 / 1 comments
Guest
Join the discussion...
  • 遨游星海
    遨游星海🇨🇳CNHangzhouMac OSEdge

    「过度设计是指,太过于考虑今后代码的扩展性、复用性,或太过于考虑测试的便利性,导致系统被过度设计为难以理解、难以重用的复杂结构。」关于这个就有点感触,我们的java组长就是这样的人,每次和他讲咱们的功能界面上看,一定是要方便用户使用的,大部分用户你不把功能设计的简单到不行,他们根本无法理解和使用,但他每次都说要兼容以后的功能,现有多框架大家都熟悉了,不大可能更换。离谱的是很多功能用他的思路看,我居然觉得也可行,害。他坚决不改,我只好文档写写明白,但其实写的在明白,部署的时候还是要人去蹲很久,手把手教也不行。