要确定条件复杂度代码味道,需要确定方法的 圈复杂度。圈复杂度是一种度量方法,由 Thomas McCabe 于 1975 年定义。
圈复杂度数(Cyclomatic Complexity Number,CCN)度量一个方法中某一路径的数量。无论一个方法中有多少条路径,它
的起始 CNN 都从 1 开始。每一个条件构造,如 if、switch、while和 for语句,都被分配一个 1 值和异常路径。一个方法的总的
CCN 表明了它的复杂度。很多人认为当 CCN 为 10 或超过 10 时,就表明该方法过于复杂。
工具
CheckStyle、JavaNCSS、以及 PMD 都是度量圈复杂度的开源工具。清单 2 展示了用 XML 定义的 CheckStyle 规则文件的一
个代码片断。CyclomaticComplexity模块定义了一个方法的 CCN 的最大限度。
清单 2. 配置 CheckStyle,查找圈复杂度为 10 或大于 10 的方法
<module
name="CyclomaticComplexity">
<property
name="max"
value="10"/>
</module>
用清单 2 的 CheckStyle 规则文件、清单 3 的 Gant 例子来示范如何将 CheckStyle 作为一个自动构建的一部分来运行。(参见
什么是 Gant ?侧边栏):
清单 3. 使用 Gant 脚本来执行 CheckStyle 检查
target(findHighCcn:"Finds
method with a high cyclomatic complexity number"){
Ant.mkdir(dir:"target/reports")
Ant.taskdef(name:"checkstyle",
classname:"com.puppycrawl.tools.checkstyle.CheckStyleTask",
classpathref:"build.classpath")
Ant.checkstyle(shortFilenames:"true",
config:"config/checkstyle/cs_checks.xml",
failOnViolation:"false",
failureProperty:"checks.failed", classpathref:"libdir") {
formatter(type:"xml",
tofile:"target/reports/checkstyle_report.xml")
formatter(type:"html",
tofile:"target/reports/checkstyle_report.html")
fileset(dir:"src"){
include(name:"**/*.java")
}
}
}
什么是 Gant ?
Gant 是一个自动构建工具,它提供了一个支持构建依赖关系的表达能力强的编程语言。开发人员利用 Groovy 编程语言的强
大功能编写 Gant 脚本。由于 Gant 提供对 Ant 的 API 的完全访问,所以任何可以运行于 Ant 的东西都可以从 Gant 脚本运
行。(参见 “用 Gant 构建软件” 教程,了解 Gant。)
清单 3 中的 Gant 脚本创建了图 1 中展示的 CheckStyle 报告。该图下面的部分指示出了一个方法的 CheckStyle 圈复杂度违
规。