我想到的用例是fastutil,它是一个大型库,包含数千个类型特定集合的实现。这个库很受欢迎,几乎有500个Maven项目使用,但是许多用户认为它的大小(>10K类)是无法管理的,并要求将jar分割成更小的部分。
jar目前是OSGi模块化的,如下所示:
Automatic-Module-Name: it.unimi.dsi.fastutil
Bundle-Name: it.unimi.dsi.fastutil
Bundle-SymbolicName: it.unimi.dsi.fastutil
Export-Package: it.unimi.dsi.fastutil.*
Bundle-Version: ${version}我想把这个罐子分成三个部分(而且,为了清楚的是,一个贡献者创建了上面的信息--我对OSGi知之甚少)。问题是,拆分必然涉及到拆分包--由于库的性质,无法避免这种情况。我读过很多文章,反对这种做法,但这是我们唯一的选择。我的理解是,在这种情况下,应该使用Require-Bundle,它允许在包之间拆分包。
但是,我还没有找到以前存在的包的这种做法的例子。在这种情况下,我们希望这个修改能够透明地通过用户。
想象两个罐子中的分裂,我目前的理解是使用以下模块化:核心jar将使用
Automatic-Module-Name: it.unimi.dsi.fastutil.core
Bundle-Name: it.unimi.dsi.fastutil.core
Bundle-SymbolicName: it.unimi.dsi.fastutil.core
Export-Package: it.unimi.dsi.fastutil.*
Bundle-Version: ${version}然后,其余的jar将被模块化为
Automatic-Module-Name: it.unimi.dsi.fastutil
Bundle-Name: it.unimi.dsi.fastutil
Bundle-SymbolicName: it.unimi.dsi.fastutil
Require-Bundle: it.unimi.dsi.fastutil.core
Export-Package: it.unimi.dsi.fastutil.*
Bundle-Version: ${version}这似乎是合理的,但现在包的一半的包名与另一半的模块名不同。这会造成问题吗?
更普遍地说,对于上面的用例(已经被OSGi模块化的jar需要跨包拆分),最佳实践是什么?
发布于 2021-03-13 11:49:24
正如其他人所指出的那样,分拆一揽子计划是一种糟糕的做法。在如何做到这一点上没有最佳做法。尽管如此,人们确实需要在某一时刻将一个过度增长的包裹分割成碎片。我要指出Eclipse,它已经多次这样做了。有关一个示例的讨论,请参见https://www.eclipse.org/equinox/documents/3.2-migration.php:org.eclipse.core.runtime包。我还将注意到,Eclipse不是使用包导出/导入的最佳实践示例,因为它过度使用了Require。
发布于 2021-03-13 11:24:55
更广泛地说,对于上面的用例(需要跨包拆分的OSGi模块化jar ),最佳实践是什么?
如果您遇到了所描述的问题,而您没有模块化任何东西。相反地。模块化的目的是创建高度内聚的模块,通过定义良好的接口进行交互。您的建议表明,模块化背后的这一想法没有得到很好的理解。
拆分一个大型库,因为它有太多的类,所以在模块化方面做了最糟糕的事情。你增加了耦合,降低了凝聚力。你做了一些像杰克逊一样可怕的事情,在你的类路径上你总是需要6捆。
对于模块化系统,包装是一个主要的设计方面,它不是什么东西,你可以开始考虑之后。如果您没有获得模块化的巨大好处,那么您很可能一直在与OSGi做斗争。OSGi是模块化应用程序最可爱的环境,但它对其他人来说是个贱人。
如果您认真对待模块化,那么您应该尝试分解包,使每个子包具有更高的内聚力,并减少整体耦合。这大大降低了复杂性。
有些技术,如Tarjan的算法,可以分析您的代码,并找到自然的模块边界。最常见的情况是,支持其他可选库造成了很大的混乱,但编码方式使它们成为强制性的传递依赖关系。当我需要比较那些麻烦缠身的公司时,我总是很难过。
尽管如此,但怀疑这是起作用的,使用设计良好的服务API通常可以使大多数类都是私有的,特别是在设计时考虑到配置管理。
最后,如果您对OSGi有问题,这很可能是因为它告诉您您没有使用模块化。
https://stackoverflow.com/questions/66611958
复制相似问题