理由
在本书第一部分中,我们首先在模块这个词上达成共识。然后马上会讨论模块化的两个方面:运行时模型和开发模型。从这里开始,将会考察模块化怎样帮助我们实现“自上而下的架构”,这是通过将重要的高层架构组件与更具体的实现结合在一起做到的。复杂性是我们要征服的怪兽,而重用是我们想得到的灵丹妙药,模块化在这两个方面都会给我们提供帮助,我们会讨论它在这个过程中所扮演的重要角色。最后,在进入模块化模式之前,会通过一个样例练习介绍模块化的收益。在整个过程中,我们为使用模块化找到了充分的理由。
定义
简单来说,模块就是“一个软件块”(chunk of software)。不过,这不能很简洁地区别模块与其他软件块,如类、包、组件、服务甚至应用。所以,我们需要关注这个定义:
软件模块是可部署的、可管理的、原生可重用的、可组合的、无状态的软件单元,它为用户提供了简洁的接口。
这是大而全的一个定义,第1章就贸然介绍它也很不好。但是,在一些解释后,你就能领会模块是什么了。图1.1展示了这个定义。接下来,将探讨模块的各个元素。
详细说明
1,可部署
模块是一个部署单元。不像其他软件实体,如类和包,模块是一个独立的部署单元,它能够与其他软件模块共处。从这个意义上讲,模块所表达的意义更多是物理层面上的,它比那些无形的软件实体如类或包的粒度更粗。可部署软件单元的例子包括EAR、WAR以及JAR文件。
2,可管理
模块是一个可管理的单元。在运行时模块系统中,模块可以进行安装、卸载以及更新。在开发过程中,将系统拆分成模块有助于简化很多其他的复杂活动。这包括提高构建的效率、允许开发人员独立地开发自主的模块并按照模块的边界规划开发工作。符合这部分定义的软件实体样例包括EAR、WAR以及JAR文件。
3,可测试
模块是一个可测试的单元。如同类可以使用测试驱动开发进行独立测试一样,模块也可以进行独立测试(参见12.3节)。符合这部分定义的软件实体样例包括类、包以及JAR文件。
4,原生可重用
模块是进程内(intraprocess)可重用的单元。尽管面向服务的架构(Service-Oriented Architecture,SOA)原则可以用来设计软件模块,但模块并不像应用或服务那样,它不是分布式计算技术。相反,以模块化组织部署单元的方式使得它们可以跨应用重用(关于重用,参见第5章),但是模块总是原生调用的。也就是说,模块暴露的操作是通过直接调用方法触发的。
重用模块的方式与重用服务也是不同的。一般来讲,服务只须部署一次并被多个使用者调用。因为模块是在进程内使用的,所以模块会与那些想重用其功能的进程一起部署。符合这部分定义的软件实体样例包括类、包以及JAR文件。
5,可组合
模块是可组合的单元。模块可以由其他模块组成。一般这指的是粗粒度的模块是由细粒度的模块组成的。(关于粒度,参见5.2.1节。)
6,无状态
模块是无状态的。特定版本的模块只会存在一个实例。我们不会实例化软件模块,尽管我们需要实例化软件模块中的类,这些类会保持状态,但是模块本身不会这样做。符合这部分定义的软件实体样例包括WAR、EAR以及JAR文件。