以下项目名称使用:aba做为例子

单体入门

大部分人初学编程时,写的都是单体应用。

例如java,如果你使用maven作为依赖包管理与构建工具,那好maven中的<packaging>关键字默认是jar,所创建的maven标准应用目录结构为

java 分层详解 java分层领域模型 太麻烦_面向对象

<packaging>默认jar

java 分层详解 java分层领域模型 太麻烦_java 分层详解_02

上边的结构,对于简单的应用已经可以满足,只要在pom.xml文件中添加对其他dependency的依赖,一个简单的服务就可以完成。

但不管怎么说,我们应该以一种发展的眼光看待应用,不管是现今还是未来,应用本身只要有人使用,就会产生需求,不同的人会有不同的需求,当需求变多、单一功能变得复杂,需要拆解的时候,单体应用在结构上的单一性导致了总体结构的复杂度急剧飙升,为了不让项目失控,这时候需要做拆分。

如何拆分?

面向对象设计(oo)的三大精髓:封装、继承、多态,封装是隐藏代码复杂度,继承是抽象的具体化,多态是抽象的更高等级抽象,但这里我要讲的是模块化,复用是我们的最终目的。

面向对象设计中,很多人领悟到了它的思想,但并没有在应用层次中使用(这里应用层次指,系统的区分,系统可能还有子系统,子系统也可以叫模块),推而广之,应用层次对oo的实践,更多的应是以模块化的方式来表达。

如何实现模块化?

我们还是用maven作为例子,其中的<packaging>关键字,父级使用关键字pom,中间层级也是用pom,最终模块层级使用jar,总体架构如下

java 分层详解 java分层领域模型 太麻烦_架构_03

目测大部分人的应用都是这么写的,组内项目,每人负责一个模块,各自应用互相解耦,不互相依赖。

站在微服务的角度上来说,一个应用,如果业务足够庞大,可以从业务角度、设计角度或者架构角度出发,对应用进行拆解,上述架构很符合这一设想。但如果站在软件设计者的角度上看,里边会存在诸多重复的代码,例如:

  • 包引用:app1app2都引用了commons-lang3包,这是一个重复
  • 工具类配置类:所有应用都需要连接数据库,所以都写了同一个配置类创建数据库线程池

时间和成本在这些无关业务的代码上耗费了很多,就好像一个测试人员为了搭建测试环境,整天都在为如何搭建可移植的,等同于开发环境的测试环境而烦恼。

优化?

如何优化模块结构?

首先我们要了解,大部分项目,都是建构在技术层面与业务层面相结合的复杂场景之下。

例如同样是要连接文件系统,aba-app1模块的开发者首先用到了该技术,aba-app2模块的开发者后续也要用到,那么我们就可以提取一个公共包,名叫aba-common,把相关实现放其中,两个模块可以共同使用。

mvc-》聚合

如果在写项目的时候,如果你接触到同一部门的不同项目组的代码会发现,有时候不同项目会读取同一个库中的数据,如果同时都由你维护,查询逻辑又相近,那你每次都得维护两份一样的代码。这低效,重复,而又枯燥。

如果是项目内部有两个模块使用了类似的查询代码,同时维护两份那更加让人抓狂。

所以这里我建议再抽象一层aba-mms(model-mapper-service的简称),后边的mms由项目各自定义,例如:可以叫aba-mmm(model-mapper-manage)等,它专门用来管理统一的查询代码,尽量剥离业务层面做访问操作业务库使用。

但这一层不做事务控制,你可以在你的aba-app1aba-app2中写service来控制事务,如果再复杂,再抽象一层facade做聚合。

业务之外的基础服务

很多时候我们会用到类似spring-cloud相关的技术组件,这些是作为基础服务呈现,那么怎么与上述模块互相整合呢?结构的最终形态是怎样?

见图

java 分层详解 java分层领域模型 太麻烦_架构_04

  • aba-app:应用,引用aba-core中模块
  • aba-core:提供公共包
  • aba-infrastructure:基础服务

只有你用?

现在又有一项目bab启动,他也要使用文件系统,这时候,aba-common就可以提交到公司的maven私服,提供给全公司使用。推而广之,如果够豪放,还可以开源,像Netflix不就是?


轮子造的多,不如开源多这是我的看法