栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

DDD仓储设计浅谈

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

DDD仓储设计浅谈

仓储设计是将前置的业务数据通过一系列的动作行为后,本身持久化的方式,那仓储我们该怎么设计呢? 明确目的:

1、封装基础设施来提供查询和持久化聚合操作。
2、集中提供常见的数据访问功能,从而提供更好的可维护性,并将用于访问数据库的基础结构或技术与领域模型层分离。
3、创建数据访问层和应用程序的业务逻辑层之间的抽象层。
4、应用程序对数据存储介质的更改不敏感

场景汇总:

1、 存储,存储的场景多见于持久化领域模型,经过某种行为后,数据发生改变,或者ui层或者其他领域广播事件,需要本领域消除副作用,这里需要注意,有时候副作用是在某个对象上面,有时候是在一批对象上(常见的一对多的关系设计),同时存储本身产生的副作用,需要广播出去,比如影响了其他领域的缓存?本身的换粗信息?以及本身的是否成功与否,对应得可能影响其他领域等等。

2、查询,该场景比较多,常见的是通过某一个固定的值来查询,但是部分常见也会有复合查询,究竟怎么定义,这里就要思考查询的场景目的是干什么的,加载单一对象数据?逻辑校验?加载一小批数据(分页)?聚合统计数据?需要对外提供的批量查询?

3、删除,部分场景可能需要物理形式的删除,以减少存储空间的使用,有的删除可能仅仅是状态的改变,可以调用存储,对应的仓储设计可以省去删除的接口。

技术选型:

动态类型的数据模型,推荐NOSQl,例如mangoDB,ES,Redis,HBase,Neo4j等,如果是强关系,MYSQL,Oracle等,仓储层的副作用消解,单机内Event和跨服务的MQ设计,缓存的强同步可能需要Feign调用来消解一致性问题。

战术: 1/模态转换:

淡出抽离一层用于数据模型的转换,上层调度可能传入的是值对象,或者具体的属性值,也可能是Event包括的Msg,我们抽离一层来解决数据映射的问题。

2/持久化Save:

持久话Save方法,在Save前查询,调度Find/ofXXX,如果有数据则调度更新,如果没有则Insert插入
对于更新这个操作,可能有些场景是一对多的关系,但这个多仅仅是影响了里面的一个子数据,如果全量更新开销是比较大的,

解决方案:

1、脏字段: 在对应的模型中增加一个标记字段,显示指明他的状态,仓储层识别后指定目标值更新,
2、AOP/ThreadLocal:会借助一个查询和变化后的数据比对,并拆解出一个工具层,同意处理,把更新的事情委托给AOP层。
3、战略设计的时候切割开,作为一个子领域去监听,相当于把某个领域里面的一个实体提炼出一个小的聚合,抽离出来设计,如果对应的单元对象发生改变,领域间通过事件机制同步信息,消除病症。(推荐)
有更好的欢迎留言。

针对批量更新,可能某个领域更新了一个对象的值后,会导致关联的某个领域发生批量更新事件,这里如果是小范围内的可以循环调度单对象更新,业务的语意会更明确,同时也可以考虑开辟一个批量的接口作为支持,这类别的借口可以放到对应的实体仓储上,也可以在领域中统一一个接口处理,开辟一个ExtRepository这种的。

需要注意: 为了高性能,一般会对热数据进行缓存,也就是双写,那么当发生数据对写事件时,往往需要同步缓存层的数据,这里就需要事件广播,异步/同步更新对应的缓存,以及事物处理后的反馈等等。
3/查询:

查询的场景相对较多,简单的查看ofXXX(身份特征)即可,但是多见的聚合统计,分页查询,批量查询等。

1、如开篇的目的中有说到常见这个词,笔者认为这里需要在业务场景及前期的领域知识等讨论的时候,汇总这类查询等场景,频繁多见的在Repository中开辟单独的查询且尽量单一,不要附带业务逻辑到Sql上。

2、批量查询可以考虑在实体仓储上设计,主要是提供伙伴关系的领域提供支持,降低网络开销,也没啥好纠结的,以前在和伙伴聊这个的时候也产生过分歧,他建议通过循环或者CQRS那种直接调度mapper,但是我比较建议这里解一层。同样这样做也有弊端,开辟了更多的读的仓储接口,泛滥了读的路口。

3、 在常见的业务规则中,有些规则常见,而且是多条件的,且这多个条件又不是某个实体本身自由特征,或设计同一个聚合中几个实体,这类查询我的建议是可以考虑设计成多个字段入参的复合查询,底层连表;当然也可以每个条件单独处理,最后组合,但是这种会设计频繁多次的DB查询,开销相对可能就大一些,但是拓展性高,这里就看具体业务具体分析了。如果有更好的方案,欢迎留言。

4、聚合统计&报表:如果公司有数仓部门,对于这类的借口可以考虑和数仓部门沟通,由数仓部门提供,也可以走自己的服务,但把这部分的接口和模型分开,正如CQS的设计,命令查询分离。报表功能也推荐这样去做,当然,如果没有数仓等部门,我个人建议把报表相关的业务抽离到一个报表服务模块儿中,统一聚合处理。


题外话

业务逻辑往往最初很简单,但是后面会很复杂,仓储层着重数据的持久化与查询,看起来是比较简单的,但是如果战略层面没有进行合理的设计,可能就导致存储的聚合根对象过大,所谓过大就是牵扯几个表处理,这种设计是不推荐的,一旦出现,往往仓储设计的时候需要判定存和度的具体对象,不是很好拿捏,不如在战略层面多砍一刀,切分开来,仓储操作单体实体,一对多通过开辟子领域去处理。当然这样可能产生更多的子域,对于聚合根来说可能管理的更多了,总之两害取其轻吧,中庸中庸。

注: 本文相对比较泛,更多的是描述应对场景的思路,后续会针对各类别的场景深入谈谈,比如仓储层的优化-分库分表/读写分离等等,包括仓储层产生的后遗症怎么治疗,具体到代码层怎么去编写等等。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/888025.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号