【笔记】代码整洁之道

2017-09-25  本文已影响0人  我爱学习_学习使我快乐

一、整洁的代码

  1. 整洁的代码从不隐藏设计者的意图,充满了干净利落的抽象和直截了当的控制语句。
  2. 读写的花费时间比例超过10:1。写新代码的时候,我们一直在阅读旧代码

二、命名

  1. 关键在于良好的描述技巧和共有的文化背景!
  2. 名副其实
  3. 避免误导,不要使用非常相似的命名,不要使用小写l和大写O(容易和数字01搞混)
  4. 做有意义的区分(用数字区分通常没有意义),例如,copy(source,destination) > copy(a1, a2)。data,info等等词通常毫无意义
  5. 名词要便于搜索,长名 > 短名
  6. 类名应该是名词短语,方法名应该是动词短语
  7. 别抖机灵,一点也不幽默
  8. 每个概念对应一个词,一以贯之,不要总变来变去。fetch, retrieve, get表达的都是一个含义
  9. 避免双关

三、函数

  1. 短小!更短小!函数的缩进层级应该<=2
  2. 只做一件事,如果多余一件事,就进行拆分
  3. 函数内的语句要在同一个抽象层级上(自顶向下的coding,自顶向下的reading)
  4. 使用描述性的名称,别害怕名字长
  5. 函数的参数要尽量少,0个最好,1个也行,2个次之,3个及以上是灾难(不好记顺序,没法测)。一定要尽可能的抽象出类
  6. 不要传布尔参数,一定可以拆出两个函数来
  7. 可以把参数名放到函数名中来,比如assertEqual(expected, actual) -> assertExpectedEqualsActual(expected, actual)
  8. 区分开「指令型」和「询问型」的函数,不要一个函数两种事情都做
  9. try-catch单独封装

四、注释

  1. 「别给糟糕的代码加注释,重新写吧」 —— Brian Kernighan and P.J. Plaugher
  2. 注释的恰当用法是弥补我们再用代码表达意图是遭遇的失败
  3. 注释存在的时间越久,就离其所描述的代码越远。原因在于程序员不能坚持维护注释
  4. 好注释包括:法律信息,提供信息,对意图的解释(不是实现,是为什么这么实现),对其他人的警示,todo(一定要写好todo的功能,以及由谁负责,何时完成),强调作用
  5. 坏注释包括:喃喃自语,多余的注释,注释掉的代码(未来其他人不敢删除),信息过多(没人会看的),署名(源代码控制系统可以记录作者)

五、格式

  1. 垂直方向:紧密关联的代码应该互相靠近(调用者应该和被调用者相邻,并且调用者在上,被调用者在下(符合人从上而下的阅读习惯)),关系密切的概念也应该互相靠近

六、对象和数据结构

  1. 应该尽量避免曝露数据细节,应该以抽象的形态表述数据
  2. 过程式代码(使用数据结构的代码)方便在不改动数据结构的情况下增加函数,面向对象的代码方便在不改动现有函数的情况下增加新类
  3. 一切都是对象只是一个传说
  4. 模块不应该了解它所操作的对象的内部情形。类C的方法f只应该调用(C的方法,f创建的对象的方法,f的参数的方法,C的实体变量所持有的方法)。一连串的调用应该做切分。
  5. 最精炼的数据结构,是一个只有公共变量、没有函数的类(Java)

七、错误处理

  1. 错误处理很重要,但如果它搞乱了代码逻辑,就是错误的做法
  2. 抛出异常的时候,应该提供足够的环境说明,以便判断错误的来源。应该创建信息充分的错误信息,和异常一起传递出去
  3. 定义异常类的时候,首要考虑它们应该如何被捕获
  4. 别返回null,应该抛出异常,或者返回特例对象
  5. 尽可能避免传递null值

九、单元测试

  1. TDD三定律:
    (1)在编写不能通过的单元测试之前,不可编写生产代码
    (2)只可编写刚好无法通过的单元测试,不能编译也算是不通过
    (3)只可编写刚好通过当前失败测试的生产代码
  2. 测试代码和生产代码一样重要,应该保持整洁
  3. 有了单元测试就不用再担心对代码的修改。是单元测试的代码让代码可扩展、可维护、可复用
  4. 整洁的测试的要素:可读性!可读性的标准:明确、简洁、足够的表达力
  5. 构造-操作-检验:构造测试数据,操作测试数据,检查操作是否得到预期结果
  6. 每个测试函数只测试一个概念
  7. FIRST规则:fast(测试代码运行速度应该足够快),independent(测试之间互相独立),repeatable(测试与测试环境无关),self-validating(测试输出应该是布尔值),timely(先写单元测试代码,后写生产代码)

十、类

  1. 类中内容的顺序:变量,函数。变量顺序:公共静态变量,私有静态变量,私有实体变量。
  2. 类应该短小,如果一个类无法精准命名,通常都意味着太长了。系统应该由许多短小的类,而不是少量巨大的类组成。
  3. 单一权责原则(SRP):类或者模块应该有且仅有一条加以修改的理由。
  4. 内聚:类应该只有少量实体变量,类中的每个方法都应该操作一个或者多个这种变量。

十一、系统

  1. 软件系统应将启动过程和运行过程的逻辑分开。
  2. 分解main:将构造与使用分开的方法之一,是将全部构造过程搬迁到main中。

十三、并发

  1. 对象是过程的抽象,线程是调度的抽象
  2. 并发是一种解耦策略,它将what(目的)与when(时机)分解开
  3. 并发有时能够改进性能,但是只在多个线程/处理器之间能分享大量等待时间的时候管用
  4. 并发算法的设计可能和单线程系统的设计极不相同
  5. 并发会在性能和编写额外代码上增加一些开销
  6. 正确的并发是复杂的,即便对于简单的问题也是如此
  7. 并发缺陷并非总能复现
  8. 并发常常需要对设计策略进行根本性修改
  9. 数据封装:严格限制对可能被共享的数据的访问
  10. 生产者消费者模型、读者作者模型、哲学家进餐模型
  11. 不要同时追踪非线程缺陷和线程缺陷,确保代码在线程之外可工作
  12. 在不同环境中,多线程代码的行为可能不同,尽量在所有可能部署的环境中测试。

十四、其他

  1. 先写可工作的脏代码,再在单元测试的辅助之下,清理它
  2. clover工具可以检查单元测试代码的覆盖率
  3. 应该限制类、模块中暴露的接口数量,类中的方法越少越好。
  4. 条件判断中的条件应加以封装,用来清晰的表明该条件的内容
  5. 用命名常量代替魔术数
  6. 时序耦合应该暴露出来。如果语句a必须在语句b的后面执行,那语句b的结果应该作为语句a的输入参数
  7. 封装边界条件,应该把所有涉及到边界条件的代码放到一起
  8. 避免传递浏览。每个模块只应该了解它的协作者,而非整个系统
  9. 测试边界条件
  10. 错误倾向于扎堆出现。如果某个函数出现错误,最好全面测试它
上一篇 下一篇

猜你喜欢

热点阅读