分享下前 Google 工程师「王争」对于这个话题的思考。
在我的工作经验中,每当共事评论起我的项目代码品质的时候,听到的最多的评语就是:“代码写得很烂”或者“代码写得很好”。用“好”“烂”这样的字眼来形容,十分地抽象。当我具体问到底如何烂、如何好的时候,只管大部分共事都能简略地列举上几个点,但往往都不够全面、十分系统,也切不中要害。
当然,也有一些工程师对如何评估代码品质有所意识,比方,好代码是易扩大、易读、简略、易保护的等等,但他们对于这些评估的了解往往只停留在外表概念上,对于诸多更深刻的问题,比方,“怎么才算可读性好?什么样的代码才算易扩大、易保护?可读、可扩大与可保护之间有什么关系?可保护中‘保护’两字该如何了解?”等等,并没有太清晰的意识。
对于程序员来说,分别代码写得“好”还是“烂”,是一个十分重要的能力。这也是咱们写出好代码的前提。毕竟,如果咱们连什么是好代码、什么是烂代码,都分辨不清,又谈何写出好代码呢?
所以,明天咱们就聊一聊对于代码品质评判的相干问题,心愿你在学完明天的内容之后,对代码品质的评判有个更加清晰、更加透彻的意识和了解。
如何评估代码品质的高下?
实际上,咱们平时嘴中常说的“好”和“烂”,是对代码品质的一种形容。“好”抽象地示意代码品质高,“烂”抽象地示意代码品质低。对于代码品质的形容,除了“好”“烂”这样比较简单粗犷的形容形式之外,咱们也常常会听到很多其余的形容形式。这些形容办法语义更丰盛、更业余、更细化。我搜集整理了一下,列举在了上面。这些简直涵盖咱们所能听到的形容代码品质的所有罕用词汇,你能够看一看。
灵活性(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)……
看到如此多的形容词,你可能要问了,咱们到底该用哪些词来形容一段代码的品质呢?
实际上,咱们很难通过其中的某个或者某几个词汇来全面地评估代码品质。因为这些词汇都是从不同维度来说的。这就好比,对于一个人的评估,咱们须要综合各个方面来给出,比方性情、面貌、能力、财产等等。代码品质高下也是一个综合各种因素失去的论断。咱们并不能通过繁多的维度去评估一段代码写的好坏。比方,即便一段代码的可扩展性很好,但可读性很差,那咱们也不能说这段代码品质高。
除此之外,不同的评估维度也并不是齐全独立的,有些是具备蕴含关系、重叠关系或者能够相互影响的。比方,代码的可读性好、可扩展性好,就意味着代码的可维护性好。而且,各种评估维度也不是非黑即白的。比方,咱们不能简略地将代码分为可读与不可读。如果用数字来量化代码的可读性的话,它应该是一个间断的区间值,而非 0、1 这样的离散值。
不过,咱们真的能够主观地量化一段代码品质的高下吗?答案是否定的。对一段代码的品质评估,经常有很强的主观性。比方,怎么样的代码才算可读性好,每个人的评判规范都不大一样。这就好比咱们去评估一本小说写得是否精彩,自身就是一个很难量化的、十分主观的事件。
正是因为代码品质评估的主观性,使得这种主观评估的准确度,跟工程师本身教训有极大的关系。越是有教训的工程师,给出的评估也就越精确。相同,资格比拟浅的工程师就经常会感觉,没有一个可执行的主观的评估规范作为参考,很难精确地判断一段代码写得好与坏。有的时候,本人感觉代码写得曾经够好了,但实际上并不是。所以,这也导致如果没有人领导的话,本人一个人闷头写代码,即使写再多的代码,代码能力也可能始终没有太大进步。
最罕用的评估规范有哪几个?
认真看后面列举的所有代码品质评估规范,你会发现,有些词语过于抽象、形象,比拟偏差对于整体的形容,比方优雅、好、坏、整洁、清晰等;有些过于细节、并重方法论,比方模块化、高内聚低耦合、文档详尽、分层清晰等;有些可能并不仅仅局限于编码,跟架构设计等也有关系,比方可伸缩性、可用性、稳定性等。
为了做到对症下药、有重点地学习,我筛选了其中几个最罕用的、最重要的评估规范,来具体解说,其中就包含:可维护性、可读性、可扩展性、灵活性、简洁性(简略、简单)、可复用性、可测试性。接下来,咱们逐个解说一下。
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.”翻译成中文就是:“任何傻瓜都会编写计算机能了解的代码。好的程序员可能编写人可能了解的代码。”Google 外部甚至专门有个认证就叫作 Readability。只有拿到这个认证的工程师,才有资格在 code review 的时候,批准他人提交代码。可见代码的可读性有多重要,毕竟,代码被浏览的次数远远超过被编写和执行的次数。
我集体认为,代码的可读性应该是评估代码品质最重要的指标之一。咱们在编写代码的时候,时刻要思考到代码是否易读、易了解。除此之外,代码的可读性在十分大程度上会影响代码的可维护性。毕竟,不论是批改 bug,还是批改增加性能代码,咱们首先要做的事件就是读懂代码。代码读不大懂,就很有可能因为考虑不周全,而引入新的 bug。
既然可读性如此重要,那咱们又该如何评估一段代码的可读性呢?
咱们须要看代码是否合乎编码标准、命名是否达意、正文是否详尽、函数是否长短适合、模块划分是否清晰、是否合乎高内聚低耦合等等。你应该也能感觉到,从侧面上,咱们很难给出一个笼罩所有评估指标的列表。这也是咱们无奈量化可读性的起因。
实际上,code review 是一个很好的测验代码可读性的伎俩。如果你的共事能够轻松地读懂你写的代码,那阐明你的代码可读性很好;如果共事在读你的代码时,有很多疑难,那就阐明你的代码可读性有待进步了。
3. 可扩展性(extensibility)
可扩展性也是一个评估代码品质十分重要的规范。它示意咱们的代码应答将来需要变动的能力。跟可读性一样,代码是否易扩大也很大水平上决定代码是否易保护。那到底什么是代码的可扩展性呢?
代码的可扩展性示意,咱们在不批改或大量批改原有代码的状况下,通过扩大的形式增加新的性能代码。说直白点就是,代码预留了一些性能扩大点,你能够把新性能代码,间接插到扩大点上,而不须要因为要增加一个性能而大动干戈,改变大量的原始代码。
对于代码的扩展性,在前面讲到“对批改敞开,对扩大凋谢”这条设计准则的时候,我会来具体解说,明天咱们只须要晓得,代码的可扩展性是评估代码品质十分重要的规范就能够了。
4. 灵活性(flexibility)
灵活性也是形容代码品质的一个罕用词汇。比方咱们常常会听到这样的形容:“代码写得很灵便”。那这里的“灵便”该如何了解呢?
只管有很多人用这个词汇来形容代码的品质。但实际上,灵活性是一个挺形象的评估规范,要给灵活性下个定义也是挺难的。不过,咱们能够想一下,什么状况下咱们才会说代码写得好灵便呢?我这里列举了几个场景,心愿能引发你本人对什么是灵活性的思考。
- 当咱们增加一个新的性能代码的时候,原有的代码曾经预留好了扩大点,咱们不须要批改原有的代码,只有在扩大点上增加新的代码即可。这个时候,咱们除了能够说代码易扩大,还能够说代码写得好灵便。
- 当咱们要实现一个性能的时候,发现原有代码中,曾经形象出了很多底层能够复用的模块、类等代码,咱们能够拿来间接应用。这个时候,咱们除了能够说代码易复用之外,还能够说代码写得好灵便。
- 当咱们应用某组接口的时候,如果这组接口能够应答各种应用场景,满足各种不同的需要,咱们除了能够说接口易用之外,还能够说这个接口设计得好灵便或者代码写得好灵便。
从刚刚举的场景来看,如果一段代码易扩大、易复用或者易用,咱们都能够称这段代码写得比拟灵便。所以,灵便这个词的含意十分宽泛,很多场景下都能够应用。
5. 简洁性(simplicity)
有一条十分驰名的设计准则,你肯定听过,那就是 KISS 准则:“Keep It Simple,Stupid”。这个准则说的意思就是,尽量放弃代码简略。代码简略、逻辑清晰,也就意味着易读、易保护。咱们在编写代码的时候,往往也会把简略、清晰放到首位。
不过,很多编程经验不足的程序员会感觉,简略的代码没有技术含量,喜爱在我的项目中引入一些简单的设计模式,感觉这样能力体现本人的技术水平。实际上, 思从深而行从简,真正的高手能云淡风轻地用最简略的办法解决最简单的问题。这也是一个编程新手跟编程老手的本质区别之一。
除此之外,尽管咱们都能意识到,代码要尽量写得简洁,合乎 KISS 准则,但怎么样的代码才算足够简洁?不是每个人都能很精确地判断进去这一点。所以,在前面的章节中,当咱们讲到 KISS 准则的时候,我会通过具体的代码实例,具体给你解释,“为什么 KISS 准则看似非常简单、好了解,但实际上用好并不容易”。明天,咱们就暂且不开展具体解说了。
6. 可复用性(reusability)
代码的可复用性能够简略地了解为,尽量减少反复代码的编写,复用已有的代码。在前面的很多章节中,咱们都会常常提到“可复用性”这一代码评估规范。
比方,当讲到面向对象个性的时候,咱们会讲到继承、多态存在的目标之一,就是为了进步代码的可复用性;当讲到设计准则的时候,咱们会讲到繁多职责准则也跟代码的可复用性相干;当讲到重构技巧的时候,咱们会讲到解耦、高内聚、模块化等都能进步代码的可复用性。可见,可复用性也是一个十分重要的代码评估规范,是很多设计准则、思维、模式等所要达到的最终成果。
实际上,代码可复用性跟 DRY(Don’t Repeat Yourself)这条设计准则的关系挺严密的,所以,在前面的章节中,当咱们讲到 DRY 设计准则的时候,我还会讲更多代码复用相干的常识,比方,“有哪些编程办法能够进步代码的复用性”等。
7. 可测试性(testability)
绝对于后面六个评估规范,代码的可测试性是一个绝对较少被提及,但又十分重要的代码品质评估规范。代码可测试性的好坏,能从侧面上十分精确地反馈代码品质的好坏。代码的可测试性差,比拟难写单元测试,那基本上就能阐明代码设计得有问题。对于代码的可测试性,咱们在重构那一部分,会花两节课的工夫来具体解说。当初,你临时只须要晓得,代码的可测试性十分重要就能够了。
如何能力写出高质量的代码?
我置信每个工程师都想写出高质量的代码,不想始终写没有成长、被人吐槽的烂代码。那如何能力写出高质量的代码呢?针对什么是高质量的代码,咱们刚刚讲到了七个最罕用、最重要的评估指标。所以,问如何写出高质量的代码,也就等同于在问,如何写出易保护、易读、易扩大、灵便、简洁、可复用、可测试的代码。
要写出满足这些评估规范的高质量代码,咱们须要把握一些更加细化、更加能落地的编程方法论,包含面向对象设计思维、设计准则、设计模式、编码标准、重构技巧等。而所有这些编程方法论的最终目标都是为了编写出高质量的代码。
比方,面向对象中的继承、多态能让咱们写出可复用的代码;编码标准能让咱们写出可读性好的代码;设计准则中的繁多职责、DRY、基于接口而非实现、里式替换准则等,能够让咱们写出可复用、灵便、可读性好、易扩大、易保护的代码;设计模式能够让咱们写出易扩大的代码;继续重构能够时刻放弃代码的可维护性等等。具体这些编程方法论是如何进步代码的可维护性、可读性、可扩展性等等的呢?咱们在前面的课程中慢慢来学习。
重点回顾
明天的内容到此就讲完了。咱们来一起回顾一下,你须要重点把握的几个知识点。
1. 如何评估代码品质的高下?
代码品质的评估有很强的主观性,形容代码品质的词汇也有很多,比方可读性、可维护性、灵便、优雅、简洁等,这些词汇是从不同的维度去评估代码品质的。它们之间有相互作用,并不是独立的,比方,代码的可读性好、可扩展性好就意味着代码的可维护性好。代码品质高下是一个综合各种因素失去的论断。咱们并不能通过繁多的维度去评估一段代码的好坏。
2. 最罕用的评估规范有哪几个?
最罕用到几个评判代码品质的规范是:可维护性、可读性、可扩展性、灵活性、简洁性、可复用性、可测试性。其中,可维护性、可读性、可扩展性又是提到最多的、最重要的三个评估规范。
3. 如何能力写出高质量的代码?
要写出高质量代码,咱们就须要把握一些更加细化、更加能落地的编程方法论,这就蕴含面向对象设计思维、设计准则、设计模式、编码标准、重构技巧等等,这也是咱们前面课程学习的重点。
话题探讨
除了我明天提到的这些,你感觉还有哪些其余的代码评估规范十分重要?聊一聊你心目中的好代码是什么样子的?
欢送在留言区发表你的观点,积极参与探讨。你也能够把这篇文章分享给你的敌人,邀请他一起学习。