随着科技和需求的发展和变化,现在的软件变得越来越庞大。这样,随之而来的最大挑战就是软件在设计上的越来越复杂和维护上的越来越困难。为了解决这个问题,软件架构师将软件切分成比较小的并且易于理解的多个模块。那么软件模块化会给我们带来什么样的好处呢?
- 拆分人力:将软件模块化后,我们就可以分配独立的团队去处理独立的模块,从而将人力拆分开来。这样既便于管理,又会降低整个软件的设计的复杂性。因为每个独立的团队可以专心去设计和实现其模块,而不用通盘考虑整个软件的复杂性。
- 抽象化:将软件模块化后,我们将整个软件抽象化成多层、多 模块的一个集成。这样使整个软件易于理解,便于管理。
- 重用:将软件模块化后,每个模块有其独立的功能和封装。这样这个模块就可以在多处(甚至是将来其他的软件中)重用,从而节省人力。
- 易于维护:将软件模块化后,当软件出现问题后,我们可以容易地定位问题出在那个模块,而每个模块又相对较小和易于理解,从而降低了软件维护的难度。
基于上述的 4 个优点,在当前的软件设计中,软件模块化是软件架构师的主流思想。为了实现软件模块化,应运而生的就是面向对象的高级编程语言,Java 是其中的典型代表。Java 用其独有的 Jar 格式文件去包装 Java 类和其他的资源文件,从而可以将软件组件封装成独立的 Jar 文件。这些 Jar 文件可以相互依赖并共同完成同一个工作,从而实现了软件的模块化。但是 Java 却不能真正的带给我们软件模块化的那 4 个优点,为什么呢?为了解释这个问题,我们需要知道模块的定义。
什么是一个模块?
一个模块应该有以下 3 个特性:
- 自包含:一个模块应该是一个业务逻辑的整体。它应该可以作为一个独立的整体被移动、安装和卸载。模块不是一个原子体,它可以包含多个更小的部分,但这些部分不能独立存在。
- 高内聚:一个模块不应该做很多不相关的事情,它应该专注于 1 个业务逻辑的目标并尽全力实现这个目标。
- 低耦合:一个模块不应该关注其他模块的内部实现,松散的联系允许我们去更改某个特定的模块,而不会影响到其他的模块。
而 Java 语言的 Jar 文件并不能完美的实现一个模块这 3 个特性,它主要会遇到以下的 3 个问题:
- 针对一个 Jar 文件,没有对应的 Java 运行时的概念。Jar 文件只有在开发和部署的时候有意义,而在 JVM 中,所有的 Jar 文件中的内容被简单地联系在一起作为一个单独的全局的列表,这就是所谓的“Classpath”。这种类加载模式,使 Jar 文件在运行时是不可见的。
- Jar 文件没有标准的元数据信息去指明该 Jar 文件所需要的外部依赖文件列表,这样我们就不能清楚的知道,该 Jar 文件需要和其他的那些 Jar 文件一起工作。另外,现在的 Jar 文件没有版本信息,这样,同一 Jar 文件的多个版本就不能同时被加载。
- Java 没有机制在不同的 Jar 文件中隐藏信息。
这 3 个问题,使 Jar 文件在模块的“自包含”和“低耦合”这两个特性上做的不好,从而使 Java 在模块的“拆分人力”和“易于维护”这两个优点上没有好的表现,而更严重的是第 2 个问题,这使 Java 应用软件存在难以处理的版本冲突问题。
Java 语言为了安全的考虑,它的类加载器(注意不是类加载)是多层立体的并且对其类加载采用了父委托机制。并且,当同一个类加载器加载类文件时,JVM 会加载最先发现类。所以当同一个类的新旧两个版本被分别封装在两个不同的 jar 文件中(比如:ClassVersion2.jar 和 ClassVersion1.jar),而这两个 jar 文件又都在 JVM 的类加载路径里的话,最先被加载的 Jar 文件中的类才会被使用到。而现在的 Java 应用软件因为长时间的更新维护,同一个模块的多个版本共存的情况比比皆是,这就会产生版本冲突问题。比如说,在 Java 应用软件中存在一个模块 ThirdComponent,这个模块依赖 ClassVersion 模块而且必须同老版本的 ClassVersion 模块(ClassVersion1.jar)一起工作,当新 ClassVersion 模块(ClassVersion2.jar)被升级到软件中后,ThirdComponent 模块很有可能就不会工作,因为类加载器很有可能会先加载的是 ClassVersion2.jar,而不是 ClassVersion1.jar。其实产生这个问题的根本原因是,Java 的 Jar 文件在自包含上做的不好。Jar 文件只是在软件的封装上起到了作用,而在 JVM 运行时中,Java 只关心类而忽略了 Jar,从而使 Java 的类加载变成了平面的线性的而非立体的网状的。
为了解决 Java 在模块化中存在的问题,OSGi 模块系统出现了。OSGi 是基于 Java 之上开发的,它提供了一种建立模块化的 Java 应用程序的方法并定义了这些模块在运行时中如何相互交互。
posted on 2010-01-03 16:24
远帆 阅读(268)
评论(0) 编辑 收藏 所属分类:
Java