代码整洁之道 读书笔记

注释

C1:不恰当的信息

    让注释传达本该更好地在源代码控制系统、问题追踪系统或任何其他记录系统中保存的信息,是不恰当的。注释只应该描述有关代码和设计的技术性信息。

C2:废弃的注释

    过时、无关或不正确的注释就是废弃的注释。

C3:冗余注释

    如果注释描述的是某种充分自我描述了的东西,那么注释就是多余的。注释应该谈及代码自身没提到的东西。

C4:糟糕的注释

    值得编写的注释,也值得好好写。如果要编写一条注释,就花时间保证写出最好的注释。

C5:注释掉的代码

    删掉注释掉的代码,源代码控制系统会保存它。

环境

E1:需要多步才能实现的构建

    构建系统应该是单步的小操作。

E2:需要多步才能做到的测试

    单个指令就可以运行全部元单测。

函数

F1:过多的参数

    函数的参数量应该少。

F2:输出参数

    读者期望参数于输入而非输出。

F3:标识参数

    布尔值参数大声宣告函数做了不止一件事。他们令人迷惑,应该消灭掉。

F4:死函数

    永不被调用的方法应该丢弃。

一般性问题

G1:一个源文件中存在多种语言

    尽力减少源文件中额外语言的数量和范围。

G2:明显的行为未被实现

    遵循“最小惊异原则”(The Principle of Least Surprise),函数或类应该实现其他程序员有理由期待的行为。

G3:不正确的边界行为

    别依赖直觉。追索每种边界条件,并编写测试。

G4:忽视安全

    忽视安全相当危险。关闭某些编译器警告(或者全部警告)可能有助于构建成功,但也存在陷于无穷无尽的调试的风险。

G5:重复

    每次看到重复代码,都代表遗漏了抽象。重复的代码可能成为子程序或干脆是另一个类。

G6:在错误的抽象层级上的代码

    创建分离较高层级一般性概念与较低层级细节概念的抽象模型。

G7:基类依赖于派生类

    将概念分解到基类和派生类的最普遍的原因是较高层级基类概念可以不依赖于较低层级派生类概念。

G8:信息过多

    尽力保持接口紧凑。通过限制信息来控制耦合度。

G9:死代码

    死代码就是不执行的代码。将它从系统中删除掉。

G10:垂直分隔

    变量和函数应该在靠近被使用的地方定义。

G11:前后不一致

    从一而终。这可以追溯到最小惊异原则。小心选择约定,一旦选中,就小心持续遵循。

G12:混淆视听

    没有实现的默认构造器,没有用到的变量,从不调用的函数,没有信息量的注释等等,这些都是应该移除的废物。

G13:人为耦合

    人为耦合是指两个没有直接目的之间的模块的耦合。其根源是将变量、常量或函数不恰当地放在临时方便的位置。这是种漫不经心的偷懒行为。

G14:特性依恋

    类的方法只应该对其所属类中的变量和函数感兴趣,不该垂青其他类中的变量和函数。

G15:选择算子参数

    选择算子参数只是一种避免把大函数切分为多个小函数的偷懒做法。使用多个函数,通常优于向单个函数传递某些代码来选择函数行为。

G16:晦涩的意图

    代码要尽可能具有表达力。联排表达式,匈牙利语标记法和魔术数都遮蔽了作者的意图。

G17:位置错误的权责

    最小惊异原则作用,代码应该放在读者自然而然期待它所在的地方。

G18:不恰当的静态方法

    如果的确需要静态函数,确保没机会打算让它有多态行为。

G19:使用解释性变量

    把计算过程打散成一系列良好命名的中间值,不透明的模块就会突然变得透明。

G20:函数名称应该表达其行为

    如果必须查看函数的实现(或文档)才知道它是做什么的,就该换个更好的函数名,或者重新安排功能代码,放到有较好名称的函数中。

G21:理解算法

    了解代码如何工作与了解算法是否按需要执行是不一样的。不确定算法是否恰当司空见惯,而不确定代码做什么却是一种懒惰行为。

G22:把逻辑依赖改为物理依赖

    如果某个模块依赖于另一个模块,依赖就该是物理上的而不是逻辑上的。依赖者模块不应该对被依赖者模块有假定(逻辑依赖)。它应当明确的询问后者全部信息。

G23:用多态替代If/Else或Switch/Case

    对于给定的选择类型,不应有多于一个switch语句。在那个switch语句中的多个case,必须创建多态对象,取代系统中其他类似switch语句。

G24:遵循标准约定

    每个团队都应遵循基于通用行业规范的一套编码标准。团队不应用文档描述这些约定,因为代码本身提供了范例。

G25:用命名常量替代魔术数

    在代码中出现原始形态数字通常来说是坏现象。应该用良好命名的常量来隐藏它。

G26:准确

    代码中的含糊和不准确要么是意见不同的结果,要么源于懒惰。无论原因是什么,都要消除。

G27:结构甚于约定

    坚守结构基于约定的设计决策。命名约定很好,但却次于强制性的结构。

G28:封装条件

    如果没有if或while语句的上下文,布尔逻辑就难以理解。应该把解释了条件意图的函数抽离出来。

G29:避免否定性条件

    尽可能将条件表示为肯定形式。

G30:函数只该做一件事

    函数做了不只一件事时,应该转换为多个更小的函数,每个只做一件事。

G31:掩蔽时序耦合

    常常有必要使用时序耦合,但你不应该掩蔽它。排列函数参数,好让它们被调用的次序显而易见。

G32:别随意

    构建代码需要理由,而且理由应与代码结构相契合。如果结构显得太随意,其他人就会想修改它。如果结构自始至终保持一致,其他人就会使用它,并且遵循其约定。

G33:封装边界条件

    边界条件难以追踪。把处理边界条件的代码集中到一处,不要散落于代码中。

G34:函数应该只在一个抽象层级上

    函数中的语句应该在同一抽象层级上,该层级应该是函数名所示操作的下一层。这可能是最难理解和遵循的启发。尽管概念足够直白,人们还是很容易混淆抽象层级。

G35:在较高层级放置可配置数据

    如果你有个已知并该 在较高抽象层级的默认常量或配置值,不要将它埋藏到较低层级的函数中。

G36:避免传递浏览

通常我们不想让某个模块了解太多其协作者的信息。如果A与B协作,B与C协作,我们不想让使用A的模块了解C的信息

a.getB().getC().doSomething()

让直接协作者提供所有的全部服务。不必逛遍系统的对象全图

myCollaborator.doSomething()

Java

J1:通过使用通配符避免过长的导入清单

J2:不要继承常量

J3:常量 vs. 枚举

     用enum代替public static final int

名称

N1:采用描述性名称

    不要太快取名。确认名称具有描述性。记住,事物的意义随着软件的演化而变化,所以,要经常性地重新估量名称是否恰当。

    这不仅是一条“感觉良好式”建议。软件中的名称对于软件可读性有90%的作用。花时间明智地取名,保持名称有关。名称太重要了,不要随意对待。

N2:名称应与抽象层级相符

    不要取沟通实现的名称;取反映类或函数抽象层级的名称。

N3:尽可能使用标准命名法

    如果名称基于既存约定或用法,就比较易于理解。具有与项目有关的特定意义的名称用得越多,读者就越容易明白你的代码是做什么的。

N4:无歧义的名称

    选用不会混淆函数或变量意义的名称。

N5:为较大作用范围选用较长名称

    名称的长度应与作用范围的广泛度相关。

N6:避免编码

    不应在名称中包括类型或作用范围信息。在如今的开发环境中,m_或f之类前缀完全无用。类似vis_(表示图形系统)之类的项目或子系统名称也属多余。

    当今的开发环境不用纠缠于名称也能提供这些信息。不要用匈牙利语命名法污染你的名称。

N7:名称应该说明副作用

    名称应该说明函数、变量或类的一切信息。不要用名称掩蔽副作用。不要用简单的动词来描述做了不止一个简单动作的函数。

测试

T1:测试不足

    只要还有没被测试探测过的条件,或是还有没被验证过的计算,测试就还不够。

T2:使用覆盖率工具

    覆盖率工具能汇报你测试策略中的缺口。使用覆盖率工具能更容易地找到测试不足的模块、类和函数。

T3:别略过小测试

    小测试易于编写,其文档上的价值高于编写成本。

T4:被忽略的测试就是对不确定事物的疑问

    有时会因为需求不明而不能确定某个行为细节。可以用注释掉的测试来表达我们对于需求的疑问。

T5:测试边界条件

    特别注意测试边界条件。算法的中间部分正确但边界判断错误的情形很常见。

T6:全面测试相近的缺陷

    缺陷趋向于扎堆。在某个函数中发现一个缺陷时,最好全面测试那个函数。

T7:测试失败的模式有启发性

    有时可以通过找到测试用例失败的模式来诊断问题所在。这也是尽可能编写足够完整的测试用例的理由之一。

T8:测试覆盖率的模式有启发性

    查看被或未被已通过的测试执行的代码,往往能发现失败的测试为何失败的线索。

T9:测试应该快速

    慢速的测试是不会被运行的测试。时间一紧,较慢的测试就会被摘掉。

原文地址:https://www.cnblogs.com/TanSea/p/ClearCode-List.html