(这与人们在 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!.