WuMortal / DDDSample

this is DDDSamp
MIT License
13 stars 8 forks source link

首先仓储放在领域层的,具体的实现在基础设施层。下图 展示层、应用服务层 都是调用 领域层的仓储,并且领域层的领域服务调用的也是该层仓储,这个是和三层有区别的地方,三层是 BLL 调 DAL #4

Open EasonXm opened 4 years ago

EasonXm commented 4 years ago

首先仓储放在领域层的,具体的实现在基础设施层。下图 展示层、应用服务层 都是调用 领域层的仓储,并且领域层的领域服务调用的也是该层仓储,这个是和三层有区别的地方,三层是 BLL 调 DAL image

Originally posted by @WuMortal in https://github.com/WuMortal/DDDSample/issues/3#issuecomment-615648152

Domain 放了仓储接口,那么DomainService里面就一个依赖注入的扩展类,且这个类也没有注册,这个类干嘛用的?IDomainService呢?你发的图片我没法打开呢,我也去找过别人的领域驱动的实现,他们领域里是将同一个业务领域的仓储类定义在同一个类中进行维护,APPlication层调用时不仅调用了DomainService的类同时还调用了仓储层的类,只是对我这个刚接触的人来说有点难懂,太多层了。

WuMortal commented 4 years ago

这个扩展类主要是用于 asp.net core 依赖注入的

WuMortal commented 4 years ago

IDomainService 看起来是有点多余,这个是我之前弄得,现在看来我觉得这个其实没有必要,只是为了满足 上层应该依赖下层的接口而不是具体实现,在实际开发中一般来说 DomainService 不会有多个实现

WuMortal commented 4 years ago

DomainService 和 ApplicationService 虽然都掉了仓储,但是这两个的职责不一样,ApplicationService 只是负责调度协调,而 DomainService 才算具体的业务

WuMortal commented 4 years ago

当一个操作涉及到多个聚合的时候,就需要 DomainService, 比如下单这个操作 ,它分为 创建订单(订单明细)--> 扣除库存 --> 通知 等等,这一系列的东西显然超出了 Order 聚合的职责范围,那么就需要 DomainService 去协调多个聚合来完成这个下单的操作。

WuMortal commented 4 years ago

ApplicationService 更多的关注的是: 商品是否存在 --> 计算优惠价格DomainService --> 生成订单DomainService

上面的流程中其实是 ApplicationService 在调度三个聚合(商品、优惠、订单)完成一件事, 1.商品聚合: 首先调用 ProductRepository 去判断商品是否存在, 2.优惠聚合: 计算优惠价格DomainService,为什么到这里确实 DomainService 呢?因为计算优惠价格肯定需要商品和优惠信息聚合配合来完成这个操作,

  1. 生成订单领域服务中,其实包含了领域事件。下单领域事件,会去调用 通知域的通知方法,还有库存扣除(这个取决与你是不是需要用分布式,简单点就是一个工作单元)
WuMortal commented 4 years ago

相对于分层架构,DDD 带来的更多是开发思想的转变

feiyueXH commented 3 years ago

当一个操作涉及到多个聚合的时候,就需要 DomainService, 比如下单这个操作 ,它分为 创建订单(订单明细)--> 扣除库存 --> 通知 等等,这一系列的东西显然超出了 Order 聚合的职责范围,那么就需要 DomainService 去协调多个聚合来完成这个下单的操作。

不一定吧,像用户注册功能,只有一个用户聚合根,但执行注册时需要调用仓储判断是否存在用户名重复,属于业务逻辑判断,放在应用层不太合适,也不能放在实体里面,只能放在领域服务中。 我也是刚学习DDD,说的不对还望指出

noahlann commented 3 years ago

当一个操作涉及到多个聚合的时候,就需要 DomainService, 比如下单这个操作 ,它分为 创建订单(订单明细)--> 扣除库存 --> 通知 等等,这一系列的东西显然超出了 Order 聚合的职责范围,那么就需要 DomainService 去协调多个聚合来完成这个下单的操作。

我觉得可能在application层去协调多个聚合会比较好,聚合原则上是独立于其它聚合存在,实际情况下看,它很可能会被独立为一个新的微服务,那么在应用层去协调多个微服务(RPC、REST都可)是不是会比较好?

DomainService则更多的用于处理类似于 用户-角色关系的业务逻辑?

可能描述不够准确,但我还是认为跨聚合调用应该处在应用层。

feiyueXH commented 3 years ago

当一个操作涉及到多个聚合的时候,就需要 DomainService, 比如下单这个操作 ,它分为 创建订单(订单明细)--> 扣除库存 --> 通知 等等,这一系列的东西显然超出了 Order 聚合的职责范围,那么就需要 DomainService 去协调多个聚合来完成这个下单的操作。

我觉得可能在application层去协调多个聚合会比较好,聚合原则上是独立于其它聚合存在,实际情况下看,它很可能会被独立为一个新的微服务,那么在应用层去协调多个微服务(RPC、REST都可)是不是会比较好?

DomainService则更多的用于处理类似于 用户-角色关系的业务逻辑?

可能描述不够准确,但我还是认为跨聚合调用应该处在应用层。

按我的理解,聚合其实是一种边界,在领域层中是最小的。再大一点的边界就是我们的界限上下文,聚合包含实体、值对象、聚合根,而界限上下文则是包含1到多个聚合。而部署微服务应该至少是在界限上下文的粒度上,比如下单上下文,一般包含购物车、订单等聚合。领域服务记得它的作用是处理单个聚合无法独自完成的事情,实体内部已经是充血模型,业务处理都是写在实体类,但也可能会出现单个聚合没办法完成的事情。比如提交订单成功后,移除购物车中对应的商品,这个时候领域服务就派上用场了。从应用场景上看,应用层负责协调多个界限上下文,比如提交订单之前可能需要从商品上下文获取商品明细、库存信息,从用户上下文获取送货地址信息,而领域服务,则是负责自己所在界限上下文内多个聚合来完成某个工作。

noahlann commented 3 years ago

当一个操作涉及到多个聚合的时候,就需要 DomainService, 比如下单这个操作 ,它分为 创建订单(订单明细)--> 扣除库存 --> 通知 等等,这一系列的东西显然超出了 Order 聚合的职责范围,那么就需要 DomainService 去协调多个聚合来完成这个下单的操作。

我觉得可能在application层去协调多个聚合会比较好,聚合原则上是独立于其它聚合存在,实际情况下看,它很可能会被独立为一个新的微服务,那么在应用层去协调多个微服务(RPC、REST都可)是不是会比较好? 而DomainService则更多的用于处理类似于 用户-角色关系的业务逻辑? 可能描述不够准确,但我还是认为跨聚合调用应该处在应用层。

按我的理解,聚合其实是一种边界,在领域层中是最小的。再大一点的边界就是我们的界限上下文,聚合包含实体、值对象、聚合根,而界限上下文则是包含1到多个聚合。而部署微服务应该至少是在界限上下文的粒度上,比如下单上下文,一般包含购物车、订单等聚合。领域服务记得它的作用是处理单个聚合无法独自完成的事情,实体内部已经是充血模型,业务处理都是写在实体类,但也可能会出现单个聚合没办法完成的事情。比如提交订单成功后,移除购物车中对应的商品,这个时候领域服务就派上用场了。从应用场景上看,应用层负责协调多个界限上下文,比如提交订单之前可能需要从商品上下文获取商品明细、库存信息,从用户上下文获取送货地址信息,而领域服务,则是负责自己所在界限上下文内多个聚合来完成某个工作。

确实如此,界限上下文在时间推移下有没有重新编排的可能? 如果有(一般情况下基本上不会发生),那么可能会涉及到将领域服务内逻辑进行拆分的可能;如果没有,那么领域服务处理多个聚合是没有问题,不过我更愿意为此新增一个聚合(关系聚合)。

后期我已经将领域服务“虚拟化”了,安排了步骤编排框架,整个编排即是领域服务,其中跨聚合的部分放置在应用层,而其它领域内部逻辑则放置在领域层。 感觉有时候不必拘泥于个中形式,虽有腐化风险,但如果有序且可控也是可取的吧。