我认为每个人都会同意,编写模块化应用程序和模块化通常是一件好事。

但是,从Java和Scala语言以及各种Java / Scala框架来看,对模块化的支持是怎样的呢? 有很多不同的方法! 让我们看看其中的一些。 “保护”以下是指模块在编译时或运行时的分离程度。

配套

首先,我们有Java(或Scala)软件包 。 当组织源代码时,该概念非常有用。 但是,它不提供编译时或运行时(受程序包保护的可见性除外,它没有被广泛使用)保护,因此很难说程序包对模块化代码有任何帮助。 此外,还有很多命名问题,因此也有约定:例如,如果我们有两种数据读取器实现,一种使用数据库,另一种使用文件系统,则相关的类应该进入数据库和文件系统子包,还是保留在同样的顶级套餐? 即使类名在专用软件包中,也应在它们之前加上数据库和文件系统吗?

建立子项目

其次,有Maven / SBT模块/子项目 。 它们提供了编译时保护,这是一件非常好的事情:现在,我们可以静态地确保我们的代码仅引用显式指定的依赖项中的类。 但是,随之而来的是一个显而易见的问题:什么时候一个功能“足够大”以使其成为一个单独的Maven模块? 可以有很多Maven模块,每个模块仅包含几个类(可以是PITA,必须为每个类定义一个单独的pom,目录结构),还是应该更大一些? 关于命名约定,包名称应与模块名称相对应吗? 如果是这样,我们显然违反了这里的DRY ;)!

想象一下,我们决定将数据库和文件系统数据读取器放入单独的程序包,maven模块中并适当命名。 因此,在myapp-database Maven模块的foo.bar.database包中,我们有一个DatabaseReader(外加10个帮助器类)。 现在是一个简单的重构:将“数据库”重命名为“ db”成为一项非常复杂的任务,最肯定的结果是在各个地方使用了各种术语。

OSGi

演进的下一步将是OSGi捆绑包 (或等效地,是JBoss ModulesProject Jigsaw中的 模块 )。 一个这样的捆绑包通常是一个(或多个)Maven模块的产品,但是它也通过适当地限定类加载器的范围来提供运行时保护。 Maven模块中的所有问题都是继承的……另外还需要命名包!

嵌套类/蛋糕图案

对代码进行范围界定的另一种可能性是使用嵌套类 ,甚至更进一步,并在Scala中使用Cake模式 。 除了旧的问题:使用什么软件包以及如何命名模块类外,我们还有几个新问题。 首先,模块的整个源代码现在位于一个文件中。 这可能意味着文件很长! 但是,这可能更多是IDE的问题:没有人说过需要一次编辑一个文件。 编辑器只能显示一种模块类/方法(例如在Smalltalk IDE中)。 蛋糕图案也不没有问题 。 而且,嵌套模块呢?

DI框架

最后,我们有各种DI框架 (例如Guice,Spring或CDI),如果从适当的角度来看,我们在其中定义了可以依赖于其他模块(由容器注入)的小模块(类)。 将模块接口(java接口)与模块实现(java类)分开,并且仅注入接口也是很常见的。 但是,再次重申,部分静态地防止注入实现的唯一方法是,我们不得不求助于创建单独的-api和-impl Maven模块。

实际上,如果我们采用嵌套类的方法,那么DI框架可能非常适合解决模块间的依赖关系并为我们完成所有连接(如果我们想避免出现以下情况,这将非常有用:模块具有新的依赖关系,并且现在必须修改每个使用站点)。

下一个?

综上所述,我认为支持模块化的各种方法可以使用某种统一性。 而且,不幸的是,这可能意味着完全偏离我们今天从Java / Scala所了解的:新的软件包系统,新的构建系统,新的运行时系统。 不幸的是,新的编程语言的出现在该领域提供的内容并不多。

您是否认为应该有一个模块系统,可在小型(单个类)和大型(类集)中使用? 毕竟, DI容器用来解决依赖关系和实例化类的操作与启动时MavenOSGi运行时的操作没有太大不同!

还是模块固有地具有几种类型,小型(类级别)和大型(maven模块/ osgi捆绑包级别)?

最后,也许还有其他一些非基于JVM的语言可以更好地解决模块化问题(仍然可用)?

参考: 模块,模块,模块…来自我们的JCG合作伙伴 Adam Warski

相关文章 :

翻译自: https://www.javacodegeeks.com/2011/10/java-modularity-approaches-modules.html

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐