衡量结构
度量软件结构
Section titled “度量软件结构”度量软件制品(需求、设计文档、源代码)的结构属性,可以为质量属性(如复杂度、可维护性、可测试性)和潜在的工作量估算提供有价值的洞察。分析结构有助于在生命周期的早期识别潜在的问题区域。
结构度量的类型
Section titled “结构度量的类型”可以从不同角度分析软件结构:
- 控制流结构 (Control-Flow Structure):检查程序或模块内的执行路径序列。它有助于理解逻辑复杂度。
- 数据流结构 (Data-Flow Structure):跟踪数据在程序不同部分或模块之间移动时如何被定义、使用和修改。它有助于理解数据依赖性和耦合。
- 数据结构 (Data Structure):指数据元素本身(例如,数组、记录、对象、数据库模式)的组织和复杂性。
- 架构/模块结构 (Architecture/Module Structure):检查系统到组件、模块或服务的高层组织及其相互连接(耦合和内聚)。
度量控制流结构
Section titled “度量控制流结构”控制流通常使用控制流图 (Control Flow Graphs, CFG) 进行建模,其中节点表示代码语句或代码块,有向边表示可能的控制转移。
- 圈复杂度 (Cyclomatic Complexity, McCabe 度量):一个广泛使用的度量,根据 CFG 计算(边的数量 - 节点的数量 + 2)。它代表代码中线性独立路径的数量,提供了逻辑复杂度的定量度量。较高的值通常表示更复杂的代码,可能更难测试和维护。
- 节点和边计数 (Nodes and Edges Count):CFG 中基本块(节点)或控制转移(边)的简单计数。
- 嵌套深度 (Nesting Depth):度量嵌套控制结构(if, while, for 语句)的最大深度。深层嵌套可能使代码难以理解。
- 认知复杂度 (Cognitive Complexity):一个更近期的度量(由 SonarSource 开发),旨在度量人类理解控制流所需的工作量,惩罚打破线性流或需要心理堆栈的结构(例如,深层嵌套、某些逻辑运算符)。
工具:静态分析工具(例如,SonarQube、PMD、Checkstyle、集成到 IDE 中的 Linter)通常会自动计算这些度量。
度量数据流结构
Section titled “度量数据流结构”数据流分析侧重于变量的生命周期(定义、使用、销毁)以及系统不同部分之间的信息流。
- 耦合度量 (Coupling Metrics):度量模块之间的相互依赖程度。高耦合表明在一个模块中的更改很可能影响其他模块,降低可维护性。类型包括数据耦合 (data coupling)、标记耦合 (stamp coupling)、控制耦合 (control coupling)、公共耦合 (common coupling) 和内容耦合 (content coupling)(从最好到最差)。工具通常可以度量扇入 (fan-in)(调用给定模块的模块数量)和扇出 (fan-out)(给定模块调用的模块数量)作为指标。
- 信息流复杂度 (Information Flow Complexity)(例如,Henry 和 Kafura):经典的度量试图根据扇入、扇出以及传递的数据结构的复杂性来量化复杂度。虽然具有基础性,但如今更常使用更简单的耦合度量。
- 变量跨度 (Span of Variables):变量 successive references 之间的代码行数。较大的跨度可能使跟踪变量使用变得困难。
应用:理解数据流对于影响分析(评估变更的连锁效应)和识别由于复杂数据交互而容易出错的区域至关重要。
度量数据结构复杂度
Section titled “度量数据结构复杂度”这涉及评估软件操作的数据的复杂性。
- 属性/字段数量 (Number of Attributes/Fields):类、记录或数据库表中的数据元素的简单计数。
- 数据类型复杂度 (Complexity of Data Types):评估复杂嵌套结构、指针或复杂的对象关系的使用。
- 数据库模式复杂度 (Database Schema Complexity):与数据库模式中表数量、关系(外键 foreign keys)、索引和范式级别 (normalization levels) 相关的度量。
应用:复杂的数据结构会增加编写操作它们的算法的难度,并且更难进行彻底的测试。
度量架构/模块结构
Section titled “度量架构/模块结构”这些度量评估高层设计的质量。
- 内聚度量 (Cohesion Metrics):度量单个模块内元素属于同一整体的程度,侧重于单个任务。高内聚是理想的(例如,LCOM - Lack of Cohesion in Methods,方法内聚不足度)。
- 耦合度量 (Coupling Metrics)(在模块级别):如数据流部分所述,但应用于高层组件或模块之间的交互。
- 依赖分析 (Dependency Analysis):识别模块或包之间的依赖关系。工具可以可视化依赖图并检测循环依赖 (cyclic dependencies),这会阻碍可维护性和可测试性。
- 规模度量 (Size Metrics):系统中模块、类或服务的数量。
局限性与情境
Section titled “局限性与情境”虽然结构度量提供了有价值的定量数据,但重要的是要记住:
- 相关性,而非因果关系 (Correlation, Not Causation):高复杂度不 保证 可维护性低,但通常 strongly correlated。
- 情境是关键 (Context is Key):可接受的复杂度阈值因应用领域、团队专业知识和重要性而异。
- 不是全貌 (Not the Whole Picture):结构度量不直接捕获算法效率、可用性或功能正确性等方面。
- 工具依赖性 (Tool Dependence):不同的工具计算同一度量的方式可能略有不同。
- 潜在的误用 (Potential for Misuse):不要在不理解其含义和潜在副作用(古德哈特定律 Goodhart’s Law)的情况下为度量设置任意目标。
结构度量最有效的使用方式是作为指导调查、跟踪趋势和支持关于代码质量和设计改进讨论的指标,而不是作为绝对判断的标准。