InFusion错误类型分析

1       God Class

1.1     特征

上帝类通常过多的操纵其他类的数据,从而破坏了类的封装性。上帝类从其他类中获得功能,同时增加了自身的耦合性,通常会导致自己具有规模过大和较高的复杂度。

判断一个上帝类的标准有:

 InFusion错误类型分析

  1. CPFD (Capsules Providing Foreign Data) 从多个不相关类(模块)中引用数据
  2. WOC (Weighted Operation Count) 类的所有函数的圈复杂度之和超过65
  3. TCC (Tight Capsule Cohesion) TCC < 1/3 类需要具有低内聚的特性(类中直接相关的方法与全部方法之比小于1/3),也就是较少的private方法
  4. 需要同时满足以上条件才可以被认定为上帝类

1.2     修改

破坏CPFD, WOC, TCC 中的一个。

2       Message Chains

2.1     特征

过度耦合的消息链

如果你看到用户向一个对象索求(request)另一个对象,然后再向后者索求另一个对象,然后再索求另一个对象……这就是Message Chains。实际代码中你看到的可 能是一长串getThis()或一长串临时变量。采取这种方式,意味客户将与查找过程中的航行结构(structure of the navigation)紧密耦合。一旦对象间的关系发生任何变化,客户端就不得不做出相应修改。

Infusion通常会寻找具有较多调用其他类数据访问接口的方法,而且会检查返回值是否匹配。

2.2     修改

采用“隐藏委托关系”修改。

先观察Message Chains最终得到的对象是用来干什么的,看看能否以 Extract Method 把使用该对象的代码提炼到一个独立函数中,再运用Move Method 把这个函数推入Message Chains。

3 FeatureEnvy

3.1 特征

函数对某个class的兴趣高过对自己所处之host class的兴趣。最通常的焦点便是数据,通常为某个函数为了计算某值,从另一个对象那儿调用几乎太多取值函数(getting method)。

 InFusion错误类型分析

ATFD(Access To Foreign Data) 方法从外部获取了数据

LDA(Locality of Data Accesses) 内部变量与所有可以获取数据方法之比<1/3,也就意味着该方法过多的使用了外部数据,而非自身数据。

FDP(Access To Foreign Data) 数据来源于很少几个类

3.2 修改

如果一个类A使用了类B的过多数据来完成某项操作或计算,那改操作就应该放在B类中。

针对ATFD,通常较难进行修改,除非该类不访问其他类。

针对LDA,可以采用增加类本身的成员变量来进行修改,提高LDA比值。

针对FDP,可以考虑将类B拆分为多个类,从而增加FDP个数。

4     Blob Class

4.1      特征

可以译为复杂类,它具有体积大,高度复杂的特征,因而难以维护。除此之外,如此大的类(通常超过千行)大大增加了与外部类耦合的可能性,并降低了自身的内聚性。

附加Infusion判断blob class的标准:

 InFusion错误类型分析

 InFusion错误类型分析

 InFusion错误类型分析

 InFusion错误类型分析

4.2      修改

修改时可以根据4.1给出的标准破坏其判断条件。

5 Blob Module

5.1 特征

类似于blob class,指模块高度复杂且体积过大。它的检测标准非常类似于blob class,只有稍微的不同:

在面向过程语言中,函数中的长参数列表是正常的。

 InFusion错误类型分析

 InFusion错误类型分析

InFusion错误类型分析

5.2 修改

一般情况下通过拆分模块或类降低规模和复杂度。

6 Cyclic Dependencies

6.1 特征

循环依赖,也即在依赖结构中存在有“环”。这种设计缺陷出现在系统及子系统级别,如果两个或更多的子系统相互依赖,维护和重用几乎是不可能的。

Infusion的检测规则使用与面向对象和面向过程代码。检测工具会绘制依赖图,并根据此图判断是否存在循环依赖。

6.2 修改

7 Data Class

7.1 特征

数据类是单纯的数据持有者,它通常不包含复杂的功能,但是会被其他类频繁和密切的引用。缺乏功能意味着这个类的数据和操作是分离的,不符合面向对象的特征。Data class缺乏封装性,由于允许其他类较为自由的存取其内部数据,导致data class较为脆弱和难以维护。

Infusion在检测时会判断data class的特征:轻量级类,包含大量的get和set方法(或public属性)。

 InFusion错误类型分析

 InFusion错误类型分析

7.2 修改

将它处的方法移到data class中,提高其封装性;或编写高复杂度函数。

8 Data Clumps

8.1 特征

数据泥团,是《重构》提到的代码坏气味的一种。

“喜欢成群结队地待在一块儿。你常常可以在很多地方看到相同的三或四笔数据项:两个classes内的相同值域(field)、许多函数签名式(signature)中的相同参数。”

也就是一组数据重复出现,如一组数据从一个方法传递到另外一个方法,这些数据完全可以抽取为一个对象来进行处理。

 InFusion错误类型分析

8.2 修改

将这些参数抽取为对象。

9 Data Module

类似于data class,可以翻译为数据模块。为面向过程的设计缺陷。一个模块暴漏了太多数据,但自身却没有完成什么功能,也即太过开放。

检测规则非常容易:提供了过多数据为外部访问;复杂度过低

 InFusion错误类型分析

10. Distorted Hierarchy

10.1 特征

扭曲的层次

通常指继承层次过窄和过深。研究表明人的记忆难以记住超过6的层次,因此此类缺陷常常导致代码难以维护。

除此之外,它还可能预示着代码存在封装性的问题,或是划分的粒度太细。

 InFusion错误类型分析

10.2 修改

修改不合理的继承层次,渐少深度和增加广度(多个类继承自某父类,则该父类具有较高的广度)。

11 God Module

11.1 特征

类似于God Class,该module的规模和复杂度高,低内聚以及访问过多的外部数据。

 InFusion错误类型分析

11.2 修改

破坏检测条件,如拆包,降低复杂度和外部依赖。

12 Intensive Coupling

12.1 特征

过紧的耦合

一个经常被提到的紧耦合的例子是:某个方法与系统中的多个方法相关,而这些方法位于某个或很少几个类之间。这表明该方法与其他方法提供类之间的通信太过冗长了。

这种设计缺陷通常意味着一个微妙的问题:provider类没有抽象层逻辑提供合理的服务,导致耦合方法必须要频繁通信。

在infusion的检测方面:耦合方法调用了许多外部方法;外部方法位于一个类或少数几个类。

 InFusion错误类型分析

12.2 修改

将耦合方法中依赖的外部方法提取和抽象,将逻辑封装到provider类中。

13 Refused Parent Bequest

13.1 特征

被拒绝的遗赠

继承关系是比类协作关系更为特殊和紧密的关系,它基于子类从父类继承成员的基础上(变量和方法),但如果子类拒绝使用父类中提供的方法或变量,这表明继承关系存在问题。

 InFusion错误类型分析

 InFusion错误类型分析

 InFusion错误类型分析

13.2 修改

修改类的继承关系,将不使用的属性和方法拆分的另外的类。

14 SAP Breaker

14.1 特征

SAP Stable Abstractions Principle 稳定抽象原则,也即包的抽象程度与其稳定程度一致

这种缺陷表明包,或者类破坏了SAP原则。

SAP原则有两种基本情况:

如果一个子系统提供了较多的抽象,则它更应位于层次设计的底层,由其他的子系统来引用,这也表明它具有较高的稳定性,也即高抽象性高稳定性。

另外,如果一个子系统的抽象较少,就是是他更多的处于调用者的角色,依赖下层子系统,则它位于层次设计的上层,且具有较低的稳定性,也即低抽象性低稳定性。

SAP Breaker破坏了这种抽象原则。

 InFusion错误类型分析

14.2 修改

修改层次设计,从抽象程度和稳定性上修改。一般在成型系统中,抽取接口较为简单。

15 Schizophrenic Class

15.1 特征

精神分裂的类

一个类本应承担一种抽象,完成一类责任,但该类确完成两种或以上的抽象,会影响对类的理解和修改。

Infusion通过如下规则检测该缺陷:

低内聚,定义大量接口,以及被不同的client使用。

 InFusion错误类型分析

15.2 修改

将不同的职责分割到其他类中去。

16 Schizophrenic Module

16.1 特征

精神分裂的模块

检测规则类似于“精神分裂的类”。

 InFusion错误类型分析

16.2 修改

将职责提取到不同的module

17 Shotgun Surgery

17.1 特征

霰弹式修改,直观的讲,就是修改该方法会引出其他大量的修改。而且这种修改是分布的,并不集中于某一类或某个包。

存在这种缺陷的方法常常被称为“瓶颈方法”,该方法通常具有很高的复杂度,引用大量的外部方法并被众多方法调用,极有可能引入bug。

在《重构》包含有对“霰弹式修改”的定义:

Shotgun Surgery类似Divergent Change,但恰恰相反。如果每遇到某种变化,你都必须在许多不同的classes内做出许多小修改以响应之,你所面临的坏味道就是Shotgun Surgery。如果需要修改的代码散布四处,你不但很难找到它们,也很容易忘记某个重要的修改。

下面给出infusion的检测规则:

 InFusion错误类型分析

InFusion错误类型分析

17.2 修改

“这种情况下你应该使用Move Method 和 Move Field 把所有需要修改的代码放进同一个class。如果眼下没有合适的可以安置这些代码,就创造一 个。通常你可以运用Inline Class 把一系列相关行为放进同一个class。这可能会造成少量Divergent Change,但你可以轻易处理它。” -《重构》

18 Significant External Duplication

18.1 特征

显著的外部重复,也即在系统包层面上的重复。代码重复破坏了系统的唯一性,将导致代码规模增大以及提高问题定位的难度。

 InFusion错误类型分析

18.2 修改

抽取公共代码

19 Significant Internal Duplication

19.1 特征

显著的内部重复

在类或模块间的代码重复,提高维护难度。

 InFusion错误类型分析

19.2 修改

提取公共代码

20 Significant Sibling Duplication

20.1 特征

显著的家族重复

即存在于继承层次上的重复,一般指继承层次中的同一层次。

 InFusion错误类型分析

20.2 修改

提取公共代码到父类。

21 Tradition Breaker

21.1 特征

传统破坏者,即子类拒绝父类提供的方法和属性,也即破坏了“继承”这一传统。在JAVA中,可以通过在子类中重写方法来完成。

这种缺陷意味着子类的定义或者继承关系存在不合理。

检测方式有两个标准:子类重写了父类方法或使用了非公用继承。

 InFusion错误类型分析

21.2 修改

重新检视和修改继承关系。

22 Unnecessary Coupling

22.1 特征

不必要的耦合

通常指在C++中引用了不必要的头文件,从而增加的耦合性。

22.2 修改

去掉不使用的头文件。

23 Unstable Dependencies

23.1 特征

不稳定的依赖

值子系统需要依赖比其更为稳定的子系统,至少是同样稳定,违反改原则则为不稳定的依赖。

Infusion通过比较不同的子系统中的IF来确定是否为稳定依赖。

IF Instability Factor The ratio of efferent coupling (Ce) to total coupling. IF = Ce / (Ce + Ca).

23.2 修改

修改依赖层次

参考文档

《Infusion帮助文档》 -  inFusion Hydrogen, Version 1.8.0

《重构 – 改善既有代码的设计》 - Martin Fowler,Kent Beck,John Brant ,William Opdyke ,Don Roberts

 
 
 
标签:  Infusion

你可能感兴趣的:(Infusion)