3

假设我有一个包含一堆相互依赖的函数的库,这个库太大了,我想把它拆分。有哪些算法可以找到合适的分区?

简单的例子,里面有四个函数:alpha,beta,gamma,delta。

  • beta 和 gamma 都称为 delta。
  • module1 调用 alpha 和 beta。
  • module2 调用 gamma。
  • module3 调用 alpha、beta 和 gamma。

算法的输出可能是:

  • LibA 包含 (alpha,beta)
  • LibB 包含 (gamma)
  • LibC 包含 (delta)
  • module1 依赖于 LibA
  • module2 依赖于 LibB
  • module3 依赖于 LibA 和 LibB
  • LibA 依赖于 LibC
  • LibB 依赖于 LibC

即它找到具有以下属性的最细粒度的 Lib* 分区

对于所有 X,如果通过任何方法将 LibX 划分为 LibY 和 LibZ,则所有依赖于 LibY 的模块/库也依赖于 LibZ,反之亦然。

有没有标准的解决方案?

4

1 回答 1

1

(这与人们在 C 和 C++ 程序中的头文件中遇到的问题相同。)

创建依赖关系的不仅仅是“调用”;它是对成员变量、静态变量甚至常量定义的任何类型的引用。

基本上你需要做的是发现所有细粒度的依赖关系(这通常需要一个类似编译器的分析工具来读取代码并发现声明的语言元素之间的这种依赖关系(声明、字段、方法、类、包,如果你是以java为中心等)和其他语言元素。使用编写库的语言的语义。(这样的分析可能是保守的)。这是本质给你一个巨大的图,节点是语言元素,并且弧是“用途”。

摘要中的库打包问题是将这个图分成块,最小化跨块依赖弧。这可能会为您提供大量的小型库。

实际问题是将一些彼此没有实际依赖关系但通常一起使用的块组合在一起。例如,一组缓冲区访问过程可能对默认缓冲区大小的定义没有任何显式依赖,但您可能想要一个包含两者的库,而不是两个库,其中一个仅包含默认缓冲区大小声明。这种一起使用的概念实际上是一个有问题的域工件,并且在代码中的任何地方都不可见,除非可能有一些统计上的使用共现。

这个问题的难点在于发现细粒度的语义依赖。您可以手动估算此值,但如果问题有任何规模,您将没有兴趣去做。(出于同样的原因,人们不会重新组织头文件)。您几乎需要语言工具来进行分析,大图管理来提出块,统计分析来获得启发式分组,并且可能需要一个 UI 来允许领域专家编辑分组以生成修改后的库。

然后,您需要一个工具来返回使用遗留库的代码,并修改它们以使用修改后的库。库重构和代码库修订都需要大量的代码分析和更改,这需要自动化。

Our DMS Software Reengineering Toolkit with its many language front ends is probably a good foundation for implementing such a library reorganization. We've considered doing this for C and C++ [which is why I have this response], but its a big task even for us to do. We'd love some serious additional motivation!.

于 2011-11-30T16:47:39.570 回答