Refactoring & Specification
重构
定义:重构是一种对软件内部结构的改善,目的是在不改变软件的可见行为的情况下,使其更易理解,修改成本更低。
为什么要重构?
时刻保证代码质量。随着代码不停的堆砌,更多的人参与项目,代码会越来越乱,最后重构成本比重新开发还高。
优秀的代码都不能一开始就完全设计好,都是迭代出来的,随着系统的演进,重构是不可避免的。
避免过度设计。在迭代过程中,真正遇到问题的时候再对代码重构,避免前期投入太多精力。
帮助工程师技术成长。
重构什么?
大规模高层次重构:对顶层代码设计重构,包括系统、模块、代码结构、类与类之间的关系,手段有分层、模块化、解耦、抽象可复用组件等。主要利用设计思想、原则、模式。影响面较大、难度较大、耗时较长、引入 BUG 风险较大。
小规模低层次重构:对代码细节的重构,包括类、函数、变量等,如规范命名、规范注释、消除超大类等。主要利用编码规范。
何时重构:持续重构。平时无事时可以做一下小规模重构;在做功能开发时,遇到不规范的代码,也顺手改了。
解耦
过于复杂的代码可读性、可维护性都不友好。解耦是保证代码松耦合、高内聚、控制代码复杂度的有效手段。
根据模块、类与类之间的关系图的复杂性来判断是否需要解耦。
封装、抽象、中间层、模块化以及一些设计原则与思想(单一职责、基于接口而非实现、依赖注入、多用组合少用继承、迪米特等)是常用的解耦方法。
单元测试
单元测试(Unit Testing)是保证重构不出错的有效手段。单元测试是研发工程师自己编写,用于测试代码的正确性。相对于集成测试(Integration Testing)粒度更小。
写单元测试的好处:
能帮你发现代码中的 bug。
能帮你发现代码设计上的问题。代码的可测试性是一个重要的质量标准,若代码很难被测试,那么意味着代码设计不合理。
对集成测试的有力补充。集成测试很难覆盖全面。
写单元测试的过程本来就是代码重构的过程。
阅读单元测试能帮你快速熟悉代码。
尽管单元测试的代码量可能是被测代码的 1~2 倍,但并不耗时,因为代码逻辑简单、重复很多。单元测试不会在线上运行,所以代码质量可以降低。不能用覆盖率作为单元测试质量的唯一标准。写单元测试不需要了解代码实现逻辑。
代码的可测试性就是编写单元测试的难易程度。依赖注入是提高可测试性的有效手段。
规范
命名
长短:在足够表达含义的情况下,命名越短越好。对于常用的词,可以用缩写,如 str(string), num(number) 等。作用域较小的变量,可以用相对较短的命名。
利用上下文简化命名。如 User 类中的成员变量 userName 可以简化为 name。
可读、可搜索。可读(容易发音)是为了在项目沟通时方便。可搜索是为了方便在 IDE 中搜索,如大家都用 selectXXX,而你用 queryXXX,那么在 IDE 中药搜索所有查询相关的代码就不方便。
接口和抽象类:接口两种方式都可以,一种 IUserService 和 UserService,另一种 UserService 和 UserServiceImpl。抽象类前缀 Abstract。
注释
注释的目的是让代码更加容易看懂。注释一般包含:做什么、为什么、怎么做,一些复杂的类和接口还要写如何用。
注释也有维护成本,并非越多越好。一般类和函数要写注释,而函数内部注释相对较少。
代码风格
函数的行数:不要超过一个屏幕的大小。
类的行数:间接判断标准,类读起来头大、实现某个功能不知道用哪个函数、用一个小功能需要整个函数(这个类包含很多无用的函数)时,说明这个类行数过多。
一行代码的长度:不要超过 IDE 显示的宽度。
善用空行分割代码。
缩进:推荐两格,因为可以节省空间。永远不要用 tab 缩进。
大括号推荐不另起一行,因为节省空间。另起一行的好处是左右括号可以对齐。
类中成员的排列顺序:先成员变量后函数,先静态后普通,先 public、再 protected、最后 private。
编程技巧
将复杂的逻辑提炼拆分成函数和类。
避免参数过多。可以拆分成多个函数或将参数封装成类的方式。
不要使用参数来做代码执行逻辑的控制。包括 null 的情况。
函数设计要职责单一。
移除过深的嵌套。方法有:去掉多余的 if 或 else;使用 continue、break、return 提前退出嵌套;调整执行顺序;将部分嵌套逻辑抽象成函数。
字面量取代魔法数。
解释性变量替代复杂表达式。
Last updated