2

如何评价代码质量

 1 year ago
source link: https://www.fly63.com/article/detial/11788
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

更新日期: 2022-06-23阅读量: 5标签: 代码分享

扫一扫分享

在作者的工作经历中,每当同事评论项目代码质量的时候,作者听到最多的评论是“代码 写得很烂”或“代码写得很好”。作者认为,用“好”“烂”这样的字眼来描述代码质量是非常 笼统的。当作者询问代码到底“烂”在何处或“好”在哪里时,尽管大部分同事都能简单地罗 列几个“烂”的方面或好的方面,但他们的回答往往都不够全面,知识点零碎,也无法切中 要害。

当然,也有一些软件工程师对如何评价代码质量有所认识,如认为好代码是易扩展、易读、 简单、易维护的,等等,但他们对于这些评价的理解往往只停留在表面上,对于诸多更加深入 的问题,如“怎么才算可读性好?什么样的代码才算易扩展、易维护?可读、可扩展与可维护 之间有什么关系?可维护中的‘维护’两字该如何理解?”,等等,他们并没有太清晰的认识。

实际上,对于代码质量的描述,除“好”“烂”这样比较简单、笼统的描述方式以外,还 有很多语义丰富、专业和细化的描述方式,如下所示:

灵活性(flexibility)、可扩展性(extensibility)、可维护性(maintainability)、可读性(readability)、 可理解性(understandability)、易修改性(changeability)、可复用性(reusability)、可测试性(testability)、模块化(modularity)、高内聚低耦合(high cohesion loose coupling)、高效(high effciency)、高性能(high performance)、安全性(security)、兼容性(compatibility)、易用 性(usability)、 简 洁(clean)、 清 晰(clarity)、 简 单(simple)、 直 接(straightforward)、 少 即是多(less code is more)、文档详尽(well-documented)、分层清晰(well-layered)、正确 性(correctness、bug free)、健壮性(robustness)、鲁棒性(robustness)、可用性(reliability)、 可伸缩性(scalability)、稳定性(stability)和优雅(elegant)等。

面到如此多的词汇,我们到底应该使用哪些词汇来描述一段代码的质量呢?

实际上,我们很难通过其中的某个或某几个词汇来全面地评价代码质量,因为这些词汇是从不同角度描述代码质量的。例如,在评价一个人的时候,我们往往通过多个方面进行综合评 价,如性格、能力等,否则,对一个人的评价可能是片面的。同样,对于代码质量,我们也需要综合多种因素进行评价,不应该从单一的角度去评价。例如,一段代码的可扩展性很好,但可读性很差,那么,我们不能片面地认为这段代码的质量高。

注意,不同的评价角度并不是完全独立的,有些之间存在包含关系、重叠关系等,或者可 以互相影响。例如,代码的可读性和可扩展性好,可能意味着代码的可维护性好。而且,各种 评价角度不是“非黑即白”。例如,我们不能简单地将代码评价为可读或不可读。如果用数字 来量化代码的可读性,那么应该是一个连续的区间值,而非 0、1 这样的离散值。

不过,我们真的可以客观地量化一段代码的质量吗?答案是否定的。对一段代码质量的评价,常常带有很强的主观性。例如,对于什么样的代码才算是可读性好,每个人的评判标准都 不一样。

正是因为代码质量评价的主观性,使得这种主观评价的准确度与软件工程师自身的经验有极大的关系。软件工程师的经验越丰富,给出的评价往往越准确。形成对比的是,资历较浅的 软件工程师常常觉得没有一个可量化的评价标准作为参考,很难准确判断一段代码的质量。如果无法辨别代码写得好或坏,那么,即使写再多的代码,编码能力也可能没有太大提高。在仔细阅读前面罗列的代码质量评价标准之后,读者会发现,有些词汇过于笼统、抽象, 而且偏向于对整体的描述,如优雅、好、坏、整洁和清晰等;有些过于注重细节、偏重方法 论,如模块化、高内聚低耦合、文档详尽和分层清晰等;有些可能并不仅仅局限于编码,与架 构设计等也有关系,如可伸缩性、可复用性和稳定性等。

为了读者有重点地进行学习,作者挑选了 7 个常用且重要的评价标准来详细讲解,包括可 维护性、可读性、可扩展性、灵活性、简洁性、可复用性和可测试性。

1 可维护性(maintainability)

对于代码开发,“维护”无外乎修改 bug、修改旧的代码和添加新的代码等。“代码易维护” 是指,在不破坏原有代码设计、不引入新的 bug 的情况下,能够快速修改或添加代码。“代码 不易维护”是指,修改或添加代码需要冒极大的引入新 bug 的风险,并且需要很长的时间才能 完成。

对于一个项目,维护代码的时间可能远远大于编写代码的时间。软件工程师可能将大部分 时间花在修复 bug、修改旧的功能逻辑和添加新的功能逻辑之类的工作上。因此,代码的可维 护性就显得格外重要。

对于维护、易维护和不易维护这 3 个概念,我们不难理解。不过,对于实际的软件开发, 更重要的是需要清楚如何判断代码可维护性的高低。

实际上,可维护性是一个难以量化、偏向对代码整体进行评价的标准,它类似之前提到的“好”“坏”“优雅”之类的笼统评价。代码的可维护性高低是由很多因素共同作用的结果。代码简洁、可读性好、可扩展性好,往往就会使得代码易维护。更深入地讲,如果代码分层清 晰、模块化程度高、高内聚低耦合、遵守基于接口而非实现编程的设计原则等,就可能意味着 代码易维护。除此之外,代码的易维护性还与项目的代码量、业务的复杂程度、技术的复杂程 度、文档的全面性和团队成员的开发水平等诸多因素有关。

2 可读性(readability)

软件设计专家 Martin Fowler 曾经说过:“Any fool can write code that a computer can understand. Good programmers write code that humans can understand. ”(任何人都可以编写计算机能理解的 代码,而好的程序员能够编写人能理解的代码。)在 Google 内部,有一个称为“Readability” 的认证。只有拿到这个认证的软件工程师,才有资格在 Code Review 的时候批准别人提交的代码。可见,代码的可读性有多么重要,毕竟,代码被阅读的次数有时候远远超过被编写和执行的次数。

代码的可读性如此重要,在编写代码的时候,我们要时刻考虑代码是否易读、易理解。代 码的可读性在很大程度上会影响代码的可维护性,因为无论是修复 bug 还是添加 / 修改功能代 码,我们首先要读懂代码。如果我们对代码一知半解,就有可能因为考虑不周而引入新 bug。

既然代码的可读性如此重要,那么我们如何评判一段代码的可读性呢? 我们需要查看代码是否符合代码规范,如命名是否达意、注释是否详尽、函数长度是否合 适、模块划分是否清晰,以及代码是否“高内聚、低耦合”等。除此之外,Code Review 也是 一个很好的测试代码可读性的手段。如果我们的同事可以轻松地读懂我们写的代码,往往能够 说明我们的代码的可读性不差;如果同事在读我们写的代码时,有很多疑问,那么可能在提示 我们,代码的可读性存在问题,需要重点关注。

3 可扩展性(extensibility)

代码的可扩展性是指在不修改或少量修改原有代码的情况下,能够通过扩展方式添加新功能代码。换句话说,代码的可扩展性是指在编写代码时预留了一些功能扩展点,我们可以把新 功能代码直接插入扩展点,而不会因为添加新的功能代码而改动大量的原始代码。可扩展性也是评价代码质量的重要标准。代码的可扩展性表示代码应对未来需求变化的能力。与代码的可读性一样,代码是否易扩展也在很大程度上决定了代码是否易维护。

4 灵活性(flexibility)

灵活性也可以用来描述代码质量。例如,我们经常会听到这样的描述:“代码写得很灵 活”。那么,我们如何理解这里提到的“灵活”呢?

尽管很多人用“灵活”描述代码质量,但实际上,“灵活”是一个抽象的评价标准,给“灵 活”下定义是很难的。不过,我们可以想一下,我们在什么情况下才会说代码写得很灵活呢?作者罗列了 3 种场景,帮助读者理解什么是代码的灵活性。

  1. 当我们添加新功能代码时,由于原有代码中已经预留了扩展点,因此,我们不需要修改原有代码,只需要在扩展点上添加新代码。这个时候,我们除可以说代码易扩展以外,还可以说代码写得很灵活。

  2. 当我们要实现一个功能时,如果原有代码中已经抽象出了很多位于底层且可复用的模 块、类等,那么我们可以直接使用。这个时候,我们除可以说代码易复用以外,还可以说代码 写得很灵活。

  3. 当我们使用某个类时,如果这个类可以应对多种使用场景,满足多种不同需求,那么, 我们除可以说这个类易用以外,还可以说这个类设计得很灵活或代码写得很灵活。从上述场景来看,如果一段代码易扩展、易复用,或者易用,我们一般可以认为这段代码 写得很灵活。因此,“灵活”的含义宽泛,很多场景都可以使用。

5 简洁性(simplicity)

有一条非常著名的设计原则,大部分读者应该都听过,那就是 KISS 原则:“Keep It Simple,Stupid”。该原则的意思是“尽量保持代码简单”。代码简单、逻辑清晰往往意味着代 码易读、易维护。在编写代码的时候,我们往往会把“简单、清晰”原则放到首位。

不过,很多编程经验不足的程序员会觉得,简单的代码没有技术含量,喜欢在项目中引入一些复杂的设计模式,觉得这样才能体现自己的技术水平。实际上,思从深而行从简,真正的 编程高手往往能用简单的方法解决复杂的问题。

除此之外,虽然我们都能认识到,代码要尽量写得简洁,要符合 KISS 原则,但怎样的代 码才算足够简洁?怎样的代码才算符合 KISS 原则呢?实际上,不是每个人都能准确地做出判 断,因此,在第 3 章介绍 KISS 原则的时候,我们会通过具体的代码示例详细说明。

6 可复用性(reusability)

我们可以将代码的可复用性简单地理解为“尽量减少重复代码的编写,复用已有代码”。在后续章节中,我们会经常提到“可复用性”这一代码评价标准。例如,当介绍面向对象特性 的时候,我们会提到继承、多态存在的目的之一就是提高代码的可复用性;当介绍设计原则的 时候,我们会提到单一职责原则与代码的可复用性相关;当介绍重构技巧的时候,我们会提到 解耦、高内聚和模块化等能够提高代码的可复用性。可见,可复用性是一个重要的代码评价标 准,也是很多设计原则、设计思想和设计模式等所要实现的最终效果。实际上,代码的可复用性与 DRY(Don’t Repeat Yourself)原则的关系紧密,因此,在第 3 章介绍 DRY 原则的时候,我们还会介绍代码复用相关的更多知识,如提高代码的可复用性的 编程方法等。

7 可测试性(testability)

相比上述 6 个代码质量评价标准,代码的可测试性较少被提及,但它同样重要。代码的可 测试性的高低可以从侧面准确地反映代码质量的高低。代码的可测试性低,难以编写单元测试,那么,基本能够说明代码的设计有问题。关于代码的可测试性,我们将在重构部分(见 5.3 节)详细讲解。

以上内容节选自《设计模式之美》一书。

《设计模式之美》这本书可以从面向对象编程范式、设计原则、代码规范、重构技巧和设计模式帮助你打通编程任督二脉,将编程内功与技巧融会贯通,大大提升你的编程功力!

链接: https://www.fly63.com/article/detial/11788


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK