1       God Class

1.1     特征

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

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

  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)。

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的标准:

4.2      修改

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

5 Blob Module

5.1 特征

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

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

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属性)。

7.2 修改

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

8 Data Clumps

8.1 特征

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

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

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

8.2 修改

将这些参数抽取为对象。

9 Data Module

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

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

10. Distorted Hierarchy

10.1 特征

扭曲的层次

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

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

10.2 修改

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

11 God Module

11.1 特征

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

11.2 修改

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

12 Intensive Coupling

12.1 特征

过紧的耦合

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

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

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

12.2 修改

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

13 Refused Parent Bequest

13.1 特征

被拒绝的遗赠

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

13.2 修改

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

14 SAP Breaker

14.1 特征

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

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

SAP原则有两种基本情况:

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

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

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

14.2 修改

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

15 Schizophrenic Class

15.1 特征

精神分裂的类

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

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

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

15.2 修改

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

16 Schizophrenic Module

16.1 特征

精神分裂的模块

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

16.2 修改

将职责提取到不同的module

17 Shotgun Surgery

17.1 特征

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

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

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

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

下面给出infusion的检测规则:

17.2 修改

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

18 Significant External Duplication

18.1 特征

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

18.2 修改

抽取公共代码

19 Significant Internal Duplication

19.1 特征

显著的内部重复

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

19.2 修改

提取公共代码

20 Significant Sibling Duplication

20.1 特征

显著的家族重复

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

20.2 修改

提取公共代码到父类。

21 Tradition Breaker

21.1 特征

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

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

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

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错误类型分析的更多相关文章

  1. java程序错误类型及异常处理

    一.程序的错误类型 在程序设计中,无论规模是大是小,错误总是难免的.程序的设计很少有能够一次完成,没有错误的(不是指HelloWorld这样的程序,而是要实现一定的功能,具备一定实用价值的程序),在编 ...

  2. ElasticSearch 线程池类型分析之 ResizableBlockingQueue

    ElasticSearch 线程池类型分析之 ResizableBlockingQueue 在上一篇文章 ElasticSearch 线程池类型分析之 ExecutorScalingQueue的末尾, ...

  3. 【ABAP系列】SAP 系统的消息类型分析 MESSAGE TYPE

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP 系统的消息类型分析 ME ...

  4. 【Python系统学习03】错误类型整理(一)

    错误类型与可能原因分析 A.语法错误: 1.syntaxError:invalid syntax 无效的语法 print(2019小石头) # print(2019小石头) # ^ # SyntaxE ...

  5. 004_C++常见错误类型总结(一)之最后几行错误

    1.介绍 经常进行代码测试和静态代码分析的同学,应该会遇到这样的一个问题,就是一个程序段的最后几行,或者一个源文件末尾会出现错误.本文,结合专业的静态代码分析软件PSV-Studio提供错误类型代码库 ...

  6. 【repost】JS错误类型的学习

    SyntaxError是解析代码时发生的语法错误 // 变量名错误  var 1a;  // 缺少括号  console.log 'hello'); (2)ReferenceError Referen ...

  7. 【repost】js 常见错误类型

    1)SyntaxError SyntaxError是解析代码时发生的语法错误 // 变量名错误  var 1a;  // 缺少括号  console.log 'hello'); (2)Referenc ...

  8. Python语言常见异常错误类型

    在运行或编写一个程序时常会遇到错误异常,这时python会给你一个错误提示类名,告诉出现了什么样的问题(Python是面向对象语言,所以程序抛出的异常也是类).能很好的理解这些错误提示类名所代表的意思 ...

  9. [WCF编程]11.错误:错误类型

    一.错误概述 不管是哪一种操作,在任意时刻都可能出现不可预期的错误.问题在于我们应该如何将错误报告给客户端.异常和异常处理机制是与特定技术紧密结合的,不能跨越边界的.此外,如果有客户端来处理错误,必定 ...

随机推荐

  1. EOF ---shell编程

    转自:http://blog.163.com/njut_wangjian/blog/static/1657964252013112152418345/ 在shell编程中,”EOF“通常与”<& ...

  2. MongoDB 用户角色

    Read:允许用户读取指定数据库 readWrite:允许用户读写指定数据库 dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建.删除,查看统计或访问system.profile user ...

  3. mqtt 服务器与客户端通讯

    mqtt 服务器与客户端通讯. 服务器端 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ...

  4. 我们复习.Net的这些日子里

    今天是我们复习前面学习的第三天,也是在今天我们结束了复习.之前上学时间感觉知识全是生僻的,在生活中很少用到,因此喜欢重复的记忆,而现在学习的知识全是现在乃至未来,将是每天我们使用的,所以就感觉没必要重 ...

  5. php第一例

    参考 例子 https://www.cnblogs.com/chinajins/p/5622342.html 配置多个网站 https://blog.csdn.net/win7system/artic ...

  6. 【PHP】算法进阶,获取给定值的最优组合:虚拟币抵扣问题解决方案

    商城里边.虚拟币抵扣问题解决方案 虚拟币抵扣规则,按照以下规则执行: 1.如果一个订单包含多款商品,且均支持虚拟币抵扣时:   优先按照最大化使用虚拟币进行全额抵扣原则进行抵扣,若抵扣后用户虚拟币账号 ...

  7. 关于线上js报错问题的思考

    1.有没有可能对线上报错进行实时监控,只要线上报错出现就会以邮件的形式发出来. 2.有没有可能将每个模块和开发者联系起来,只要报错就直接报给开发者

  8. axios请求本地json

    在vux的项目中 1,首先,json文件的位置: 原因: 访问服务器文件,应该把 json文件放在最外层的static文件夹,这个文件夹是vue-cli内置服务器向外暴露的静态文件夹   2,一定要用 ...

  9. bzoj 3307 雨天的尾巴

    题目链接:传送门 题目大意:中文题,略 题目思路:网上有题解说是合并线段树的,但是太难蒟蒻不会,只能用树剖求解 如果不是树而是一维数组我们会怎么解? 当然是利用前缀和思想标记 (L) v+1,(R+1 ...

  10. 2015.10.11(js判断鼠标进入容器的方向)

    判断鼠标进入容器的方向 1.前几天在万圣节专题项目中用到了鼠标坐标page事件,随着鼠标背景图片移动形成有层次感的效果,但page事件在IE低版本不支持,所以还要做兼容.在研究page事件同时无意中想 ...