相信很多开发者在开发的时候会常常抱怨说:“这代码太糟糕了”、“这代码谁写的,根本看不懂”、“为什么要这么写,感觉很多都没用”,再一看提交记录,说不定正是自己几个月前提交的代码。

 

《代码整洁之道》让应用质量更可靠_编程语言

 

Martin的《Clean Code》这本书中引用了一副很有趣的漫画,衡量代码质量的唯一有效标准就是:WTFs/minute,这是个很生动的表达。这种事情十有八九的开发者都经历过,但是为什么会发生这种问题呢,什么是好的代码,有没有办法能够预防这种问题呢,已经糟糕的代码要如何改进呢,都是这篇文章接下来将要说明的。

 

为什么会有糟糕的代码

 

 

 

想要解决糟糕的代码,首先要正视糟糕代码的存在。糟糕代码的源头在哪里,其实就在每个人的态度里面。

 

很多开发者都会找各种各样的理由,什么项目进度问题,什么DDL要到了,或者说还有很多事情要做之类之类的。但这归根结底都要看我们是以什么态度在写代码的,很多情况下,只有把代码写好,才是赶上进度的最好办法。

 

《代码整洁之道》让应用质量更可靠_编程语言_02

 

除了赶进度,还有什么想法会导致糟糕的代码呢。书中提到的勒布朗法则“稍后等于永不”,很可能戳中了很多开发者的心理状态。看一下截图中我们项目中TODO的数量,再看看TODO的时间,有一些已经过了两三年了。虽然说写TODO注释是一个好的习惯,但是千万不要让这个TODO变成NEVER。

 

 

什么是质量好的代码

 

 

 

承认了糟糕代码的存在,知道了为什么糟糕代码会存在,下一步就是需要知道糟糕代码的对立面,什么是质量好的代码。《Clean Code》这本书中提出的核心观念就是代码质量与其整洁度成正比,那我们现在的追求就是写出整洁的代码。

什么是整洁的代码,很多大牛都说了各种各样的定义。我们整理一下言论,最后总结出这四个点:体现理念、减少依赖、通过测试、没有重复。虽然仅仅只有这么几个关键点,我们开发者是需要注意大量的细节才能够做到的。

 

命名与函数

 

 

《代码整洁之道》让应用质量更可靠_编程语言_03

 

直接以我们基线代码中的一个例子开端,从命名开始,来让大家感受一下如何写出整洁的代码。看这个例子,一个简单的二分插入,仅仅是修改一个命名,就能让人很直观的明白每个参数的作用,在之后的算法中,也不容易混淆,连注释都可以省略了。     

 

《代码整洁之道》让应用质量更可靠_编程语言_04

 

好的命名简单来说就是要做到名副其实的命名,做的事情是什么,名字就是什么,并且千万不要出现拼写错误,这样可以降低无数的沟通与看代码的成本。我们最近出过的线上故障,复盘后发现可以通过换个名字就能提前避免问题:一位同事在使用另一位同事的代码时,调用了一个get方法,然而这个get方法的实际作用却是getAndReset,上线后导致调用此功能的用户信息被重置。

       

命名的问题,一定不要惧怕两点:一个是不要怕长名字,Object-C中都有超过两百个字符的函数名;一个就是不要怕改名字,起个更好的名字更加重要,现代IDE都会帮你解决重构的问题。

       

一个好的名字就是体现理念的关键一点,那对于函数来说,体现理念的关键点就在于短小且只做一件事。过长做事过多的函数只会让读代码的人异常困难,降低项目整体的生产力,毕竟在我们写新代码的过程中,其实大部分时间都在阅读着旧代码。

 

注释

 

 

 

《代码整洁之道》让应用质量更可靠_编程语言_05

 

那可能会有人说体现理念,那就多写注释吧。但很直接的一点就是,注释并不能美化糟糕的代码,最好的注释其实就是代码本身。如图的废话注释,这样的注释有存在的必要吗。绝大部分注释要做的事情,是需要解释代码的设计,也就是俗称的why。对于what的注释,则是能用代码解释就是最好的,代码不够直观的才需要写注释。下面的这些好注释才是真正能够体现理念的注释。

 

《代码整洁之道》让应用质量更可靠_编程语言_06

 

对于我来说,最不喜欢的注释,就是注释掉的代码。看看这些几年前的陈旧的注释掉的代码,在大家都在用Git的情况下,注释大段大段代码早就没有必要了。

 

《代码整洁之道》让应用质量更可靠_编程语言_07

 

格式

 

 

 

接下来要提到的是代码格式的问题,良好的格式,能提供良好的沟通,对于提升代码表达力来说,是头等大事,但也是最好解决的事情。IDE甚至于一些文本编辑器都提供了一键格式化的功能,其实就是一个快捷键随手按下的事情,养成这个习惯,真的非常的简单,就看有没有这个态度去做。

 

《代码整洁之道》让应用质量更可靠_编程语言_08

 

错误处理

 

 

 

说到错误处理,可能很多开发者会想到try-catch-finally三段式结构,但当然整洁的代码不止于此。学习使用自定义异常,能比错误码提供更多更详尽的信息,用于错误定位追踪都非常的方便。而null值的问题,可能很多开发者都会头疼。我们可以常常用@Nullable与@NonNull注解标明我们变量参数返回值等的状态。有了IDE的提示,在处理null的问题上会方便很多。当然了,切换到Kotlin语言,使用”?”过滤null也可以达到这个目的,这也是Kotlin语言非常好用的一点。

 

《代码整洁之道》让应用质量更可靠_编程语言_09

结构

 

 

 

之前大部分都是再说细节的层面,在更高的层面上,有什么要考虑的呢。这里有太多太多可以说的,但都需要大量的开发实践,熟悉各类架构,才能做到真正的好的代码。在这里,简单说说书中提到的那些,我们可以在不断的学习实践重构中做到更好。

 

类需要封装,需要短小,需要符合单一全职原则,需要隔离修改,需要使用接口隐藏实现。对于安卓来说,对于Activity等类,我们可以采用MVP架构或Jetpack提供的包进行重构。在我的重构下,我们的MainActivity从三千多行,UI、逻辑、数据杂糅,拆成了多个接口与六七个实现类,每个类维持在六七百行的水平,并只做某单一方面的事情,在这之后维护起来就变得非常的容易。

       

在系统层面,可以写单元测试,可以切分层级,可以使用各种设计模式,可以考虑依赖注入。所有的一切,都是为了能够做到整洁的代码:体现理念、减少依赖、通过测试、没有重复。

 

规范

 

 

 

说了这么多,如何能够让大家知道呢,这时候就需要有规范出场了。没有规矩不成方圆,我们小组结合Google、阿里等公司的各规范文档,以及整合了我们自身多年积累下来的WIKI文档——爱奇艺基线开发规约,推广给基线开发者们学习。

 

如何改进和维护代码质量

 

 

 

良好的代码提交及Review流程,文档式的代码规范,静态代码的扫描,是很好的解决糟糕代码的一条龙服务。如图所示,我们爱奇艺安卓基线是从下面这一些方面对我们的代码进行了各类的控制。在代码提交前、提交后、代码合并后,都会做相应的验证,在保证开发效率的同时,也能兼顾代码质量。

 

《代码整洁之道》让应用质量更可靠_编程语言_10

 

相信开发者们对这些工具都不陌生:CheckStyle、PMD、FindBugs、AndroidLint、SonarQube等等,如何在合适的阶段用这些工具是我们需要考量的。

 

 

PreCommit

 

 

 

我们在代码提交前会使用GitHooks,进行CheckStyle代码格式命名等的验证,验证速度快,修改也快。这里检测的问题,都是最基础的也是最好解决的问题,所以我们会要求新代码提交前就处理好这些问题。

 

AfterPush

 

 

 

当代码提交上去之后要做什么呢,这时候我们就要请出Gerrit与Jenkins了。Gerrit提交的代码并不会直接入库,这时候就可以通过各种方式Review代码。用过Gerrit的一般都会使用Code-Review与Verified标签,其中Code-Review为主动加人对业务逻辑进行Review,Verified主要用于Jenkins验证此Patch是否能够编译通过。

《代码整洁之道》让应用质量更可靠_编程语言_11

 

在我们的实践中,Verified与Jenkins的联动赋予了更多的功能,除了正常的工程编译外,还提供了组件化打包以及实时代码质量检测的功能。例如:APK文件大小、APP权限申请、敏感文件控制、封板分支限制等一系列可较快速得出结果的检查。

《代码整洁之道》让应用质量更可靠_编程语言_12

 

我们在Gerrit上还加入了自定义的Code-Quality标签。在有了代码规范后,自然就要有监督规范的小组成员。Jenkins会根据不同的几率,随机加入代码Review小组两名成员对代码质量进行人工Review。Review小组成员会审核代码,并标记Code-Quality标签。标签在开始时仅仅作为标记作用,随着代码质量的逐渐提升,标签的重要性也会逐渐升级,之后如果被-1后,代码就不可合入主仓库。

《代码整洁之道》让应用质量更可靠_编程语言_13

AfterMerge

 

 

       

代码通过种种考验,合到了主仓库中,这个时候就可以执行一些时间较长的扫描任务,Jenkins与SonarQube的作用就体现了出来。我们在Jenkins上建立了各类定时构建,每天都会对代码进行各类扫描。例如敏感API调用检测、解耦检测、单元测试、各团队代码SonarQube扫描等较耗时的操作。

 

《代码整洁之道》让应用质量更可靠_编程语言_14

 

SonarQube作为代码质量管理系统,提供了各类代码问题完全自动化的分析,可以接入各类静态代码扫描插件。我们在此接入了SonarJava、CheckStyle、PMD、FindBugs、AndroidLint等各类插件。部分插件还经过重写,加入了自定义的规则。

 

《代码整洁之道》让应用质量更可靠_编程语言_15

 

我们还在内部平台做了中间页(图为初版设计图),提供各项目的问题的直观展示,并将提供快速接入、重点问题跟踪、责任人问题数量、定期发布报告等一系列功能。可以更好更直观的监控我们各平台的代码质量。除此之外,平台还接入了各类质量检测工具。从APK包大小分析,敏感权限扫描再到反馈报警系统等,之后还会不断有新的检测工具接入,共同承担起维护爱奇艺代码质量的责任。

 

结语

 

 

 

努力,让世界比你来时更好一些”,来自童子军创始者的遗言,应用到我们的专业领域,就是希望我们能够做到时时保持代码整洁。如果我们能够做到每次push时,代码都比pull下来时更干净。有这样的态度,我们的项目质量终将变得更好。