《代码整洁之道》

《代码整洁之道》

马丁(Robert C. Martin)


2019-03-20 抽象即恶。代码除恶,而整洁的代码则大抵是圣洁的。
2.2 名副其实
2019-03-20 如果名称需要注释来补充,那就不算是名副其实。
2.6 使用可搜索的名称
2019-03-20 单字母名称仅用于短方法中的本地变量。名称长短应与其作用域大小相对应
2.8 避免思维映射
2019-03-20 专业程序员善用其能,编写其他人能理解的代码。
2.9 类名
2019-03-20 类名和对象名应该是名词或名词短语
2.14 使用解决方案领域名称
2019-03-20 只有程序员才会读你的代码。所以,尽管用那些计算机科学(Computer Science,CS)术语、算法名、模式名、数学术语吧
2.15 使用源自所涉问题领域的名称
2019-03-20 与所涉问题领域更为贴近的代码,应当采用源自问题领域的名称。
2.18 最后的话
2019-03-20 取好名字最难的地方在于需要良好的描述技巧和共有文化背景。

3.1 短小
2019-03-20 函数就该小。

2019-03-20 if语句、else语句、while语句等,其中的代码块应该只有一行。该行大抵应该是一个函数调用语句。这样不但能保持函数短小,而且,因为块内调用的函数拥有较具说明性的名称,从而增加了文档上的价值。
2019-03-20 函数不应该大到足以容纳嵌套结构。
2019-03-20 函数的缩进层级不该多于一层或两层
3.2 只做一件事
2019-03-20 函数应该做一件事。做好这件事。只做这一件事。
2019-03-20 要判断函数是否不止做了一件事,还有一个方法,就是看是否能再拆出一个函数,该函数不仅只是单纯地重新诠释其实现
2019-03-20 只做一件事的函数无法被合理地切分为多个区段。
3.6.6 参数列表
2019-03-21 当一组参数被共同传递,就像上例中的x和y那样,往往就是该有自己名称的某个概念的一部分。

4.4.2 多余的注释
2019-03-22 任何迫使读者查看其他模块的注释,都没能与读者沟通好,不值所费。

5.2.4 垂直距离
2019-03-22 若某个函数调用了另外一个,就应该把它们放到一起,而且调用者应该尽可能放在被调用者上面。

5.2.5 垂直顺序
2019-03-22 被调用的函数应该放在执行调用的函数下面
第6章 对象和数据结构
2019-03-24 将变量设置为私有(private)有一个理由:我们不想其他人依赖这些变量。我们还想在心血来潮时能自由修改其类型或实现。
6.1 数据抽象
2019-03-24 隐藏实现关乎抽象!类并不简单地用取值器和赋值器将其变量推向外间,而是曝露抽象接口,以便用户无需了解数据的实现就能操作数据本体。
6.2 数据、对象的反对称性
2019-03-24 对象把数据隐藏于抽象之后,曝露操作数据的函数。数据结构曝露其数据,没有提供有意义的函数。
2019-03-24 过程式代码(使用数据结构的代码)便于在不改动既有数据结构的前提下添加新函数。面向对象代码便于在不改动既有函数的前提下添加新类。
6.3 得墨忒耳律
2019-03-24 对象隐藏数据,曝露操作。
2019-03-24 对象不应通过存取器曝露其内部结构,因为这样更像是曝露而非隐藏其内部结构。
6.3.1 火车失事
2019-03-24 如果是对象,则它们的内部结构应当隐藏而不曝露
2019-03-24 数据结构,没有任何行为,则它们自然会曝露其内部结构
2019-03-24 数据结构只简单地拥有公共变量,没有函数,而对象则拥有私有变量和公共函数
6.3.3 隐藏结构
2019-03-24 公共访问器及改值器都把私有变量公开化,诱导外部函数以过程式程序使用数据结构的方式使用这些变量
6.4 数据传送对象
2019-03-24 最为精练的数据结构,是一个只有公共变量、没有函数的类。这种数据结构有时被称为数据传送对象,或DTO(Data Transfer Objects)
2019-03-24 Active Record是一种特殊的DTO形式。它们是拥有公共(或可豆式访问的)变量的数据结构,但通常也会拥有类似save和find这样的可浏览方法。Active Record一般是对数据库表或其他数据源的直接翻译。
6.5 小结
2019-03-24 对象曝露行为,隐藏数据。便于添加新对象类型而无需修改既有行为,同时也难以在既有对象中添加新行为。数据结构曝露数据,没有明显的行为。便于向既有数据结构添加新行为,同时也难以向既有函数添加新数据结构。
第7章 错误处理
2019-03-25 错误处理很重要,但如果它搞乱了代码逻辑,就是错误的做法。
7.2 先写Try-Catch-Finally语句
2019-03-25 在某种意义上,try 代码块就像是事务。catch 代码块将程序维持在一种持续状态,无论 try代码块中发生了什么均如此。所以,在编写可能抛出异常的代码时,最好先写出try-catch-finally语句。这能帮你定义代码的用户应该期待什么,无论try代码块中执行的代码出什么错都一样。
2019-03-25 尝试编写强行抛出异常的测试,再往处理器中添加行为,使之满足测试要求。结果就是你要先构造try代码块的事务范围,而且也会帮助你维护好该范围的事务特征。
7.3 使用不可控异常
2019-03-25 可控异常的代价就是违反开放/闭合原则
7.4 给出异常发生的环境说明
2019-03-25 你抛出的每个异常,都应当提供足够的环境说明,以便判断错误的来源和处所。
9.1 TDD三定律
2019-03-25 在编写不能通过的单元测试前,不可编写生产代码。
2019-03-25 只可编写刚好无法通过的单元测试,不能编译也算不通过。
2019-03-25 只可编写刚好足以通过当前失败测试的生产代码。
9.2 保持测试整洁
2019-03-25 测试必须随生产代码的演进而修改。
2019-03-25 测试代码和生产代码一样重要。
2019-03-25 如果测试不能保持整洁,你就会失去它们。没有了测试,你就会失去保证生产代码可扩展的一切要素。
9.3 整洁的测试
2019-03-25 在单元测试中,可读性甚至比在生产代码中还重要。
9.3.1 面向特定领域的测试语言
2019-03-25 构造-操作-检验(BUILD-OPERATE-CHECK)[3]模式。每个测试都清晰地拆分为三个环节。第一个环节构造测试数据,第二个环节操作测试数据,第三个部分检验操作是否得到期望的结果。
9.4 每个测试一个断言
2019-03-25 更好一些的规则或许是每个测试函数中只测试一个概念。
10
10.1 类的组织
2019-03-26 类应该从一组变量列表开始。如果有公共静态常量,应该先出现。然后是私有静态变量,以及私有实体变量。很少会有公共变量。
2019-03-26 公共函数应跟在变量列表之后。
10.2 类应该短小
2019-03-26 如果无法为某个类命以精确的名称,这个类大概就太长了。类名越含混,该类越有可能拥有过多权责。
10.2.1 单一权责原则
2019-03-26 单一权责原则(SRP)[2]认为,类或模块应有且只有一条加以修改的理由。该原则既给出了权责的定义,又是关于类的长度的指导方针。类只应有一个权责——只有一条修改的理由。
2019-03-26 鉴别权责(修改的理由)常常帮助我们在代码中认识到并创建出更好的抽象。
2019-03-26 让软件能工作和让软件保持整洁,是两种截然不同的工作。我们中的大多数人脑力有限,只能更多地把精力放在让代码能工作上,而不是放在保持代码有组织和整洁上。
10.2.2 内聚
2019-03-26 类应该只有少量实体变量。类中的每个方法都应该操作一个或多个这种变量。通常而言,方法操作的变量越多,就越黏聚到类上。
2019-03-26 内聚性高,意味着类中的方法和变量互相依赖、互相结合成一个逻辑整体。
10.2.3 保持内聚性就会得到许多短小的类
2019-03-26 当类丧失了内聚性,就拆分它!
2019-03-26 将大函数拆为许多小函数,往往也是将类拆分为多个小类的时机。程序会更加有组织,也会拥有更为透明的结构。
10.3 为了修改而组织
2019-03-26 具体类包含实现细节(代码),而抽象类则只呈现概念。
2019-03-27 DIP认为类应当依赖于抽象而不是依赖于具体细节。
11.3 扩容
2019-03-30 Entity bean是关系数据在内存中的体现,换言之,是表格的一行。
11.5 纯Java AOP框架
2019-03-30 数据存取器对象(DAO)
11.12 文献
2019-03-30 AOP系统的真正价值在于用简洁和模块化的方式指定系统行为。
12.2 简单设计规则1:运行所有测试
2019-03-30 不可测试的系统同样不可验证。不可验证的系统,绝不应部署。
2019-03-30 只要系统可测试,就会导向保持类短小且目的单一的设计方案。
12.3 简单设计规则2~4:重构
2019-03-30 有了测试,就能保持代码和类的整洁,方法就是递增式地重构代码。
2019-03-30 测试消除了对清理代码就会破坏代码的恐惧。
2019-03-30 消除重复,保证表达力,尽可能减少类和方法的数量。
13.3.1 单一权责原则
2019-03-30 单一权责原则(SRP)[5]认为,方法/类/组件应当只有一个修改的理由
14.1 Args的实现
2019-03-31 要编写整洁代码,必须先写肮脏代码,然后再清理它。
16.2 让它做对
2019-04-01 修改历史是产生于19世纪60年代的古董,现今源代码控制工具可以帮我们做到这个。应该删掉修改历史
17.1 注释
2019-04-01 注释只应该描述有关代码和设计的技术性信息。
2019-04-01 注释应该谈及代码自身没提到的东西。
2019-04-01 值得编写的注释,也值得好好写。如果要编写一条注释,就花时间保证写出最好的注释。字斟句酌。使用正确的语法和拼写。别闲扯,别画蛇添足,保持简洁。
2019-04-01 看到注释掉的代码,就删除它!别担心,源代码控制系统还会记得它。如果有人真的需要,可以签出较前的版本。
17.3 函数
2019-04-01 函数的参数量应该少。没参数最好,一个次之,两个、三个再次之。三个以上的参数非常值得质疑,应坚决避免。
2019-04-01 输出参数违反直觉。读者期望参数用于输入而非输出。如果函数非要修改什么东西的状态不可,就修改它所在对象的状态好了。
17.4 一般性问题
2019-04-01 孤立抽象是软件开发者最难做到的事之一,而且一旦做错也没有快捷的修复手段。
2019-04-01 将概念分解到基类和派生类的最普遍的原因是较高层级基类概念可以不依赖于较低层级派生类概念。这样,如果看到基类提到派生类名称,就可能发现了问题。通常来说,基类对派生类应该一无所知。
2019-04-01 将派生类和基类部署到不同的jar文件中,确保基类jar文件对派生类jar文件的内容一无所知,我们就能把系统部署为分散和独立的组件。
2019-04-01 变量和函数应该在靠近被使用的地方定义。
2019-04-01 私有函数应该刚好在其首次被使用的位置下面定义。
2019-04-01 类的方法只应对其所属类中的变量和函数感兴趣,不该垂青其他类中的变量和函数。
2019-04-01 通常应该倾向于选用非静态方法。如果有疑问,就是用非静态函数。如果的确需要静态函数,确保没机会打算让它有多态行为。
2019-04-01 让程序可读的最有力方法之一就是将计算过程打散成在用有意义的单词命名的变量中放置的中间值。
2019-04-01 解释性变量多比少好。只要把计算过程打散成一系列良好命名的中间值,不透明的模块就会突然变得透明,这很值得注意。
2019-04-01 如果你必须查看函数的实现(或文档)才知道它是做什么的,就该换个更好的函数名,或者重新安排功能代码,放到有较好名称的函数中。
2019-04-01 用多态替代If/Else或Switch/Case
2019-04-01 在使用switch之前,先考虑使用多态。
2019-04-01 用命名常量替代魔术数
2019-04-01 用浮点数表示货币几近于犯罪。
2019-04-01 代码中的含糊和不准确要么是意见不同的结果,要么源于懒惰。无论原因是什么,都要消除。
2019-04-01 否定式要比肯定式难明白一些。所以,尽可能将条件表示为肯定形式。
2019-04-01 把处理边界条件的代码集中到一处,不要散落于代码中。
2019-04-01 函数中的语句应该在同一抽象层级上,该层级应该是函数名所示操作的下一层。
2019-04-01 确保模块只了解其直接协作者,不了解整个系统的游览图。
17.6 名称
2019-04-01 不要太快取名。确认名称具有描述性。记住,事物的意义随着软件的演化而变化,所以,要经常性地重新估量名称是否恰当。
2019-04-01 不要取沟通实现的名称;取反映类或函数抽象层级的名称。
2019-04-01 不应在名称中包括类型或作用范围信息。
A.2.2 深入挖掘
2019-04-01 依据Java内存模型,32位值的赋值操作是不可中断的。
2019-04-01 根据 JVM规约,64位值的赋值需要两次32位赋值。
A.3.2 非锁定的解决方案
2019-04-01 现代处理器拥有一种通常称为比较交换(Compare and Swap,CAS)的操作。这种操作类似于数据库中的乐观锁定,而其同步版本则类似于保守锁定。
2019-04-01 关键字synchronized总是要求上锁,即便第二个线程并不更新同一值时也如此。
A.4.3 基于服务端的锁定
2019-04-01 基于客户代码的锁定实在不可靠。

你可能感兴趣的:(《代码整洁之道》)