背景
今天和大佬聊天的时候聊到了现在的项目架构让我感觉非常混乱,大佬给我看了一些理想的架构,以及一些理想的对应方法
参考资料
一些交流笔记
总体来说,可以分成三个部分
- interface部分,包括前段,form,controller,webBean等等的内容
- application的业务逻辑部分,包括各种interface,service(logic),repository interface,repository
- 更高层级的业务部分(domain,flow)等,在开发的时候可以不考虑
从根本上来说,所有的代码都可以写在一起,但是划分这么多层级的主要目的就是消减代码之间的依赖关系。比如如果把业务逻辑写在controller里面,那么修改逻辑的时候就必须要从controller里面再去寻找了。更严重的问题,比如在service层级里面有大量依存数据库的代码,那么更改数据库之后所有的地方都需要更改。
- 最理想的方式是service和repository里面都带有interface,这样不需要触碰更深一层的代码(但是太理想了现在的业务里做不到)
- repository的最大存在意义是处理很复杂的select逻辑->(所以如果特别简单的数据读取(比如index)可以考虑跳过repository,但是相当于增加了对数据库的依存)
repository pattern的阅读笔记
根本目的:和DAO相似的设计模式,用高度抽象的操作隐藏具体的数据库操作(也就像JPA里面只给我们看interface)。这样用repository的人不用考虑底层用的什么数据库(MySQL还是Redis),而是直接跟interface交涉
经常出现的一些反面教材
按照功能分开repository
对于一个entity,按照不同的功能分出来了好几个repository
- 光看一眼不知道用哪个功能,业务逻辑也被分散在不同的地方
- 因为太混乱,所以业务逻辑上更容易出问题
- 对策
- 意识到repository只是对底层的对数据库的读写,不要加入进去太多的业务逻辑
- 把这个功能整合到service里面
对于子table做很多个repository
比如用户对应的住所,联络方式等等多个表,每个表都有一个repository
- 如果联络方式有两个种类(自家电话,手机),同时注册用户的时候要求必须有一种联系方式。这样的话虽然是跟用户有关的操作但是必须放在联络方式的repository里面,变得更混乱了
- 对策
- DDD集约,也就是跟这个entity(用户)有关系的必须都经过一个object
- (但是不太适合太复杂的情况,太多了)
复杂的query
比如要找:没有退会+最近三个月登陆过+最近一个月买过10个以上商品的
- 问题:需要从id的到商品记录,在count买过的商品数。这种比较大的query会引起一些性能上的问题以及维护上的混乱
- 对策 CQS(Command Query Separation)
- command和query分离的方法
- 复杂的query不装在repository里面,而是直接装在业务逻辑里面(也就是service层)
- CQS
- Query: 是得到一个method的return(不改变application的state)
- Command:是让一个method有所行动(改变application的state)-> 可以在method名字前面加上!可以提醒用户这个会改变状态
- 这样我call这个method的时候,我就会知道我这个行为会不会改变application的state
- 违反这个原则的,比如pop,又改变了stack的状态,又取得了内容