包括面向契约设计和面向接口程序的模式(将在下文中更详细地描述)。
[0058]基于架构的规则506可以包括具有比基于模式的规则508更高抽象的规则。例如,基于架构的规则506可以基于架构组件的结构和架构组件之间的关系。基于架构的规则506可以包括基于预定结构和关系指南的规则,以及基于组织专用或用户专用指南的规贝U。基于架构的规则506可被模板化,并可基于知识库中所包含的其他结构规则和基于关系规则。
[0059]示出了示例规则602至630的表600。表600包括作用域栏601,该作用域栏指示了每个示例规则602至603的可应用的作用域,例如类、接口、包或顺序图。例如,规则602至630以及例如由用户定义的自定义规则之类的其他规则可由规则引擎O使用。例如,如果过量的类(例如相比于阈值)基于特定的类,则可能违反过度扇入度量规则602。例如,如果对类使用了过度继承(例如相比于阈值),则可能违反过度继承规则604。例如,具有高级别继承的类可成为扩展性的瓶颈,并且对该类的改变可影响该类的子类。例如,如果具有非常大量的行为(例如相比于阈值),则可能违反“神圣的类(godly class)”规则606。具有大量行为的类(例如功能类)可考虑用于重构。
[0060]例如,如果类具有许多向内的依赖关系和高级别继承(例如,相比于阈值),则可能违反高耦合、高继承和高依赖关系出规则608。这种类可表示“脆弱”类,并且,如果这种类失效(例如在测试过程中失效),则从属类可能被影响。例如,如果类具有公有方法但是该类不被该类包外的其他类访问,则可能违反非API方法访问规则610。理想地,仅当由公有方法暴露的特定功能是由其他类访问(特别是来自该类的包外的类)时,类才具有公有方法。如果类具有不被其他包中类访问的公有方法,则类中所暴露的公有方法可最终导致功能的错误使用并破坏系统的API。
[0061]例如,如果在类定义的内部找到私有构造函数,则可能违反在类中找到的私有构造函数的规则612。私有构造函数可用于阻止类的实例化。然而,私有构造函数并非某些语言的默认值。因此,私有构造函数可被标记用于进一步的评价。例如,如果接口具有大量的行为(例如相比于阈值),则可能违反“神圣的接口(godly interface) ”的规则614。具有大量行为的接口可被考虑用于重构。由于接口的每个客户端都依赖于所暴露的类接口,所以在类的每个客户端之间具有无意的耦合。如果一个客户端需要向单类接口添加额外的功能,则当这种功能被添加至所述接口时,每个其他客户端可能需要改变以支持所添加的功能,尽管许多类可能不需要该功能。因此,一个客户端的一个改变可能迫使在整个系统内将改变传播到许多客户端类,这可导致耗时的代码维护并难于定位软件漏洞。
[0062]例如,如果包通过实体类而非通过接口被耦合至所述系统的剩余部分,则可能违反PIF(面向接口编程的因素)规则616。理想地,包仅通过接口耦合。使用实体类而非接口可导致低扩展性的包。例如,如果包包括多于阈值数量的类和/或接口,则可能违反“神圣的包”的规则618。具有较大数量的类和/或接口的包可以包括太多的功能,并因此可作为重构的候选。
[0063]例如,如果包的类与接口的比例过高或过低(例如相对于阈值),则可能违反面向契约设计的规则620。例如,仅具有类的包可以是绝对实体的并且不可被扩展。然而,仅具有接口的包可以是绝对抽象的,并且如果该包未被标记作为框架包,则它可视为被错误标记。例如,如果低级别模块依赖于高级别模块,则可能违反依赖关系反转规则622。理想地,高级别模块不依赖于低级别模块,并且高级别模块和低级别模块仅依赖于抽象。例如,如果包通过耦合链接至系统中的大量包(例如相对于阈值),则可能违反全向存在包的规则624。通常,全向存在包是包括系统的工具类或核心组件的包。如果存在太多全向存在包,则可以考虑重构所述系统。
[0064]例如,如果软件实体不对扩展开放并对修改封闭,则可能违反开放封闭的规则626。一般而言,开放封闭原理可应用于类、模块或函数。对扩展开放但对修改封闭可以阻止对系统不利的改变。如果顺序图包括大量的远程调用(例如相比于阈值),则可能违反过度远程规则628。大量的远程调用可以影响性能。例如,如果类具有多重构造函数,则可能违反工厂规则630。对于类而言,具有多重构造函数可使得在研发期间难于确定调用哪个构造函数。在具有非公有构造函数的类层级中具有所有的类,以及创建客户端可用于直接实例化类的工厂类可能是有用的,该被实例化的类驻留于一个包中并实现共用接口。
[0065]可能违反其他规则。例如,如果在类之间存在过度耦合,则可能违反过度耦合规贝U。如果包的抽象不与其稳定性成比例(例如,如果稳定包不是抽象的或是不稳定的包不是实体的),则可能违反缺乏稳定抽象规则。如果包依赖于另一较不稳定的包,则可能违反稳定的依赖关系规则。如果方法涉及其他类的数据多过涉及自身类的数据,则可能违反“特征依恋(feature-envy)”规则。如果方法包括多于阈值数量的代码行(长的方法可能难于理解、调试和重复使用),则可能违反“长方法(long-method)”规则。如果类具有多于阈值数量的公有访问器方法,则可能违反数据-类规则(触发进一步查询)。
[0066]示例度量702至744的表700。表700包括作用域栏701,该作用域栏指示每个示例度量702至744的可应用的作用域,例如类、接口、包或顺序图。例如,可与一个或多个基于度量的规则510()结合来使用度量702至744。
[0067]NOC (子类数量)度量702指示类的子类(例如UML概括)的数量。“0pslnh”(继承的操作)度量704指示类的继承操作的数量,而“Attrlnh”(继承的属性)指示类的继承属性的数量。“DIT”(继承树的深度)度量708指示继承层级中类的深度,并且可以表明从所述类到继承树的根的最长路径。
[0068]“NumDeSC”(后代的数量)度量710指示了类的后代数量(例如类的子类数量、类的子类的子类的数量,等等)。“NumAnc”(祖先的数量)度量712指示了类的祖先的数量。“D^)_In”(依赖关系指示符)度量714指示了基于类的元素的数量,并且可以包括传入UML依赖关系(例如UML图上的虚箭头)、方法调用或参数类型依赖关系。
[0069]“NumAssEl” (相关元素的数量)度量716指示了作为类的相同作用域(例如,命名空间、包)中的相关元素的数量。鼓励在相同作用域中的元素关联,因为它们不跨越作用域界限并有助于包或命名空间内的内聚。关联可包括合并、组合以及UML关联,并且可包括传入、传出和双向关联。
[0070]“NumOps”(操作的数量)度量718指示了类中操作的数量。例如,可包括被明确建模的所有操作,无论其可视性、所有者作用域以及抽象程度。然而,可能不包括继承操作。“取得器(getter)”度量720可指示具有以“取得”、“是”、“具有”开头的名称的类的操作数量。“设置器”度量722指示具有以“设置”开头的名称的类的操作数量。连接符度量724指示由类所拥有的连接符的数量。
[0071][O] “NumOps” (操作的数量)度量726类似于NumOps度量718,但是指示的是接口的继操作数量而非类的操作数量。“Assoc”(关联)度量728指示了接口关联的元素的数量。“NumAnc” (祖先的数量)度量730类似于NumAnc度量712,但是它指示的是接口的祖先数量而非类的祖先数量。“NumlndClients” (间接客户端的数量)度量732指示了实现接口后代的元素数量,而“NumDirClients”(直接客户端的数量)度量734指示了直接实现接口的元素数量。
[0072]“NumOpsCls”(类中操作的数量)度量736指示了包的类中操作的数量,而“NumClsRec”(递归的类的数量)度量738指示了包以及该包的子包中的类的数量。嵌套度量740指示了包层级中包的嵌套级别。NumCls (类的数量)度量742指示了包中类的数量,以及“Numlnterf” (接口的数量)度量744指示了包中接口的数量。