演化架构与紧急设计: 通过指标进行紧急设计

简介: 软件指标可以帮助您寻找代码中隐藏的设计元素,让它们能够成为惯用模式。 演化架构与紧急设计 的这一期讲解如何使用指标和可视化发现被复杂性掩盖的重要代码元素。

紧急设计的难题之一是寻找隐藏在代码中的惯用模式和其他设计元素。指标和可视化有助于识别代码的重要部分,从而提取出一些设计元素。本文主要讨论两个指标,圈复杂度(cyclomatic complexity) 和传入耦合(afferent coupling)。圈复杂度度量方法的相对复杂度。传入耦合表示有多少个其他类使用当前类。本文要介绍显示和理解这两个指标的一些工具,以及如何通过组合指标帮助发现设计特征。

我在 “测试驱动设计,第 2 部分” 中讨论过圈复杂度,但是有一些细节没有讨论。通过 Java 工具度量圈复杂度的一个难点是工作单元。圈复杂度是方法级度量,但是 Java 编程中的工作单元是类。因此,圈复杂度指标通常表示为类中所有方法的总复杂度或平均复杂度。这两种形式都是有意义的。

例如,可能会出现以下情况。假设一个类包含一个非常复杂的方法 (CC = 40),但是还有许多非常小的方法(比如 Java 代码中常见的 get/set 方法对)。JavaNCSS等工具报告所有方法的总复杂度,因此整个类的圈复杂度很高。如果使用 Cobertura 等工具(它们报告类的平均圈复杂度),那么这个类看起来并不糟糕,因为大量简单方法掩盖了那个复杂方法的复杂度。由于工作单元不匹配,所以同时观察圈复杂度的总值和平均值是有意义的。如果单独考虑它们,可能会得出错误的结论。同时使用这两个指标有助于消除这种可能性。

软件指标与物理指标

在软件中,指标是指应用客观的度量开发工件,从而判断粗粒度的特征。与物理指标(比如量尺)不同,大多数软件指标并不反映真实环境中的一些特征。圈复杂度值(比如 5)没有度量单位;它并不说明代码的任何物理性质。这个数字只在与其他代码的圈复杂度进行比较时才有意义。

对于设计有意义的其他指标是两个耦合数:传出(efferent) 和传入 耦合。传出耦合度量当前类引用的类的数量。很容易通过简单的检查判断传出耦合:打开要检查的类,统计(字段和参数中)对其他类的引用。传入耦合比较难判断,但是更有价值。它度量使用当前类的其他类的数量。可以使用命令行 fu 判断它,也可以使用理解这个指标的其他工具。这种工具包括 ckjm,这是一个用于运行 Chidamber & Kemerer 面向对象指标集的开放源码工具。尽管 ckjm 的设置和运行有点儿复杂,但是能够提供圈复杂度(报告类中所有方法的圈复杂度总和)以及传出和传入耦合数。

但是,获得了这些数字之后,如何发挥它们的作用呢(尤其在设计方面)?指标数字只提供关于代码的一个信息维,数字本身往往意义不大。可以以两种方式通过指标获得有用的信息。一种方式是观察数值随时间的变化和趋势。还可以把指标组合起来,提供更丰富的信息,本文介绍这种方式。

指标和设计

我在本系列的几篇文章中以 Struts 代码库作为示例,这不是因为我偏爱 Struts,而是因为它是一个著名的开放源码项目。相信我:在世界上的大多数代码中都能够找到隐藏的设计特征!既然前面使用 Struts,本文继续使用它说明我的观点。

ckjm 的输出是文本,这些文本可以转换为 XML(也可以使用 XSLT 转换为其他格式)。图 1 显示几个 ckjm 指标的组合,其中的 WMC (Weight Methods per Class) 是类的方法的圈复杂度,Ca 是传入耦合。

图 1. 表格形式的 ckjm 指标结果

图 2 显示按 WMC 排序的同一个表:

图 2. 按 WMC 排序的 ckjm 指标

时间: 2024-09-09 16:21:14

演化架构与紧急设计: 通过指标进行紧急设计的相关文章

演化架构与紧急设计: 积累惯用模式

简介: 本期将之前的 演化架构与紧急设计 文章中的紧急设计概念与一个案例研究相结合,展示如何 发现.积累和利用代码中意料之外的设计元素.一旦理解了如何识别设计元素,便可以使用该知识改进代 码的设计.紧急设计使您可以发现代码中意料之外但是已成为代码库重要部分的那些方面. 在本系列第一期 "研究架构和设计" 中,我曾断言每个较大的项目都包括超出所有人意料的设计元 素.详细考虑一个问题时,常常会发现有些本以为困难的事情实际上却更容易,有些本以为容易的事情实 际上却更困难.随后的几期则演示了发

演化架构和紧急设计: 利用可重用代码,第2部分

简介:在使用 演化架构和紧急设计 前几期描述的技术发现 代码中的紧急设计之后,下一步您需要一 种获取和利用这些设计元素的方法.本文介绍了两种用于获取惯用模式的方法:将模式作为 APIs 进行捕 捉:使用元程序设计方法. 本 系列 的前几期主要关注紧急设计中显而易见的第一步:发现 惯用模式.发现惯用模式之后,您要 用它做什么?该问题的答案就是本期重点,本文属于由多个部分组成的系列文章的第二部分.第 1 部分 -代码与设计的关系探讨- 介绍了一种观点的理论基础,这种观点就是软件中的设计真正是指解决方

演化架构和紧急设计:利用可重用代码,第1部分

简介:识别出代码中的惯用模式后,下一步是积累和使用它们.理解设计与代码之间的关系有利于发 现可重用的代码.本期的 演化架构与紧急设计 探索代码与设计的关系,使用表达性强的语言的重要性, 以及重新考虑抽象风格的潜在价值. 通过本 系列 的前几期,您已经知道,我的观点是软件的每个部分都包括可重用的代码块.例如,公 司处理安全性的方式在整个应用程序甚至多个应用程序中可能都是一致的.这就是我所说的 惯用模式 的 实例.这些模式代表对构建软件特定部分时遇到的问题的常用解决方案.惯用模式有两种类型: 技术模

演化架构和紧急设计: 演化架构

简介: 这一期的 演化架构和紧急设计 将会解决演化架构相关的各种主题,包括设计和架构之间的重 要区别(以及如何区分两者),您在创建企业级架构时遇到的某些问题,以及面向服务的架构中静态类型 和动态类型的区别. 在 本系列的第一期 中,我推荐了软件世界中的一些架构定义.无论如何,如果您已经阅读过本系列 ,您会注意到我花费了大部分时间在设计上.我之所以这么做是基于以下几个原因:首先,在当前紧急设 计尚未被广泛关注时,软件世界里存在很多架构定义(良莠不齐):其次,在设计方面很多问题都有具体 的.不受环境

演化架构与紧急设计:研究架构和设计

演化架构(evolutionary architecture)和紧急设计(emergent design)都是将 重要的决策推迟到最后责任时刻(Last Responsible Moment)的敏捷技术.在本 系列的第一期文章中,系列作者 Neal Ford 将定义架构和设计,然后指明了一些 关于整个系列的基本概念. 软件架构和设计一直都没有一个明确的定义,因为软件开发作为一门学科,尚 未完全理解其中的复杂度和内涵.但是要发表关于这些主题的论述,您必须从某 个位置开始.本系列涉及演化架构和紧急设

演化架构与紧急设计:对设计进行重构

在 "测试驱动设计,第 1 部分" 和 "测试驱动设计,第 2 部分" 中,我 介绍了测试如何为新的项目实现更好的设计.在 "组合方法和 SLAP" 中,我讨 论了两种关键模式 - 组合方法(composed method)和单一抽象层原理 - 为您 的代码结构提供了整体目标.需要牢记这些模式.一旦拥有了一个现有软件项目 ,那么发现和利用设计元素的主要方法就是进行重构.在 Martin Fowler 的经典 著作 Refactoring 中,他将

回归架构本真:从规划、思维到设计,构建坚不可摧的架构根基

   关于什么是架构,业界从来没有一个统一的定义.Martin Fowler在<企业应用架构模式>中也没有对其给出定义,只是提到能够统一的内容有两点: 最高层次的系统分解: 系统中不易改变的决定.   <软件架构设计>一书则将架构定义总结为组成派和决策派: 组成派:架构=组件+交互:软件系统的架构将系统描述为计算组件及组件之间的交互. 决策派:架构=重要决策集:软件架构是在一些重要方面所作出的决策的集合.   而架构的概念最初来源于建筑,因此,我想从建筑的角度去思考这个问题.Wik

设计师的KPI指标应该如何设计

年度考评,季度考评,月度考评--现代企业,特别是现代的IT企业中已经普遍使用了这种战略目标分解操作并检验的管理手段,当然了,我们很多传统企业中或者家族企业中暂时没有导入这种工具.不过既然是先进思想,必然就有其优越性,考还是不考,这不是个问题 - 问题在于怎么考. KPI是量化指标为优先的,对于设计师来说很多东西一旦量化以后反而显得价值降低,比如:你半年时间做了一套概念设计方案,在创新程度上有突出的表现,但对于KPI来说,你的工作是在6个月时间内完成了一件工作,并且这个工作是你份内的,最多给你加一

信号处理-在信号重采样的时候,滤波器设计的指标怎么确定?

问题描述 在信号重采样的时候,滤波器设计的指标怎么确定? 尝试把44.1kHz的信号转换成96kHz的信号. 把L/M=320/147 分解成 (8/7)(4/3)(10/7)的形式,可以知道截至频率应该等于 π/max(L,M). 但是具体每个滤波器应该怎么设计呢? 还有我看了下matlab的resample函数的处理方法,不太明白这一段: % Need to delay output so that downsampling by q hits center tap of filter. n