软件设计的质量在很大程度上受到系统封装关系的影响。模块间松耦合而模块内部又保持高度一致性是高质量设计软件的要害之一。所以,评定软件设计的水平的手段之一就是考察它的模块间的关系。对系统的可重用性和可维护性水平的客观评价是一个评价软件结构的重要组成部分。我在本文介绍的度量标准可以帮助你客观评定你的软件设计的质量。
尽管度量标准可以对我们的软件设计质量起着指导和反馈的作用,但是你要牢记我在本文提出的度量标准并不是软件设计的唯一依据。设计质量分数的高低未必一定对应于真实软件设计质量的高低,但是不太可能出现那种设计水平很高,但是在我们这种度量标准下,分数却很低的情况。我们提出软件设计质量度量标准的目的在于帮助设计者正确评估他们自己的设计,更重要的是帮助你检测设计的水平是否达到预期目标。
测试稳定性
稳定性指的是修改软件中某个模块而不影响其它模块的困难程度。让我们看看模块间的依靠关系是如何影响到稳定性的。
一个模块在软件中重用的次数越多,那么就越依靠于它。模块的输入依靠性越强(较多的其它模块依靠本模块),则它的稳定性得分也就越高(即难以修改)。换句话来说,其它模块越依靠于本模块,那么修改本模块而不影响其它模块也就越困难。模块的输入依靠性和输出依靠性是评测模块稳定性和不稳定性的重要方面。模块的输出依靠性强、输入依靠性弱,则稳定性低(即轻易修改),这是因为对变化不会扩展到很多其它方面。另一方面,模块的输入量越多,它就越难以修改,则越稳定。稳定性可以通过计算输入量和输出量来计算。
输入耦合度代表依靠本模块的其它模块数,输出耦合度代表本模块所依靠的其它模块数。不稳定度可以通过输出耦合度与总的耦合度的比例来得到。计算公式如下:I = Ce/(Ce + Ca)
I 代表该模块的不稳定度
Ca代表该模块的输入耦合度,即输入依靠度
Ce代表本模块的输出耦合度,即输出依靠度
假如I的值接近于零,那么模块的输入依靠性就远远大于输出依靠性,模块也就越稳定。模块越稳定也就越难以修改,因为某个变化会衍生出许多新的变化,波及到依靠它的其它模块上了。对I值接近于一的模块来说,它的输出依靠性远远大于输入依靠性,模块很不稳定。由于受本模块影响的模块不多,所以不稳定的模块轻易修改。看到这些,你也许会感到很困惑,“到底我应该让模块的稳定性高一些好,还是低一些?”
由于组成一个软件的一整套模块中,有些模块有输入依靠性(被其它模块引用),而有些模块有输出依靠性(引用其它模块)。我们在设计模块不应该追求完全的稳定性或者不稳定性,而是具体考虑某个模块需要的是稳定性还是不稳定性并尽可能实现。输入依靠度比较强的模块必须拥有较高的抗可变性,展现较高程度上的稳定性。在面向对象的开发方法中,抽象性通过分离功能和功能的实现方法来提高稳定性。对Java来说,抽象类和界面(interface)显然就是抽象性的表现形式。因此,越需要稳定的模块应该有越高的抽象层次。与此对应,越不稳定的模块也就越具体。
测量抽象性
你可以通过计算模块内抽象类(或者界面)的数目与所有类的数目的比例来测出该模块的抽象程度。抽象度可以用下面的公式计算:
A=Na/Nc
A 代表模块的抽象程度
Na代表模块中抽象类或者界面的数目
Nc代表模块中具体类的数目
抽象度等于零表示该模块是一个完全抽象的模块,而抽象度等于一代表它是完全具体的模块。
评估度量标准
比较抽象度和稳定度,你可以发现一些更有趣的结论。完全不稳定的抽象模块也是完全抽象的、并且输入依靠度为零。相反,完全稳定、输入依靠度较大的模块意味它有较多的频繁使用的具体类。
这是因为抽象性把变换和实现分隔开来。变动频繁使用的具体类会衍生出许多新的变化,这些变化可能会波及整个软件。所以,你应该在具体类中尽量降低模块的输入依靠性。换句话来说,设计模块时要确保抽象性和输入依靠性、具体性与输出依靠性成比例。
评估设计质量的有效辅助工具
本评估方法可以帮助你提高软件强壮性。尽管好的度量方法并不能保证高质量的设计自然就会产生,但是它确实可以帮助你加强信心。在正确灵活的使用下,本方法是评估软件设计质量的宝贵手段。