圈复杂度那些事儿-前端代码质量系列文章(二)

Are You Smart Enough To Debug Your Own Code?
算法


Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.编程


上面这句话的意思是:调试的难度至关于写代码的两倍。所以,若是你写出了你自认为最聪明巧妙的代码,那么你将不具有拥有足够的智商去调试它。根据这段话的意思,咱们不该该去写出“自做聪明”的代码,不然的话咱们本身都没有能力维护。应该写出浅显易懂,刚毕业的实习生都能看懂的代码才是好代码。bash


01 圈复杂度定义

怎么才能写出浅显易懂的代码就不得不提软件工程质量度量方法中一个重要的概念——圈复杂度。微信

圈复杂度(Cyclomatic complexity,简写CC)也称为条件复杂度,是一种代码复杂度的衡量标准。由托马斯·J·麦凯布(Thomas J. McCabe, Sr.)于1976年提出,用来表示程序的复杂度。它能够用来衡量一个模块断定结构的复杂程度,数量上表现为独立现行路径条数,也可理解为覆盖全部的可能状况最少使用的测试用例数。编程语言

圈复杂度大说明程序代码的判断逻辑复杂,可能质量低且难于测试和维护。有研究代表复杂度和出现缺陷的数量存在强相关性,代表了越复杂的代码越可能会出错。函数式编程


02 圈复杂度计算

圈复杂度衡量的是程序中线性独立路径的数量。函数

例如:若是程序中不包含控制、判断、条件语句,那么复杂度就是 1,由于整个程序只有一条执行路径;测试

若是程序包含一条 IF 语句,那么就会有两条路径来执行完整个程序,因此这时候的复杂度就是 2;spa

两个嵌套的 IF 语句,或者包含两个判断条件的一个 IF 语句,复杂度就是 2 * 2 = 4。debug

更加具体的状况看下图:


圈复杂度的计算方法


  1. 圈复杂度能够经过程序控制流图计算,公式为:V(G) = e + 2 - n

  e : 控制流图中边的数量

  n : 控制流图中节点的数量

  1. 圈复杂度对应程序控制流图中从起点到全部终点的路径的条数,因此也能够经过数路径的方式得到圈复杂度。


03 下降复杂度


那么问题来了,咱们如何下降代码复杂度呢?若是你想写出易读且可测试的代码,可使用可以有效下降代码复杂度的利器——函数式编程。

咱们已经了解了圈复杂度指的是一段程序执行分支的可能性数量。而函数式编程就是尽可能避免使用全部循环语句这种会增长代码执行分支的语句。函数式编程是一种指导咱们如何编写程序的方法论,主要思想是把运算过程尽可能写成一系列嵌套的函数调用。

一种比较极端的观点任务数学是物理世界的根基,一切问题都是数学问题,世间万物均可以用数学函数去表示。电脑的运算也能够视为数学上的函数计算,因此咱们的代码其实也均可以概括化简成为一系列数学表达式。

函数式编程有要求只用"表达式",不用面向过程的"语句"。表达式和语句的区别是表达式总有一个返回值,而语句表示执行了某种操做。只使用表达式的函数咱们能够成为“纯函数”,纯函数的好处是不论函数被执行多少次,都不会产出任何的反作用,由于它不会去修改中间状态。

因为咱们使用函数式编程,咱们就能够用表达式去代替各类条件判断语句,从而下降代码的圈复杂度,使咱们的代码可读易测试。在函数式编程语言里没有 for 循环,由于这些逻辑意味着有状态的改变。相替代的是,这种循环逻辑在函数式编程语言里是经过递归、把函数当成参数传递的方式,也就是高阶函数实现的。

JavaScript虽然在设计的时候不是函数式语言,可是咱们能够经过 lodash,underscore等方法库来让咱们的程序更加函数式。函数式编程是我最为推崇的有效下降代码复杂度的编程方法。可是具体关于函数式编程的内容不属于本篇的范畴,在这里再也不展开阐述。

除了函数式编程,咱们还能使用一些更为传统的方式来下降代码复杂度。常见的方法有:

  • 提取函数 - 将独立业务或模块代码独立出来,封装提炼为函数,并经过函数名诠释代码做用,提升代码可读性。当一个函数过于复杂时就应该拆分为多个负责独立功能的子函数。

  • 替换算法 - 复杂算法会致使bug可能性的增长及可理解性/可维护性。

  • 合并条件式 - 把复杂的条件表达式,使用函数进行封装。举个例子:

if(data.code === 200 && data.id && data.list.length > 2) {
    db.insert(data);
} 复制代码

咱们能够将条件表达式封装为函数:

if(isValidate(data)) {
    db.insert(data);
}复制代码


经过以上这些方法咱们可使本身的代码保持一个较低的代码复杂度。在咱们写代码的时候咱们记住要让本身的代码 Stay Simple Stay Foolish 。一个有助于你记住这个原则的办法是“写程序时时刻记着,这个未来要维护你写的程序的人是一个有严重暴力倾向,而且知道你住在哪里的精神变态者”。




关注微信公众号查看更多原创内容

相关文章
相关标签/搜索