最开始可能只有一个项目,可能仅仅需要构建一个工程就可以,但是随着项目越来越大,在代码工程角度,需要做模块化,模块化指的工程的拆分以及工程内模块的拆分。
工程的拆分可以按照业务来拆分,模块的拆分可以按照功能来拆分。
举个例子:
项目包含了订单业务以及用户业务,那一般来讲是要拆成两个工程的。
每一个工程都可以大致分为三个模块:sdk,service,api。
sdk:封装本工程可以暴露的接口定义;
service:封装本工程接口的内部实现;
api:可以部署的模块,比如web api接口,直接打包部署;
依赖关系:api -> service -> sdk。
这是一个比较合理的工程模块化实践。
一旦所有的工程都按照如上模式构建,工程与工程之间如何协作?
理想情况,希望工程只依赖其他工程的sdk,或者runtime依赖一些本地实现,不能直接compile依赖service或者api。下面解释原因。
分两种:
1. 已经服务化的模块:比如用户工程,sdk内部定义了rpc比如thrift的接口,在api模块定义了rpc的实现,订单工程只需要加一个用户工程的sdk模块的依赖就行。
2. 未做服务化的模块:指的是采用本地实现的方式,比如用户工程的sdk定义了一个userService接口,用户工程的sevice模块实现了这个接口,订单工程想要依赖这个接口,那么必须compile依赖sdk的jar包然后runtime依赖service的jar包才行。
那么,为什么要做模块化?
或者说为什么这么定义依赖的规范,主要是因为这样做会让模块与模块之间的耦合度降低很多,其实就是依赖倒置原则的体现。依赖方和实现方都依赖接口,这样的构架是很稳固的。如果要改实现,只需要重发一个service的包,让依赖方更新依赖版本就行,依赖方的代码不用动。如果依赖方要改代码,也完全不会影响实现方。只要不动接口,二者没有任何直接的关联。
另外也是很重要的一点,可以降低编译时间。项目大了以后,对于非服务化的依赖,如果直接依赖别人的实现,那么这个实现是要被编译的,也就是说我作为依赖方不仅仅要编译我的代码,还需要编译外部依赖实现的代码,而实现一般也会有很多依赖,这会导致编译我方代码花费很长的时间,非常不利于平时的测试和发包。如果只依赖别人的sdk接口定义,编译就会快很多,别人的实现不会被编译,只会在编译完以后打包进来(runtime依赖),编译效率会有很大的提升。
千万别小看编译时间!!
=====================================
假设项目目录为:
parent
--service
--api
其中api会依赖service的模块;
要想让api可以使用service的代码,可以:
1.在api的pom里加入service的依赖;
2.在parent的pom里加入service的依赖,子项目会默认继承;
3.在parent的pom里声明service的dependenciesManagement,再在api的pom里加入service的依赖;