但是,从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 Modules或Project Jigsaw中的 模块 )。 一个这样的捆绑包通常是一个(或多个)Maven模块的产品,但是它也通过适当地限定类加载器的范围来提供运行时保护。 Maven模块中的所有问题都是继承的……另外还需要命名包!
嵌套类/蛋糕图案
对代码进行范围界定的另一种可能性是使用嵌套类 ,甚至更进一步,并在Scala中使用Cake模式 。 除了旧的问题:使用什么软件包以及如何命名模块类外,我们还有几个新问题。 首先,模块的整个源代码现在位于一个文件中。 这可能意味着文件很长! 但是,这可能更多是IDE的问题:没有人说过需要一次编辑一个文件。 编辑器只能显示一种模块类/方法(例如在Smalltalk IDE中)。 蛋糕图案也不是没有问题 。 而且,嵌套模块呢?
DI框架
最后,我们有各种DI框架 (例如Guice,Spring或CDI),如果从适当的角度来看,我们在其中定义了可以依赖于其他模块(由容器注入)的小模块(类)。 将模块接口(java接口)与模块实现(java类)分开,并且仅注入接口也是很常见的。 但是,再次重申,部分静态地防止注入实现的唯一方法是,我们不得不求助于创建单独的-api和-impl Maven模块。
实际上,如果我们采用嵌套类的方法,那么DI框架可能非常适合解决模块间的依赖关系并为我们完成所有连接(如果我们想避免出现以下情况,这将非常有用:模块具有新的依赖关系,并且现在必须修改每个使用站点)。
下一个?
综上所述,我认为支持模块化的各种方法可以使用某种统一性。 而且,不幸的是,这可能意味着完全偏离我们今天从Java / Scala所了解的:新的软件包系统,新的构建系统,新的运行时系统。 不幸的是,新的编程语言的出现在该领域提供的内容并不多。
您是否认为应该有一个模块系统,可在小型(单个类)和大型(类集)中使用? 毕竟, DI容器用来解决依赖关系和实例化类的操作与启动时Maven或OSGi运行时的操作没有太大不同!
还是模块固有地具有几种类型,小型(类级别)和大型(maven模块/ osgi捆绑包级别)?
最后,也许还有其他一些非基于JVM的语言可以更好地解决模块化问题(仍然可用)?
参考: 模块,模块,模块…来自我们的JCG合作伙伴 Adam Warski 。
翻译自: https://www.javacodegeeks.com/2011/10/java-modularity-approaches-modules.html
所有评论(0)