“这代码真烂”或“代码写得真好”。这描述太笼统,具体怎么烂了、怎么就好了?

也有一些工程师对如何评价代码质量有所认识,如好代码易扩展、易读、简单、易维护,但更深入的,“怎么算可读性好?代码怎么算易扩展、易维护?可读、可扩展与可维护之间有什么关系?可维护中‘维护’两字该如何理解?”

如果连啥是好代码、烂代码,都分不清,又谈何写好代码?

如何评价代码质量的高低?

对代码质量的一种描述:

  • “好”笼统地表示代码质量高
  • “烂”笼统地表示代码质量低

其他描述方法语义更丰富、更专业、更细化:

灵活性(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)、好(good)、坏(bad)……

到底该用啥词描述代码质量?很难通过其中某个词汇全面评价代码质量,因为都是从不同立场来说。代码质量高低需综合各种因素,如一段代码的可扩展性好,但可读性差,也不能说这段代码质量高。

不同评价维度也并不是完全独立的,有些是具有包含关系、重叠关系或互相影响的。如代码的可读性好、可扩展性好,就意味着代码可维护性好。而且,各种评价维度也不是非黑即白。如不能简单将代码分为可读、不可读。

可以客观量化代码质量高低吗?No!代码质量评价常有很强主观性。如代码可读性,每个人标准不一。正因代码质量评价的主观性,使得这种主观评价的准确度,跟工程师自身经验有极大关系。越有经验,给出评价越准确。

常用评价标准

  • 有些词过于笼统、抽象,比较偏向对于整体的描述,如优雅、好、坏、整洁、清晰
  • 有些过于细节、偏重方法论,比如模块化、高内聚低耦合、文档详尽、分层清晰等
  • 有些可能并不仅仅局限于编码,跟架构设计等也有关系,比如可伸缩性、可用性、稳定性等

为有的放矢,挑选最常用的、最重要评价标准详细讲解:可维护性、可读性、可扩展性、灵活性、简洁性(简单、复杂)、可复用性、可测试性。

1.可维护性(maintainability)

“维护”不过就是修bug、修老代码、添加新代码。

  • 代码易维护,不破坏原有代码设计、不引入bug情况下,能快速修改或添加代码
  • 代码不易维护,修改或者添加代码需要冒着极大的引入新bug的风险,且需费很长时间才能完成

一个项目,维护代码时间>>编码时间。大部分时间可能都是在修bug、改老逻辑、添加新逻辑。所以,代码可维护性很重要。

如何判断代码可维护性好坏呢?

很难量化、偏向对代码整体的评价标准,类似“好”“坏”“优雅”。可维护性由多因素作用:

  • 可读性好、简洁、可扩展性好,就易维护;相反,就不易维护
  • 更细地,如代码分层清晰、模块化好、高内聚低耦合、遵从基于接口编程等,就易维护。此外,代码易维护性还和项目代码量、业务复杂度、技术复杂度、文档是否全面、团队开发水平有关

所以,从正面去分析一个代码是否易维护稍微有点难度。不过,我们可以从侧面上给出一个比较主观但又比较准确的感受。如果bug容易修复,修改、添加功能能够轻松完成,那我们就可以主观地认为代码对我们来说易维护。相反,如果修改一个bug,修改、添加一个功能,需要花费很长的时间,那我们就可以主观地认为代码对我们来说不易维护。

你可能会说,这样的评价方式也太主观了吧?没错,是否易维护本来就是针对维护的人来说的。不同水平的人对于同一份代码的维护能力并不是相同的。对于同样一个系统,熟悉它的资深工程师会觉得代码的可维护性还不错,而一些新人因为不熟悉代码,修改bug、修改添加代码要花费很长的时间,就有可能会觉得代码的可维护性不那么好。这实际上也印证了我们之前的观点:代码质量的评价有很强的主观性。

2.可读性(readability)

Martin Fowler说过:“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”

傻瓜都会写计算机能理解的代码。好的程序员能编写人能够理解的代码。

时刻要考虑代码是否易读、易理解。因为其也影响代码可维护性。毕竟,不管干啥,首先就是要读懂代码。代码读不懂,就可能考虑不全,天天写bug。

如何评价可读性?

符合编码规范?命名信达雅?注释详尽?函数长短合适?模块划分清晰?高内聚低耦合?地区,很难给出一个覆盖所有评价指标的列表。这也是无法量化可读性的原因。

其实CR是很好的测验代码可读性的途径:

  • 同事能轻松读懂你的代码,说明可读性很好
  • 他有很多疑问,那就说明你的代码可读性有很大进步空间

3 可扩展性(extensibility)

代码应对后续需求变化的能力,也很决定代码是否易维护。

在不修改或少修改原有代码情况下,通过扩展方式添加新功能代码。即代码预留一些功能扩展点,你能把新功能代码,直接插到扩展点,而无需因为要添加一个功能而大动干戈,改动大量原始代码!

“对修改关闭,对扩展开放”设计原则与之密切相关。

4 灵活性(flexibility)

挺抽象的标准,下定义还真难。何时会说代码写得灵活呢?

  • 添加一个新功能代码时,原有代码已预留好扩展点,无需修改原有代码,只要在扩展点添加新代码即可。可以说代码易扩展,还能说写得好灵活
  • 实现一个功能时,发现原有代码已抽象出很多底层可复用模块、类,可拿来直接用。除了说代码易复用,也能说代码灵活。
  • 使用某组接口时,若这组接口可以应对各种使用场景,满足各种不同需求,除了说接口易用,也能说灵活。

看来,只要一段代码易扩展、易复用或易用,都能说这段代码灵活,意义很宽泛。

5 简洁性(simplicity)

KISS原则:“Keep It Simple,Stupid”,尽量保持代码简单。代码简单、逻辑清晰,就意味着易读、易维护。编写代码时,优先考虑简单、清晰。

很多编程经验不足的程序员觉得简单代码无技术含量,喜欢引入复杂设计模式。实际上,思从深而行从简,高手能用最简单方法解决最复杂问题。

怎么样的代码算简洁?

后续讲KISS原则,会通过实例给你解释为何KISS原则看似非常简单、好理解,但实际上用好不容易。

6 可复用性(reusability)

简单理解为尽量减少重复代码,多复用代码:

  • OOP继承、多态目的之一就是提高代码可复用性
  • 单一职责原则也跟代码可复用性相关
  • 重构技巧,解耦、高内聚、模块化等都能提高代码的可复用性

可复用性也是重要标准,是很多设计原则、思想、模式等所要达到的最终效果。

跟DRY(Don’t Repeat Yourself)设计原则关系密切。

7 可测试性(testability)

较少被提及,但又重要的代码质量评价标准。能从侧面非常准确反应代码质量。代码可测试性差,难写单元测试,那基本上就能说明代码设计有问题。

如何写出高质量代码

等于问,如何写出易维护、易读、易扩展、灵活、简洁、可复用、可测试的代码?

掌握更细化、更能落地的编程方法论,包括面向对象设计思想、设计原则、设计模式、编码规范、重构技巧等。

如OOP的继承、多态能让我们写出可复用的代码;编码规范能让我们写出可读性好的代码;设计原则中的单一职责、DRY、基于接口而非实现、里式替换原则等,可以让我们写出可复用、灵活、可读性好、易扩展、易维护的代码;设计模式可以让我们写出易扩展的代码;持续重构可以时刻保持代码的可维护性等。