《代码整洁之道:敏捷软件开发手册》
介绍:《代码整洁之道:敏捷软件开发手册》 读书笔记。
评价 : 书中比较有用的核心观点总结下来并不多,我这篇读书笔记也才 2500 多字左右。不过,我并没有总结每一个章节,只总结了一些我觉得比较有用的章节。另外,如果你平时本身的编码习惯就比较好的话,这本书对你的帮助应该不大,毕竟里面讲的东西都是比较老生常谈的。不过,复习巩固一下怎样写好代码肯定不是坏事!
作者:Guide哥

积累!!!平时写代码的过程中就要注意!!!
整洁的代码
现在有很多人觉得我们的关注点应该在模型和需求上,说实话,这有点扯淡,我们永远无法离开代码,代码是我们最终用来表达需求的语言。
代码质量实在是太重要了!你回想一下自己平时为了赶时间完成某些任务,是不是写过很多很乱的代码,以至于过几天之后自己再看都看不太懂了。好的代码质量在很多时候甚至决定了你的产品能否能长久的发展下去。特别是在公司里的团队开发的时候,如果你的代码过于混乱,可能会影响到整个项目的进展,甚至影响到整个项目是否能顺利完成。好的代码不是一步就能得到的,而是一步一步重构获得的。试想一下:假如你们的项目代码特别糟糕,这个时候你们要在原有代码的基础上再增加或者修改一个功能的话是不是会让人头疼?
写整洁代码需要遵循大量小技巧,贯彻刻苦习得的“整洁感”。编写整洁代码的程序员就和艺术家一样!
什么是整洁的代码?
- 如同优美的散文;
- 便于他人的阅读;
- 必须包含测试;
- 没有重复代码;
- 尽量少的依赖关系和尽量少的 API;
- 方法、函数、变量的命名要有意义;
有意义的命名
- 名副其实:通过变量、函数或者类的名称就能大概知道它是干什么用的;
- 避免误导:避免使用专有名称或者具有误导性的名称;
- 做有意义的区分:比如:ProductInfo 类和 ProductData 类意思并无区别;
- 使用读者能读出来的名称;
- 使用可搜索的名称:单英文字母和数字常量很难被搜索出来;
- 避免使用编码;(接口和实现:ShapeFactory.interface,ShapeFactoryImp.Java;)
- 类名和对象名称应该是名词或名词短语如:Customer、AdressParser,避免使用 Manager、Processor、Data 和 Info 这样的类名;
- 方法名应该是动词或动词短语,如 postPayment、deletePage 或 save
函数
- 最重要也是首要原则就是要短小。(尽量把函数长度控制在 20 行以内,函数内尽量不要有嵌套结构)
- 只做一件事情。
- 函数中的语句都要在同一抽象层级上。自顶向下读代码:向下规则,让代码拥有自顶向下的阅读顺序,让每个函数后面都跟着下一抽象层级的函数。
- 使用描述性的名称(① 函数越短小,功能越集中,就越便于取个好名字;② 别害怕长名称,长而具有描述性的名称,要比短而令人费解的名称好;③ 命名方式要保持一致。④ 不要害怕花时间取名字。)。
- 最理想的参数数量是零,其次是一,再次是二,有足够的理由才能用三个以上参数——所以无论如何也不要这么做。另外,从测试的角度来说多参数更会带来很多麻烦。如果函数看来需要两个、三个或三个以上参数,就说明其中一些参数应该封装为类了。参数不多的情况下我们可以把参数的名称加在函数名上。
- 函数要么做什么事,要么回答什么事,但二者不可得兼。
- 错误处理就是一件事,处理错误的函数不该做其他事。
- 重复可能是软件中一切邪恶的根源,许多原则与实践规则都是为控制与消除重复而创建。
如何写出这样的函数:
- 打磨代码,分解函数、修改名称、消除重复;
- 缩短和重新安置方法、拆散类、保持测试通过。
分享书中的一句鸡汤:
大师级程序员把系统当做故事来讲,而不是当程序来写。他们使用选定编程语言提供的工具构建一种更为丰富且更具表达力的语言,用来讲那个故事。
注释
这里有个常见误区:代码的注释越详细越好或者一行代码一行注释最好。实际上好的代码本身就是注释,我们要尽量规范和美化自己的代码来减少不必要的注释。
1.糟糕的注释还不如别注释。 带有少量注释的整洁而有表达力的代码要比带有大量注释的零碎而复杂的代码像样得多。与其花时间编写解释你搞出的糟糕的代码的注释,不如花时间清洁那堆糟糕的代码(好代码 > 差代码+好注释)。
2. 若编程语言足够有表达力,就不需要注释,尽量通过代码来阐述。
创建一个与注释所言同一事物的函数即可
// check to see if the employee is eligible for full benefits
if ((employee.falgs & HOURLY_FLAG) && (employee.age > 65))应替换为
if (employee.isEligibleForFullBenefits())3. 程序员应当负责将注释保持在可维护、有关联、精确的高度,更应该把力气用在写清楚代码上,直接保证无须编写注释。
4.对代码进行修改了之后,记得看看注释是否需要修改。
5.不要重复性注释也不要废话注释。
比如下面的注释就是单纯重复了很明显的代码要干的事情,这完全没必要,还会为我们带来没有必要的阅读负担。
int[] a = {1, 2, 3, 4};
//让数组b指向数组a
int[] b = a;还比如下面这样:
//一个月中的某一天
private int dayOfMonth;
/**
* 返回一个月中的某一天
*/
public int getDayOfMonth(){
return dayOfMonth;
}能用函数或者变量表示就别用注释:
// does the module from the global list <mod>
// depend on the subsystem we are part of?
if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem())可以改为
ArrayList moduleDependees = smodule.getDependSubsystems();
String ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.contains(ourSubSystem))好的注释应该包含哪些内容?
- 法律信息
- 提供信息
- 解释意图
- 警示
- TODO 注释。
格式
代码的格式同样非常重要,规范的代码格式可以极大提高代码的可阅读性。
一些关于代码格式的小建议:
- 一行代码不要过长,不超过 100 - 120 个字符。
- 注意缩进。
- 变量声明应尽可能的靠近其使用位置;本地变量在函数的顶部出现;实体变量应该在类的顶部声明。
- 若某个函数调用了另一个函数,就应该将他们放在一起,调用者尽量放在被调用者上面。
- ......
对象与数据结构
得墨忒耳律 :方法不应调用由任何函数返回的对象的方法。
反例:
final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();错误处理
- 在某种意义上,
try代码块就像事务,catch代码块将程序维持在一种持续状态,无论try代码块中发生了什么均如此。所以,在编写可能抛出异常的代码块时,最好先写出try-catch-finally语句。 - 抛出的每个异常的时候,都应当提供足够的错误信息说明,以便判断错误的原因。
- 尽量使用不受检查异常。这是因为受检查异常违反了开放/闭合原则 OCP,如果底层函数需要抛出新的可控异常,那么每个调用该函数的函数都需要修改。并且,Java 代码在编译过程中,如果受检查异常没有被
catch/throw处理的话,就没办法通过编译 。RuntimeException及其子类都统称为非受检查异常。我们一般业务开发的时候,所有的异常类都是继承自RuntimeException。 - 不要返回 null 值,也不要传递 null 值。
单元测试
- 单元测试可以为重构提供信心。
- 持续集成依赖单元测试。持续集成服务在新代码更改上自动构建和运行单元测试,以立即发现任何错误。
- 测试代码和生产代码一样重要,一定要重视。
- 测试代码需要随着生产代码的演进而修改,如果测试不能保持整洁,只会越来越难修改。
- 整洁的测试有什么要素?有三个要素:可读性,可读性和可读性
类
类应该短小 :
- 职责单一,类的名称应当描述其权责,如果无法为某个类命以精确的名称,这个类大概就太长了,类名越含混,该类越有可能拥有过多权责;类或模块应有且只有一条加以修改的理由。
- 内聚性强,方法操作的变量越多,就越黏聚到类上,如果一个类的每个变量都被每个方法所使用,则该类具有最大的内聚性。
组织类时考虑代码的修改 :
- 开放-闭合原则(OCP):类应当对扩展开放,对修改封闭。
- 依赖反转原则(Dependency Inversion Principle,DIP): 如果要设计一个灵活的系统,在源代码层级的依赖关系中就应该多应用抽象类型,而非具体实现。
更新: 2022-02-18 12:56:51
原文: https://www.yuque.com/snailclimb/to3hqu/nfnmv0