您如何比较两个不同程序的结构? 您可以启动IDE并潜入水中。一周的浮潜无疑会得出有效的结论。 但是,如果只有十秒钟的时间来决定,那么您需要其他一些工具。
在其他领域面临类似问题的工程师通常会寻求累积分布函数 (CDF)来获得结果,软件工程师可以从中学到很多。
但是,首先,通常是(对于本博客而言)前言:结构良好的程序可促进更新的可预测性。 导致更新与预测大相径庭的原因之一就是涟漪效应,从而一处更改代码会导致另一处发生更改,进而导致进一步的变化等。两个因素会极大地影响涟漪效应: 传递依赖项的数量和长度。 因此,在所有其他条件都相同的情况下,与其他程序相比,具有更多和更长的传递依赖性的程序倾向于结构欠佳。
因此,我们的任务变成了:我们如何比较两个不同程序中传递依赖的数量和长度? (我们将在这里研究方法之间的依赖关系,而不是类或包。)
仅对传递依赖项进行计数会产生较差的比较工具:较大的程序往往具有更多的传递依赖项。 相反,我们应该比较传递依赖项密度:传递依赖项的数量除以方法数量,从而将数量标准化。 程序A具有比程序B更高的密度,表明程序A的结构上的劣势。
但是,要比较传递依赖项长度,我们可以使用传递依赖项长度的CDF(实际上是其变体)。 例如,图1展示了JUnit的传递依赖项长度的CDF。
图1的X轴显示了JUnit的传递依赖项的长度:其所有传递依赖项的长度在1到20个方法之间。 Y轴显示等于或小于特定长度的JUnit传递依赖项的百分比。
该图显示JUnit的传递依赖的50%左右是5种方法或更少。 90%的时间大约在11种以下。 而且由于JUnit的最长传递依赖项的长度为20个方法,因此其传递依赖关系的100%必须小于或等于20个方法的长度。
但这还不能进行直接比较,因为X轴的绝对值将意味着两个程序可能占据不同的范围,从而使图形倾斜。 但是,我们可以在X轴上绘制最大长度的百分比,而不是任何特定的可传递依赖项所具有的最大长度的百分比,而不是绝对可传递依赖项的长度,请参见图2。
在两个轴上都具有百分比可能看起来很奇怪,但是图2显示,只要最长的传递依赖项,JUnit的60%的传递依赖项大约为30%(或更少)。 只要最长的传递依赖项,JUnit的90%传递依赖项约为55%(或更少)。
结构良好的系统向左弯曲该曲线:与结构较差的系统相比,传递依赖项更短,它们的传递依赖项所占的百分比较高,而最大长度所占的比例较低。
最后,我们现在可以并排绘制多个系统,见图3。
图3的图例中的数字表示每个系统的传递依存关系密度。
结构良好的系统会Swift上升,因此比较六个30%到50%百分比长度的系统很有意义。 四肢之间的鸿沟令人不安:只有25%的Ant的及物依赖项不到最大值的30%,而Spoiklin的及物性依赖项不到最大值的30%。 结合每种方法令人垂涎的22种传递依赖关系,这强烈表明了蚂蚁的理想结构。
Spring在程序包级别提供了一个漂亮的结构,但是,如前所述,在方法级别上,它长期遭受传递依赖的困扰,其传递依赖的30%超过了最大长度的一半。
JUnit , FitNesse和Struts都跟踪相似的轨迹,其传递依赖的80%小于最大长度的一半。 它们的曲线是如此相似,以致它们的密度可以决定它们的结构命运,而JUnit和Struts都显示出良好的,波纹效果惊人的低密度。
摘要
CDF可以一目了然并从特定角度提供整个系统的概述,使其非常适合分析大型复杂软件系统。 当然,仅CDF图并不能绝对地评估结构的宏大程度或变形程度。 极端的异常值可能会损害结果; 建议进行一些浮潜。 但是,CDF可以提供宝贵而快速的洞察力。
翻译自: https://www.javacodegeeks.com/2015/04/software-engineering-as-engineering.html