#圈复杂度
来源:互联网 发布:权力的游戏第八季 知乎 编辑:程序博客网 时间:2024/04/28 14:52
##概念
循环复杂度(Cyclomatic complexity)也称为条件复杂度,是一种软件度量,是由老托马斯·J·麦凯布(英语:Thomas J. McCabe, Sr.) 在1976年提出,用来表示程序的复杂度,其符号为VG或是M。“循环复杂度”的名称有时会让人误解,因为此复杂度不只计算程序中的循环 (循环)个数,也包括条件及分支个数。
##算法
圈复杂度(Cyclomatic Complexity)是一种代码复杂度的衡量标准。它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行 路径条数,也可理解为覆盖所有的可能情况最少使用的测试用例数。圈复杂度大说明程序代码的判断逻辑复杂,可能质量低且难于测试和 维护。程序的可能错误和高的圈复杂度有着很大关系。
它的计算方法很简单,计算公式为:V(G)=e-n+2。其中,e表示控制流图中边的数量,n表示控制流图中节点的数量。其实,圈复杂度的计 算还有更直观的方法,因为圈复杂度所反映的是“判定条件”的数量,所以圈复杂度实际上就是等于判定节点的数量再加上1,也即控制流 图的区域数,对应的计算公式为:V(G)=区域数=判定节点数+1。
对于多分支的CASE结构或IF-ELSEIF-ELSE结构,统计判定节点的个数时需要特别注意一点,要求必须统计全部实际的判定节点数,也即每 个ELSEIF语句,以及每个CASE语句,都应该算为一个判定节点。判定节点在模块的控制流图中很容易被识别出来,所以,针对程序的控制 流图计算圈复杂度V(G)时,最好还是采用第一个公式,也即V(G)=e-n+2;而针对模块的控制流图时,可以直接统计判定节点数,这样更为 简单。
##意义
- 在缺陷成为缺陷之前 捕获它们。
- 研究显示,平均每人在其大脑中大约能够处理 7(±2)位数字。这就是为什么大多数人可以很容易地记住电话号码,但却很难记住大 于 7 位数字的信用卡号码、发射次序和其他数字序列的原因。
- 过去几年的各种研究已经确定:圈复杂度(或 CC)大于 10 的方法存在很大的出错风险。
- 许多研究发现循环复杂度和缺陷个数有高度的正相关:循环复杂度最高的模组及方法,其中的缺陷个数也最多。
- 圈复杂度是代码复杂度的一个好的指示器;此外,它还是用于开发人员测试的一个极好的衡量器。一个好的经验法则是创建数量与将被 测试代码的圈复杂度值相等的测试用例。
- 在持续集成环境中,可以随时间变化评估方法的复杂度和成长度。如果某一方法的 CC 值在不断增长,那么您有两个响应选择:
- 确保相关测试的健康情况仍然表现为减少风险。
- 评估重构方法减少任何长期维护问题的可能性。
- 因为圈复杂度是如此好的一个代码复杂度指示器,所以测试驱动的开发 (test-driven development) 和低 CC 值之间存在着紧密相关 的联系。在编写测试时,开发人员通常倾向于编写不太复杂的代码,因为复杂的代码难以测试。如果您发现自己难以编写某一代码,那么 这是一种警示,表示正在测试的代码可能很复杂。在这些情况下,TDD 的简短的 “代码、测试、代码、测试” 循环将导致重构,而这将 继续驱使非复杂代码的开发。
- 在使用遗留代码库的情况下,测量圈复杂度特别有价值。
- 有助于分布式开发团队监视 CC 值,甚至对具有各种技术级别的大型团队也是如此。确定代码库中类方法的 CC 并连续监视这些值将使 您的团队在复杂问题出现时抢先处理它们。
##示例
- 圈复杂度为 2
public String case1(int num) { String string = null; if (num == 1) { string = "String"; } return string.substring(0);}
- 圈复杂度为 6
public String case2(int index, String string) { String returnString = null; if (index < 0) { throw new IndexOutOfBoundsException("exception <0 "); } if (index == 1) { if (string.length() < 2) { return string; } returnString = "returnString1"; } else if (index == 2) { if (string.length() < 5) { return string; } returnString = "returnString2"; } else { throw new IndexOutOfBoundsException("exception >2 "); } return returnString;}
##PHPMD
PHP Mess Detector是一种代码质量检查工具,支持5大类31小类的质量检查:
- Code Size Rules
- CyclomaticComplexity: Complexity is determined by the number of decision points in a method plus one for the method entry. The decision points are 'if', 'while', 'for', and 'case labels'. Generally, 1-4 is low complexity, 5-7 indicates moderate complexity, 8-10 is high complexity, and 11+ is very high complexity.
- NPathComplexity
- ExcessiveMethodLength
- ExcessiveClassLength
- ExcessiveParameterList
- ExcessivePublicCount
- TooManyFields
- TooManyMethods
- ExcessiveClassComplexity
- Controversial Rules
- Superglobals
- CamelCaseClassName
- CamelCasePropertyName
- CamelCaseMethodName
- CamelCaseParameterName
- CamelCaseVariableName
- Design Rules
- ExitExpression
- EvalExpression
- GotoStatement
- NumberOfChildren
- DepthOfInheritance
- CouplingBetweenObjects
- Naming Rules
- ShortVariable
- LongVariable
- ShortMethodName
- ConstructorWithNameAsEnclosingClass
- ConstantNamingConventions
- BooleanGetMethodName
- Unused Code Rules
- UnusedPrivateField
- UnusedLocalVariable
- UnusedPrivateMethod
- UnusedFormalParameter
##用重构降低圈复杂度
从Refactoring网站看到的93种重构方式,也可学习《重构:改善既有代码的设计》:
- Add Parameter
- Change Bidirectional Association to Unidirectional
- Change Reference to Value
- Change Unidirectional Association to Bidirectional
- Change Value to Reference
- Collapse Hierarchy
- Consolidate Conditional Expression
- Consolidate Duplicate Conditional Fragments
- Convert Dynamic to Static Construction by Gerard M. Davison
- Convert Static to Dynamic Construction by Gerard M. Davison
- Decompose Conditional
- Duplicate Observed Data
- Eliminate Inter-Entity Bean Communication (Link Only)
- Encapsulate Collection
- Encapsulate Downcast
- Encapsulate Field
- Extract Class
- Extract Interface
- Extract Method
- Extract Package by Gerard M. Davison
- Extract Subclass
- Extract Superclass
- Form Template Method
- Hide Delegate
- Hide Method
- Hide presentation tier-specific details from the business tier (Link Only)
- Inline Class
- Inline Method
- Inline Temp
- Introduce A Controller (Link Only)
- Introduce Assertion
- Introduce Business Delegate (Link Only)
- Introduce Explaining Variable
- Introduce Foreign Method
- Introduce Local Extension
- Introduce Null Object
- Introduce Parameter Object
- Introduce Synchronizer Token (Link Only)
- Localize Disparate Logic (Link Only)
- Merge Session Beans (Link Only)
- Move Business Logic to Session (Link Only)
- Move Class by Gerard M. Davison
- Move Field
- Move Method
- Parameterize Method
- Preserve Whole Object
- Pull Up Constructor Body
- Pull Up Field
- Pull Up Method
- Push Down Field
- Push Down Method
- Reduce Scope of Variable by Mats Henricson
- Refactor Architecture by Tiers (Link Only)
- Remove Assignments to Parameters
- Remove Control Flag
- Remove Double Negative by Ashley Frieze and Martin Fowler
- Remove Middle Man
- Remove Parameter
- Remove Setting Method
- Rename Method
- Replace Array with Object
- Replace Assignment with Initialization by Mats Henricson
- Replace Conditional with Polymorphism
- Replace Conditional with Visitor by Ivan Mitrovic
- Replace Constructor with Factory Method
- Replace Data Value with Object
- Replace Delegation with Inheritance
- Replace Error Code with Exception
- Replace Exception with Test
- Replace Inheritance with Delegation
- Replace Iteration with Recursion by Dave Whipp
- Replace Magic Number with Symbolic Constant
- Replace Method with Method Object
- Replace Nested Conditional with Guard Clauses
- Replace Parameter with Explicit Methods
- Replace Parameter with Method
- Replace Record with Data Class
- Replace Recursion with Iteration by Ivan Mitrovic
- Replace Static Variable with Parameter by Marian Vittek
- Replace Subclass with Fields
- Replace Temp with Query
- Replace Type Code with Class
- Replace Type Code with State/Strategy
- Replace Type Code with Subclasses
- Reverse Conditional by Bill Murphy and Martin Fowler
- Self Encapsulate Field
- Separate Data Access Code (Link Only)
- Separate Query from Modifier
- Split Loop by Martin Fowler
- Split Temporary Variable
- Substitute Algorithm
- Use a Connection Pool (Link Only)
- Wrap entities with session (Link Only)
##参考资料
- 追求代码质量: 监视圈复杂度
- 循环复杂度
- 圈复杂度
- 代码质量-圈复杂度及其计算
- Refactoring
- 圈复杂度
- 圈复杂度
- 圈复杂度
- 圈复杂度
- 圈复杂度
- 圈复杂度
- 圈复杂度
- 圈复杂度
- #圈复杂度
- 程序复杂度之圈复杂度
- 圈复杂度计算
- 圈复杂度计算
- 圈复杂度计算
- 圈复杂度的计算
- 圈复杂度详解
- 函数圈复杂度介绍
- 控制流图|圈复杂度|基本复杂度
- 什么是圈复杂度(Cyclomatic Complexity)
- 计算属性和观察者
- PIVOT和UNPIVOT使用详解
- B树
- Centos 7 ip 设置
- IPv6终于要取代IPv4了!阿里云将全面提供IPv6服务
- #圈复杂度
- 面试题整理--Java设计模式--行为型模式
- Class 与 Style 绑定
- sdnu-并查集-weeklyexam —— A
- Hive编程(八)【HiveQL:索引】
- 【Python】python版本之前互相切换
- Bringing up interface eth2: Error: No suitable device found: no device found for connection 'System
- 条件渲染
- RabbitMQ 之一"Hello World"