文章目录

我常常思考,如何才能保持代码的good smell。
Good smell,顾名思义,就是干净,清晰的代码风格。这看起来很简单,但真正做起来就发现并非坦途。

好的代码风格不是单方面形成的,围绕它周围有很多因素。
首先我们说到的是文档。

《人月神话》中提到了“焦油坑”这个概念。一方面它形容了组织的一种不良的发展趋势,另一方面也能反映项目的走势。
代码的坏味道不是一天两天就形成的,一个项目在设计初期应当都有着虽称不上优秀但也很清晰的结构。但随着时间的推移,新旧开发者的交替,项目变得越来越庞大、复杂,甚至变得有些怪异。于是我们会发现代码变得不可控了。奇特的命名,冗长的方法体,缺乏注释的类,聚集在一起的时候常常令新人摸不着头脑。

新人接手了这个项目,新的需求开始落地,于是他开始去审视整个项目。

常见的流程无外乎这几步:

首先他搭建了项目的运行环境,先跑起来从宏观上感知整个项目。运气好的,借助文档和同事的帮助项目能够顺利的运行;运气差些的可能在部署阶段就遇到了问题:
“这个配置文件怎么报错了?”“为什么会缺少jar?”“文件找不到了?”诸如此类的问题。连业务都没接触就已经碰壁了。对于这种情况,我想最需要的就是文档吧。

现实往往是残酷的,一个怪兽型的项目一直在成长。或许在项目初期有一些文档,但是程序员一般比较懒惰,有代码就够了,写什么文档啊?我能看懂就够了啊。

当然这种想法无可后非,三天五天可以看懂,如果一直接手的话,长期下去也基本能够理顺。但是项目在继续,程序员却不一定能伴随项目整个生命周期。新人会加入,需求会增加,老的代码还在系统中运行,新人接手之后先做的就是checkout代码并运行然后去理顺逻辑。

我想表达的是,或许我们没办法保持文档和代码库一直并行更新,但是我们起码能够总结一份部署文档,这样对于新人的上手及业务的交替是有着很大的益处的。

文档是很多程序员同学不愿意提及的东西,我们总是希望有模版能够参考。模版是好东西,我们参考前人总结的东西写出自己的文档并提交。然后呢?就没有然后了。文档的管理,这就又是一个问题,或许我们写了文档,而且不少,但需要的时候就是找不到。甚至系统内部的文档互相之间都不能正常的交流,问题的关键在于我们需要一个较为合理的文档管理。

文档管理实施起来不太容易。我们可以引入搜索引擎来做这件事,比如solr,es。制定一个良好的文档命名规范,诸如:项目名模块名版本日期作者.xxx,然后将其纳入搜索引擎的索引范围并加以备份。我想混乱的文档管理或许会有所改善。

对于文档我能说的并不多,毕竟刚上路不久,就不敢妄加评论了。

文档是系统的周边产出,而系统的核心便是代码,保持代码的good smell还是要从根本入手。

《代码整洁之道》已经对如何书写漂亮干净的代码做出了详细的阐述,笔者就不敢再班门弄斧了,在本文中我只说一些个人看法。

在日常开发中,我们经常看到一些较为久远的代码,没有过多的注释,逻辑也不慎清晰。一个类上千行,单个方法上百行是常有的事。找作者常常是不现实的事情,那么我们该如何去做?

重构。这个词是首先想到的。那么如何做才能既避免代码更加混乱又能方便后来的维护呢?

这种怪物级的代码有个特点,常常有些“魔数”在其中,首先我建议将其抽离出来,放到一个枚举类或者常量类中,或者直接放置在本类的头部,写明命名的含义。这样便一目了然。

然后是逻辑的优化。IDE一般都具有重构的功能,我建议使用该功能对一些简单逻辑进行方法提取,并加以注释,将大方法剥离为若干个小方法。可以使用类似于命令模式的风格,在大方法体中只进行方法调用和传值,方法的定义抽取到更小粒度的方法中。

对于老代码中存在的注释代码,维护者常常对其保持谨慎态度,“万一以后还用到怎么办?到时候岂不是抓瞎”这么想就有些过度谨慎了。从我们自身出发思考,在开发中,在对代码进行调试的过程中,经常简单的对某一段代码进行注释然后添加新的逻辑,而这段被注释的代码我们就不再使用了!但是它还存在于项目中,原因在于我们认为之后可能还会用到。现实是我们可能再也不会用它了,于是项目中的被注释掉的代码越来越多。开发者把这些代码留在项目中然后逐渐离开,而维护者面对他们只能选择谨慎。

放心删除它们吧,别让这些注释代码打乱整体的美感。什么?你怕万一以后还会用到?版本控制工具不就是干这件事的吗?工程化的开发流程中,只要备份体系完备,开发者完全不必担心代码没办法回退,所以大胆的优化吧,让代码中的污秽变得越来越少。可能你会说这是“洁癖”。我却建议开发者都或多或少有代码洁癖。虽然我们戏称自己是“码农”,即便如此,还有另一种说法,那就是“匠人”。匠心是成为一个合格的甚至大师级别的工匠的必备的品质,一个合格的工匠是不允许自己的作品有所污秽的。培养匠心请从让代码变得更加整洁开始。

代码变得整洁,一方面是表面上没有无用的注释,另一方面是格式和命名的规范。

每一种语言都有自己的标准开发格式,包括命名规范。比如如何缩进,如何空行,命名是采用大驼峰还是小驼峰等等。这些每家公司都有完善的定义,在这里我推荐《阿里巴巴Java开发手册
》,Java开发的同学们可以深入的阅读并付诸实施,我想对今后的发展必大有裨益。

无论是文档的书写还是代码格式的整洁都是外在的措施,是可以通过统一的规范加以训练和约束。更重要的还是代码内在的逻辑。

“好的代码是自注释的”。有言如是说。
我深以为然。

这里并不是鼓励不写注释,而是当开发到一定程度的时候,阅读代码本身就是在阅读注释。我们翻看某些开源代码时,会发现其中的代码比我们平时写的项目都少,但是却能够很清楚的理清逻辑,而且读起来很舒服。通过命名就能了解这是在操作谁干一件什么事。关于命名还是建议去学习上面提到的阿里的开发规范。这样的代码本身就是文档,而且不会过期。

注释是必需的,但不能滥用,泛滥的注释只能让阅读者更晕,在关键的逻辑或者专业知识比较深入的地方添加注释就足够了。进一步说,如果他人只能通过阅读注释来理清你的代码,这时候就一定要停下来思考一下是不是在设计上出了问题。

最后再从宏观的角度简单阐述一下保持代码good smell的一些良好实践。

【适度使用设计模式】

设计模式的适度采用能够提高代码的易读性和精简性。但是有些同学为了炫技在不必要的地方使用设计模式,处处封装,处处工厂、单例,滥用接口导致代码变得不必要的复杂就得不偿失了。抽象是为了重用,当抽象只有一个实现的时候放弃抽象或许是不错的方法。毕竟公司中水平是参差不齐的,保证代码能让大部分人看懂的前提下使用设计模式等技巧我想是不错的选择。

【进行Code Review】

这个就不赘述了,基本上在上线之前都会进行Code Review。确认代码是否是明显的逻辑问题,是否符合开发规范,以及和之前版本的一致性等问题都需要进行确认。开发者之间可以互相进行review,对对方做的好的地方进行记录,对发现的问题进行总结。在整个开发小组内形成一种良好的风格和氛围,从而培养并提高众人对clean code的热情。

【组合大于继承】

设计模式推崇组合优于继承。此处我借这个原则来阐述项目的迭代。新的需求到来的时候,我的习惯是先想想需求的关键,如何引入项目才能使对之前的结构影响最小。一方面,这依赖于项目本身的扩展能力,另一方面还在于开发者自身是如何构架新的功能的。对流程进行简单的梳理,找准切入点,尽量减少对历史遗留代码本身结构的影响,为了增量部署的方便也为了上线时减少新旧代码对比的工作量,尽量采用组合方式还不是在前人的基础上进行缝缝补补。

这样做的好处是多方面的,首先可以划清责任基线。在前人的基础上做了大量的修改,(注意这里是说修改而不是重构,这是两个不同的概念)出了问题很难分清到底是新代码的问题还是改动造成的问题。使用组合方式添加新的功能,遇到问题容易调试,出现问题也很容易划分责任归属。这其实在另一个意义上也促进开发者对自己写的代码负责,清晰的结构、详尽的注释在此时就发挥了重要的作用。对新人也就更加友好。所谓“己所不欲勿施于人”嘛。前人做的如何我们已经无法评说,但至少我们可以保证自己写的代码不会给后来人添麻烦。

小结

到这里文章暂时告一段落,但是我们的clean code旅程才刚刚开始,如何保持代码的good smell这个辩证的问题将会伴随一个开发者整个职业生涯。重要的是要对自己写的代码负责,我们写出的代码首先是给他人阅读的,其次才是计算机能够正常运行的。时刻优化调整自己的代码,避免“破窗效应”。就像“墨菲定律”中说的,“会出错的事总会出错,如果你担心某种情况发生,那么它就更有可能发生”,如果不对代码进行优化,那么它的腐化只是时间问题。希望本文能够对读者的编码有所启迪,写出干净易读的代码,将是你我共同的追求。

文章目录
Fork me on GitHub