深搜代码
依赖元组。
图片您的代码。 描绘所有不依赖源代码的函数。 这听起来可能很奇怪:如果一个函数没有源代码依赖性,那么它的目的是什么? 好吧,我们必须区分编译时依赖和运行时依赖。 的确,在运行时所有实体都必须由其他运行时实体调用:它一直是乌龟(或者至少一直到刚上电的硬件及其固件初始化的指令指针)。
但是,在编译时的超现代怪异中,源代码依赖为王,两种类型的函数愤然地避开了所有源代码依赖。 的
第一种类型包括从源代码外部调用的那些函数。 main()
函数提供了一个很好的例子:您无需编写任何明确调用main()
函数的内容,而是将环境粉碎到源代码中才能找到它。 第二种类型包括实现在其他地方的接口中声明的签名的那些函数。 此类函数的客户很少会直接调用它们,而是选择通过其接口声明来调用它们。 是的,系统在运行时将两个和两个放在一起以确定要执行的内容,但是在编译时,系统的灵活性取决于仅通过关联的接口调用这些函数。 源代码依赖性取决于接口签名,实现功能避免了倾盆大雨。 (第二种类型还包括从超类继承并通过该超类调用的函数,但在此我们主要关注接口。)
回到我们的可视化。 考虑一个由单个类Wonder
组成的玩具系统。 该类具有三个函数:Java的静态main()
函数,该函数通过调用构造函数实例化Wonder对象。 构造函数本身, Wonder()
; 以及构造函数调用的函数a()
,见图1。
图1:简单的Wonder系统。
图1中有多少个源代码依赖元组? 有一个:{ main()
, Wonder()
, a()
}。 元组是一组刚排序的元素。 在功能级别上,源代码依赖项元组只是源代码功能依赖项的有序集合。 如果它们看起来像是普通的调用路径,那是因为这两个概念共享DNA。 但是,调用路径只有在运行时才能爆发,条件执行序列的神奇表现从实现到实现都在跳跃,而忽略了接口。 源代码元组在文件系统永久冻结中Hibernate,在两次更新之间冻结(有时长达数年)。 它们在任何没有源代码依赖性的函数上句法终止,无论是实现还是接口声明。
鉴于程序在功能级别上的结构仅仅是其功能及其相互关系的枚举,因此可以说,在某种意义上,程序的功能级别结构是其所有功能级别依赖项元组的并集。 一些其他示例可能会有所帮助。
图2:扩展的奇迹。
图2显示了一个略微扩展的Wonder类,现在该构造函数调用了其他三个函数。 现在有三个依赖元组:{ main()
, Wonder()
, a()
},{ main()
, Wonder()
, b()
}和{ main()
, Wonder()
, c()
}。
图3:更多奇迹。
图3有四个依赖项元组。 当然,所有这些都非常有趣,但是这与“深层”代码有什么关系?
代码深度。
依赖项元组的深度只是其基数,即它包含的元素数。 因此在图3中,元组{ main()
, Wonder()
, c()
, d()
的深度为4。 那么,程序的深度就是其所有依赖元组的平均深度。 因此,图3显示了深度为3.5的系统。 鉴于对函数的更改比起向独立的函数起跳回依赖函数的可能性更大,因此深度编程人员会感兴趣,因为依赖元组越深,则对该元组的更改可能会影响更多的函数。 在图3中,函数e()
具有三个与传递相关的函数: c()
, Wonder()
和main()
,而较短的元组中的a()
只有两个。
当然,代码深度几乎不能说是程序结构的唯一甚至最重要的驱动力,它只是陷入竞争影响的喧嚣之中。 但是程序员不应忽略它。 让我们从深度的角度看一下Wonder系统的最佳和最差配置。
图4:神奇的森伯斯特。
图4显示了Wonder功能的深度理想配置,即最浅的可能配置: sunburst 。 (如果我们准备允许main()
函数静态地调用所有其他函数,那将变得更浅。)在此,没有一个函数具有两个以上依赖于该函数的传递函数。
图5:不足为奇。
另一方面,图5显示了Wonder系统的最差配置:单个元组,最大深度。 这里的五个功能具有两个以上依赖于它们的功能。 同样,深度仍然是许多影响因素之一,程序员当然不能享受以他们希望的任何方式配置其功能的自由。 至少,语义约束要求逻辑分解。 那么代码有多深? 程序员会坚持到底吗?
重新分析。
那些采样过像Junit和Ant这样的小样本集的人既不能得出明确的结论,也不能拒绝猜测。 图6显示了从版本3.6到版本4.9的每个JUnit版本的功能依赖元组深度。
图6:JUnit深度。
该图表明JUnit的平均元组深度保持在5.5左右,也就是说,大多数函数可以期望驻留在5.5个函数的元组中(标准偏差约为3)。 这似乎不太过分。 很少有程序员会发现这样的元组不堪重负。 但是,将此与蚂蚁的历史轨迹进行比较。
图7:蚂蚁深度。
图7显示了蚂蚁的深度,在版本1.6中,该深度已飙升至近20(标准偏差约为8)。 许多程序员可能会发现这一点。 他们可能会质疑,为什么大多数功能都应该位于如此长且可能是波纹的元组中。 也许更多的项目应该使用深度表。
摘要。
在我们程序的弹球机中,我们倒入分析思想的金属球,看着它们在复杂的依赖元组的网中掉落时发生气泡和弹跳,并以满意的感觉将它们收集在托盘中(“这些功能的结构精确或困惑(“该功能与现在的功能有关?”)。
翻译自: https://www.javacodegeeks.com/2013/04/how-deep-is-your-code.html
深搜代码