以下项目名称使用:aba
做为例子
单体入门
大部分人初学编程时,写的都是单体应用。
例如java,如果你使用maven作为依赖包管理与构建工具,那好maven中的<packaging>
关键字默认是jar
,所创建的maven标准应用目录结构为
<packaging>
默认jar
上边的结构,对于简单的应用已经可以满足,只要在pom.xml
文件中添加对其他dependency
的依赖,一个简单的服务就可以完成。
但不管怎么说,我们应该以一种发展的眼光看待应用,不管是现今还是未来,应用本身只要有人使用,就会产生需求,不同的人会有不同的需求,当需求变多、单一功能变得复杂,需要拆解的时候,单体应用在结构上的单一性导致了总体结构的复杂度急剧飙升,为了不让项目失控,这时候需要做拆分。
如何拆分?
面向对象设计(oo)的三大精髓:封装、继承、多态
,封装是隐藏代码复杂度,继承是抽象的具体化,多态是抽象的更高等级抽象,但这里我要讲的是模块化
,复用是我们的最终目的。
面向对象设计中,很多人领悟到了它的思想,但并没有在应用层次
中使用(这里应用层次指,系统的区分,系统可能还有子系统,子系统也可以叫模块),推而广之,应用层次
对oo的实践,更多的应是以模块化
的方式来表达。
如何实现模块化?
我们还是用maven作为例子,其中的<packaging>
关键字,父级使用关键字pom
,中间层级也是用pom
,最终模块层级使用jar
,总体架构如下
目测大部分人的应用都是这么写的,组内项目,每人负责一个模块,各自应用互相解耦,不互相依赖。
站在微服务的角度上来说,一个应用,如果业务足够庞大,可以从业务角度、设计角度或者架构角度出发,对应用进行拆解,上述架构很符合这一设想。但如果站在软件设计者的角度上看,里边会存在诸多重复的代码,例如:
- 包引用:
app1
与app2
都引用了commons-lang3
包,这是一个重复 - 工具类配置类:所有应用都需要连接数据库,所以都写了同一个配置类创建数据库线程池
时间和成本在这些无关业务的代码上耗费了很多,就好像一个测试人员为了搭建测试环境,整天都在为如何搭建可移植的,等同于开发环境的测试环境而烦恼。
优化?
如何优化模块结构?
首先我们要了解,大部分项目,都是建构在技术层面与业务层面相结合的复杂场景之下。
例如同样是要连接文件系统,aba-app1
模块的开发者首先用到了该技术,aba-app2
模块的开发者后续也要用到,那么我们就可以提取一个公共包,名叫aba-common
,把相关实现放其中,两个模块可以共同使用。
mvc-》聚合
如果在写项目的时候,如果你接触到同一部门的不同项目组的代码会发现,有时候不同项目会读取同一个库中的数据,如果同时都由你维护,查询逻辑又相近,那你每次都得维护两份一样的代码。这低效,重复,而又枯燥。
如果是项目内部有两个模块使用了类似的查询代码,同时维护两份那更加让人抓狂。
所以这里我建议再抽象一层aba-mms
(model-mapper-service的简称),后边的mms
由项目各自定义,例如:可以叫aba-mmm
(model-mapper-manage)等,它专门用来管理统一的查询代码,尽量剥离业务层面做访问操作业务库使用。
但这一层不做事务控制,你可以在你的aba-app1
与aba-app2
中写service
来控制事务,如果再复杂,再抽象一层facade
做聚合。
业务之外的基础服务
很多时候我们会用到类似spring-cloud
相关的技术组件,这些是作为基础服务呈现,那么怎么与上述模块互相整合呢?结构的最终形态是怎样?
见图
- aba-app:应用,引用aba-core中模块
- aba-core:提供公共包
- aba-infrastructure:基础服务
只有你用?
现在又有一项目bab
启动,他也要使用文件系统,这时候,aba-common
就可以提交到公司的maven私服,提供给全公司使用。推而广之,如果够豪放,还可以开源,像Netflix不就是?
轮子造的多,不如开源多
这是我的看法