文章插图
作者|王烨 转自美团点评技术团队
前言本文从clean code的几个大前提出发,提出了实践clean code的一些手段,重点放在促成clean code的一些常用编码和重构技巧 。本文只代表笔者本人的一点点感悟 。好的代码,最需要的,还是大家不断追求卓越的精神 。你有什么经验可以分享呢?
写在前面clean code,顾名思义就是整洁的代码,或者说清晰、漂亮的代码,相信大多数工程师都希望自己能写出这样的代码 。
也许这是个千人千面的话题,每个工程师都有自己的理解 。比如我,从一个天天被骂代码写得烂的人,逐渐学习成长,到现在也能写的出“人模人样”的代码来了 。这期间算是积累了一点经验心得,想和大家分享,抛砖引玉 。
本文主要针对面向对象编程的clean code来阐述,面向过程代码的思路会比较不同,不在本文的讨论范畴 。
代码整洁的大前提代码大部分时候是用来维护的,而不是用来实现功能的
这个原则适用于大部分的工程 。我们的代码,一方面是编译好让机器执行,完成功能需求;另一方面,是写给身边的队友和自己看的,需要长期维护,而且大部分项目都不是朝生夕死的短命鬼 。
大部分情况下,如果不能写出清晰好看的代码,可能自己一时爽快,后续维护付出的代价和成本将远高于你的想象 。
对清晰好看代码的追求精神,比所有的技巧都要重要 。
优秀的代码大部分是可以自描述的,好于文档和注释
当你翻看很多开源代码时,会发现注释甚至比我们自己写的项目都少,但是却能看的很舒服 。当读完源码时,很多功能设计就都清晰明了了 。通过仔细斟酌的方法命名、清晰的流程控制,代码本身就可以拿出来当作文档使用,而且它永远不会过期 。
相反,注释不能让写的烂的代码变的更好 。如果别人只能依靠注释读懂你的代码的时候,你一定要反思代码出现了什么问题(当然,这里不是说大家不要写注释了) 。
说下比较适合写注释的两种场景:
- public interface,向别人明确发布你功能的语义,输入输出,且不需要关注实现 。
- 功能容易有歧义的点,或者涉及比较深层专业知识的时候 。比如,如果你写一个客户端,各种config参数的含义等 。
之前见过一些所谓“高手”的代码都比较抽象,各种工厂、各种继承 。想找到一个实现总是要山路十八弯,一个工程里大部分的类是抽象类或者接口,找不到一两句实现的代码,整个读起代码来很不顺畅 。我跟他聊起来的时候,他的主要立场是:保留合适的扩展点,克服掉所有的硬编码 。
其实在我看来,也许他的代码被“过度设计”了 。首先必须要承认的是,在同一个公司工作的同事,水平是参差不齐的 。无论你用了如何高大上的设计,如果大多数人都不能理解你的代码或者读起来很费劲的话,其实这是一个失败的设计 。
当你的系统内大部分抽象只有一个实现的时候,要好好思考一下,是不是设计有点过度了,清晰永远是第一准则 。
代码整洁的常见手段
记住原则后,我们开始进入实践环节,先来看下有哪些促成clean code的常见手段 。
code review
很多大公司会用git的pull request机制来做code review 。我们重点应该review什么?是代码的格式、业务逻辑还是代码风格?我想说的是,凡是能通过机器检查出来的事情,无需通过人 。比如换行、注释、方法长度、代码重复等 。除了基本功能需求的逻辑合理没有bug外,我们更应该关注代码的设计与风格 。比如,一段功能是不是应该属于一个类、是不是有很多相似的功能可以抽取出来复用、代码太过冗长难懂等等 。
我个人非常推崇集体code review,因为很多时候,组里相对高级的工程师能够一眼发现代码存在较大设计缺陷,提出改进意见或者重构方式 。我们可以在整个小组内形成一个好的文化传承和风格统一,并且很大程度上培养了大家对clean code的热情 。
勤于重构
好的代码,一般都不是一撮而就的 。即使一开始设计的代码非常优秀,随着业务的快速迭代,也可能被改的面目全非 。
为了避免重构带来的负面影响(delay需求或者带来bug),我们需要做好以下的功课: