作者 | 陈胜利(李渔),网上有个段子,说建筑工程师不会轻易答应会给摩天大楼增加一个地下室,但代码开发工程师却经常在干这样的事,并且总有人会对你说“这个需求很简单”。到土里埋个雷,这确实不复杂,但我们往往面临的真实场景其实是“在一片雷区的土里埋一个雷”。而雷区里哪里有雷,任何人都不知道。,回到我们日常的写代码的场景,我们一直在说系统很复杂,那到底什么是系统复杂度呢?最近几个月,蚂蚁代码力平台(注:是蚂蚁的代码评价平台)进入大家视野,很多同学开始关注起自己代码力的得分情况。作为团队的稳定性底盘负责人,也经常和大家探讨为什么会因为圈复杂度高而被扣分。那么,怎么才能写的一手可读,可扩展,可维护[注1]的好代码?本文作者尝试结合在团队内部的实践,分享下过程中心得,希望对大家的代码圈复杂度治理提供微弱的帮助。,先看看圈复杂度的通用的定义,圈复杂度(Cyclomatic complexity,简写CC)[注2]也称为条件复杂度/循环复杂度,是一种代码复杂度的衡量标准。由托马斯·J·麦凯布(Thomas J. McCabe, Sr.)于1976年提出,用来表示程序的复杂度,其符号为VG。它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行路径条数,也可理解为覆盖所有的可能情况最少使用的测试用例数。说人话,圈复杂度关系到质量同学最少需要设计多少用例才能覆盖你的代码分支。,蚂蚁广目平台给出了比较详细的说明,这里直接引用,网上也可以查到类似内容。节点判断计算公式为:V (G) = P + 1 注:除了节点判断法,还有其他方法,如点边判断法,这里只选一个用于说明。其中P为条件节点数,条件节点类型为:a.条件语句,b.条件表达式(二元或多元),举例如下(部分代码省略后用xxx代替):,好了,了解了圈复杂度的定义之后,我们基本可以得出一个结论,圈复杂度大说明程序逻辑复杂,不利于代码的阅读,维护,和后续扩展。如果需要看懂一个圈复杂度高的方法,需要小心翼翼整理所有的分支情况,而改动这类代码更像踏入雷区一样。,下面,我们来看一段代码案例(部分内容已省略)。,原代码大概400行以上,复杂度69,憋了一口长气才读完。如果让你来接手这段代码,是不是感觉很头疼?需要梳理里面各种分支逻辑,弄清楚主干脉络。,那么什么样的代码才容易读,容易上手呢?一般业界认为代码可读性,可测试,维护成本和圈复杂度有很大关系,具体如下:,,1.【知己知彼,了解自己代码复杂度】这个比较简单,有以下几种方式:a.自己数下判定节点(if while for catch case and or等)大概就知道圈复杂度是多大了,参考上面怎么计算圈复杂度章节。b.在蚂蚁内部使用的广目平台,也可以查看到新提交commit记录里,哪些方法圈复杂度比较高。,,c.在代码提交之前,自己用idea小插件(Metrics Reloaded插件),一次性扫描自己负责的系统所有方法的复杂度。,,红色部分标识圈复杂度,数字越大复杂度越高。,2.【对症下药,降低复杂度】网上有很多方法,我总结了下,大概有以下几种方法一:抽取出独立逻辑的子方法,把复杂逻辑拆分成几个独立模块,再去读代码,就会感觉清晰很多。以上面举例的复杂度69的方法为例,我们做了如下的方法拆分,是不是感觉清晰了很多?,方法二:优化逻辑判断,通过提取频繁出现的条件, 或者调整判断顺序等方式达到简化代码目的。,方法三:适当使用java新特性,降低大量的if判断。下面是来自团队一淏同学的提供的优化案例,当然,只要用心钻研,降低复杂度还有很多方法,这里不一一列举了。总结下思路:,作为蚂蚁工程师的我们,开发代码也应该像创作一个艺术品,深思熟虑,精雕细刻,经过产品的不断升级迭代,仍然能够保持顽强的生命力,就像代码四层境界[注3]里面说的第四层,经过了时间历练“我的代码还在用”。,引用:[注1]对代码的领悟之-高质量代码有三要素:可读性、可维护性、可扩展性 :https://wenku.baidu.com/view/ce7e54e60f22590102020740be1e650e52eacff5.html,[注2]详解圈复杂度:https://baike.baidu.com/item/%E5%9C%88%E5%A4%8D%E6%9D%82%E5%BA%A6/828737,[注3]代码的四层境界:https://www.sohu.com/a/238434622_185201, 第一层“我的代码写完了”,第二层“我的代码写好了”,第三层“我的代码能跑了”,第四层“我的代码还在用”
© 版权声明
文章版权归作者所有,未经允许请勿转载。