编写高质量代码的技巧、方法和理论
讲在前面
代码质量的评价有很强的主观性。对于同样一个系统,熟悉它的资深工程师会觉得代码的可维护性还不错,而一些新人因为不熟悉代码,修改 bug、修改添加代码要花费很长的时间,就有可能会觉得代码的可维护性不那么好。
可维护性
落实到编码开发,所谓的“维护”无外乎就是修改 bug、修改老的代码、添加新的代码之类的工作。
所谓“代码易维护”就是指,在不破坏原有代码设计、不引入新的 bug 的情况下,能够快速地修改或者添加代码。所谓“代码不易维护”就是指,修改或者添加代码需要冒着极大的引入新 bug 的风险,并且需要花费很长的时间才能完成。
对于一个开发者来说,什么样的代码是“可维护”的呢?应该是能看懂、易修改、可测试的代码。对应的,也就是可读性、可扩展性&可复用性、可测试性。
可读性
代码的可读性应该是评价代码质量最重要的指标。
- 命名规范:命名技巧
动作➕名词
,如 AssertMemberCommentPrivilege。 - 参数个数:参数个数控制在 3、4 个以内,如果太多的话应该传入一个“结构体”。
- 函数大小:一般在 100 行以内。
如何检验可读性:
实际上,code review 是一个很好的测验代码可读性的手段。如果你的同事可以轻松地读懂你写的代码,那说明你的代码可读性很好;如果同事在读你的代码时,有很多疑问,那就说明你的代码可读性有待提高了。
可扩展性
说直白点就是,代码预留了一些功能扩展点,你可以把新功能代码,直接插到扩展点上,而不需要因为要添加一个功能而大动干戈,改动大量的原始代码。
可复用性
如何实现可复用性:
- 利用继承、组合、多态等面向对象特性。
- 函数职责单一,。
可测试性
代码可测试性的好坏,能从侧面上非常准确地反应代码质量的好坏。代码的可测试性差,比较难写单元测试,那基本上就能说明代码设计得有问题。
设计原则
单一职责原则
开闭原则
对扩展开放,对修改关闭。
编码时最头疼的就是更改旧代码,因为要确保依赖旧代码的其他模块正常工作。
这条原则的设计初衷:只要它没有破坏原有的代码的正常运行,没有破坏原有的单元测试,我们就可以说,这是一个合格的代码改动。
看一个违反原则的例子:
|
|
里氏替换原则
接口隔离原则
接口隔离原则:我只要我想要的,不想要的别给我
其实类似于单一职责原则,个人感觉不太重要。
有时候为了符合这一原则把接口拆分得太细也不好。
依赖反转原则
接口隔离原则:高层模块不依赖低层模块,高层模块提供一个插件&钩子来使用低层模块。我们规定好高层流程框架,在这个流程中会开放出一些接口,我们只需要把接口的实现类(低层)挂载到这个流程框架中即可实现完整的业务逻辑,而此时高层框架是完全不依赖低层的。
比如,Tomcat是一个HTTP服务器,其内部规定好了如何处理HTTP请求的报文,它给我们开放出来的规范就是一些Servlet类中的API,比如把HTTP报文转换成ServletRequest,把响应转换为ServletResponse。我们只需要编写自己的Servlet然后把这些Servlet注册到容器中,对应的HTTP请求就可以被派发到我们的Servlet对象中了。
设计原则实战
控制反转&依赖注入框架
控制反转
这里所说的“控制”指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程通过框架来控制。流程的控制权从程序员“反转”给了框架。
依赖注入
依赖注入是一种具体的编码技巧。我们不通过 new 的方式在类内部创建依赖的类对象,而是将依赖的类对象在外部创建好之后,通过构造函数、函数参数等方式传递(或注入)给类来使用。
依赖注入框架
依赖注入框架:由框架来自动创建对象、管理对象的生命周期、依赖注入等原本需要程序员来做的事情。
设计模式
大部分设计模式要解决的都是代码的可扩展性问题。
如何重构
全文总结
对于提升代码质量,最有效的是编码规范,其次是设计原则,再次是代码重构,最后才是面向对象和设计模式。 整个排序是按照我理解的难易程度来进行的。一般一个项目都是多人开发,多人并行开发中,考虑到团队中技术水平不一,保持代码质量最好的方式就是先制定编码规范,大家最容易达成一致并遵守。其次是设计原则,因为它相对来讲更明确,违反设计原则基本等于硬伤,更容易得到认同。代码重构是需要长期去做的,甚至不是在开发过程中而是在维护过程中去做的,所以排在第三位。后面两项更多的要考虑实际情况,不同水平的人甚至相同水平的人都会有自己不同的理解,比较难以达成统一,项目排期足够还好,一旦排期不足,很可能在当时没那个成本去谈论这些。
原文链接:编写高质量代码的技巧、方法和理论