
2.3 模块化现状
乍看起来,运行时模型与开发模型有着密不可分的关系。运行时模块系统会使得设计模块化的软件更加简单,但对于设计模块化软件,它并不是必需的。实际上,本书第一部分的其余章节会讨论模块化所带来的明显益处,在了解完这些之后,开发团队最好可以立即模块化他们的应用,即便它们目前可能不会部署在支持运行时模块系统的平台上。如果你正在使用支持模块化的平台,那这对你会很有好处。但如果不是这样,那么你可能会想知道如何设计模块化的软件。
关于OSGi运行时模型,我们了解了很多,Jigsaw的细节也逐渐为人所知。 [1]我们正在使用的很多平台在内部使用了OSGi运行时模型,即便它们现在并没有向我们暴露这一点。我们已经知道模块化单元是JAR文件,通过强调将JAR文件作为模块化单元并使用本书中的模式,现在就可以模块化我们的应用了。在第7章中,我们会直接看到在没有运行时模块系统的情况下,如何将一个系统进行模块化,这是通过将JAR文件作为模块化单元实现的。本书中很多模式的样例有意避免使用OSGi,不过我们会讨论当使用OSGi时这些模式该如何实现,OSGi会帮助我们进一步解释它们。在很多场景下,我们会包含使用OSGi的示例来阐述它所带来的优势。
当在应用中使用OSGi时,还需要记住的一点就是,对应用进行模块化的目的不仅是开发利用OSGi的应用,真正的价值在于它所带来的模块化架构。
注意
有很重要的一点需要注意,在没有运行时模块支持的情况下,对软件系统进行模块化会很有挑战性。在没有运行时系统时,你所使用的工具就很重要了。可视化工具可以帮助你理解结构,构建工具可以强制你保证应用中的结构,而依赖管理工具可以帮助你管理依赖,这些工具是很必要的。在本书中的很多样例中,将使用JarAnalyzer管理模块间的依赖(关于模块依赖,参见4.3节)。
另外,本书中的模式会帮助你对系统进行模块化。例如,等级化构建模式(Levelize Build pattern,参见12.2节)会帮助你在编译时实现模块间的关联关系。借助良好的工具和严格的纪律,模块化架构就会实现。另外,模块化架构实现之后一旦有运行时支持,就可以马上使用它了。但是,如果没有运行时支持,有一些事情是无法完成的。运行时模块化系统通常会支持以下的功能。
·封装(encapsulation)[2]:在标准的Java中,包中任何公开的类只要在类路径下就能被类路径下的其他类访问。换句话说,没有办法隐藏实现细节。所有的事情都是全局性的,这阻碍了模块化设计。运行时模块化系统提供了隐藏实现细节的能力。例如,OSGi可以使用μService为底层的实现细节提供接口。
·动态部署(dynamic deployment):在标准的Java中,更新软件通常需要重新启动JVM。运行时模块系统支持热部署。
·版本管理(versioning):在标准Java中,不能为一个类部署多个版本。模块化的系统允许部署多个版本。
·依赖管理(dependency management):在标准的Java中,没有办法实现模块的依赖结构。像Maven这样的构建工具试图通过描述依赖关系的JAR文件仓库解决这个问题。运行时模块系统可以实现运行时的依赖管理。