项目模块化
在企业项目中,包层次结构和类关系可能变得非常复杂。 将代码分成模块是一项艰巨的任务,因为它要求您能够清楚地识别功能边界,例如,将业务逻辑与数据持久逻辑分开。
耦合性和内聚性
两个主要因素将决定实现项目关注点分离的容易程度:耦合和内聚。 耦合衡量特定代码工件(例如类)之间关系的强度。 内聚性是指模块的组件所属的程度。 代码的耦合性越低,内聚性越高,项目的重组就越容易。 教授良好的软件设计实践超出了本书的范围,但是您应该牢记两个指导原则:最小化耦合和最大化内聚。
Spring 框架是正确实现模块化架构的一个例子。 Spring 是一个开源框架,提供许多企业 Java 应用程序所需的广泛服务。 例如,简化的 MVC Web 应用程序开发或事务管理的服务支持功能作为 JAR 文件进行分发。 如果服务需要不同模块提供的功能,则服务相互依赖。 图 6.1 显示了 3.x 版本的所有 Spring 模块及其相互关系。

Spring 的架构乍一看可能看起来很可怕。 它定义了许多相互依赖的组件。 但实际上,您不需要将包含所有组件的整个框架导入到您的项目中。 您可以选择要使用的框架服务。 值得庆幸的是,组件之间的依赖关系是通过元数据指定的。 使用 Gradle 的依赖管理使解决这些传递依赖变得轻而易举。
在以下部分中,您将模块化待办事项应用程序并使用 Gradle 的多项目功能来构建它。 由于目前代码库有限,这对于 Spring 框架的开发人员来说将是一项容易得多的任务。 我们将首先确定适合您的应用程序的模块。
识别模块
让我们回顾一下您已经为待办事项应用程序编写的代码,以找到其自然边界。 这些边界将帮助您将应用程序代码分解为模块。 以下目录树展示了现有的项目结构:
.
└── src
└── main
├── java
│ └── com
│ └── manning
│ └── gia
│ └── todo
│ ├── model
│ │ └── ToDoItem.java
│ ├── repository
│ │ ├── InMemoryToDoRepository.java
│ │ └── ToDoRepository.java
│ └── web
│ └── ToDoServlet.java
└── webapp
├── WEB-INF
│ └── web.xml
├── css
│ ├── base.css
│ └── bg.png
└── jsp
├── index.jsp
└── todo-list.jsp
通过将具有特定功能的类分组到包中,您已经很好地分离了应用程序的关注点。 您将使用这些包作为查找应用程序功能边界的指南:
-
模型:待办事项的数据表示
-
存储库:待办事项的存储和检索
-
Web:用于处理 HTTP 请求并在浏览器中呈现待办事项和功能的 Web 组件
即使在相当简单的应用程序中,这些模块之间也存在关系。 例如,存储库模块中的类使用模型数据类将数据传入和传出数据存储。 图 6.2 给出了所有建议模块及其关系的全貌。

考虑到已识别的模块及其关系,您可以开始将它们从单个项目中分离出来。
重构为模块
将现有项目结构重构为已识别的模块很容易。 对于每个模块,您将创建一个具有适当名称的子目录,并将相关文件移到其下面。 每个模块的默认源目录 src/main/java 将保持不变。 唯一需要默认 Web 应用程序源目录 src/main/webapp 的模块是 Web 模块。 以下目录树显示了模块化项目结构:
.
├── model
│ └── src
│ └── main
│ └── java
│ └── com
│ └── manning
│ └── gia
│ └── todo
│ └── model
│ └── ToDoItem.java
├── repository
│ └── src
│ └── main
│ └── java
│ └── com
│ └── manning
│ └── gia
│ └── todo
│ └── repository
│ ├── InMemoryToDoRepository.java
│ └── ToDoRepository.java
└── web
└── src
└── main
├── java
│ └── com
│ └── manning
│ └── gia
│ └── todo
│ └── web
│ └── ToDoServlet.java
└── webapp
├── WEB-INF
│ └── web.xml
├── css
│ ├── base.css
│ └── bg.png
└── jsp
├── index.jsp
└── todo-list.jsp
就是这样——您模块化了待办事项应用程序。 现在是时候处理构建基础设施了。