52 Comments

  1. 韩海文

    对目前习惯mvc的开发来说,DDD的实施是一个挑战。比较认同,避免贫血对象。贫血对象的出现,导致业务的耦合,复杂度的上升。

  2. heys

    在将repository的时候说到只有聚合根才配拥有资源库,但是在示例代码中应用服务里面直接使用了repository的byId和sava方法,这两种没有矛盾吗。感觉在应用服务里面直接使用repository这样和贫血模型也没什么差别啊

    • 滕云

      “只有聚合根才配拥有repository”与“应用服务直接调用repository”没有关系。贫血模型主要针对的是业务对象(比如文中的Order),其与“应用服务里面直接使用repository”也没有关系

  3. 姓名

    删除只要一个聚合根的ID就可以了,需要封装成命令吗,如果不需要,删除也是写操作,怎么统计命令动作。示例代码里没有,请教!

      • 日子

        您好,两个问题请教下:
        1、您怎么看待DDD和OOD之间的联系?感觉这俩既有联系有没联系。
        2、您示例中Order实体有个方法pay,我有个疑问,付款是个动词,只有人才有付款的行为,为什么在Order里有个业务方法pay?难道订单自己会付款?这是否与真实世界的逻辑合理性相悖?

        • 滕云

          1、是的,既有联系又没联系,没有联系是说DDD不一定是OO的,有联系是说在落地实践过程中,DDD通常以OO的形式呈现

          2、当我们说OO中的一个对象既有数据又有行为(也即动词)时,我们并没有因为这个对象不是人而认为其不应该有行为;Java中的List有个add()方法,元素其实是别人add进去的,为什么最终却放在了List上呢?因此,全然用真实世界去刻画OO是一个很大的误区,DDD也如此。

          • 日子

            第二点看后有种豁然开朗的感觉。
            第一点,我个人仍有【不知其然】的感觉。那具体DDD和OO又是如何结合的呢?滕老师可否电子邮件回复,希望向您做更进一步的请教。感谢!

  4. 微笑刺客

    尝试阶段,遇到一个问题,不好怎么划分。
    1、Controller如果是提交一个表单,这个表单中包含两个聚合根需要的东西或是两个限界上下文内的聚合根,在Controller,是否是需要两个限界上下文内的应用服务各调用一次呢?
    Controller action{
    _aAppService.CreateXXX();
    _bAppService.CreateXXX();
    }
    2、一个聚合根如Plan,在创建Plan时,要依据Plan的信息生成一份Plan模板,并返回Plan模板Id,再填充到Plan中,这时操作的属于两个聚合根。这种场景不确定操作是否合适,有点拿捏不准。

    • 滕云

      在一个controller中操作两个聚合根通常是不推荐的做法,即便却有这种需求,也需要将他们同时放到一个事务边界中。

  5. arvin

    想问下,遇到了批量更新操作,这种场景怎么理解聚合根,是单独设计再设计一个批量的么,求指导下这种设计思路

  6. 微笑刺客

    用工厂创建聚合或是聚合本身承担工厂时,如果请求传递过来的参数过多,整个聚合创建将会有好多行参数,有没有什么好的替代方案呢,目前用构建者模式进行了拆分,想看看是否还有好的方式,去解决满屏都是参数。

  7. Kid

    我想请教一下为什么order上下文里面的内容要拆分为
    ecommerce-order-service-api和ecommerce-order-service-sdk这两个模块呢?

    • 滕云

      我文章里这种分法并不具备通用性,不过可以参考。我的初衷是:当其他服务调用order service中的API或者消费order service的领域事件时,他们也需要创建出相应的command和domain event对象,要么自己另行创建,要么依赖order中的sdk,sdk中就包含了command和domain event。

  8. lucas

    想请教一下
    1. 在不使用分布式id,使用自增长ID的时候 这个唯一标识是怎么处理,是在保存的时候生成吗?
    2. 聚合根通过repository进行持久化和获取的时候,聚合需要分别存储 如 用户包含用户信息和地址 别存储两张表 那么在repository中就是对这两个的Dao 进行保存和获取?
    3. 有一些细碎的处理 比如用户名唯一的验证 手机验证码的校验 也是应该在领域服务中处理是吗?像我上面这个用户例子 我是不是可以在领域服务中直接调用用户的dao接口对用户名进行唯一验证?

  9. lucas

    我想请教一下, 聚合根通过repository进行持久化的时候,聚合需要分别存储 如 用户包含用户信息和地址 别存储两张表如何处理?是不是在repository实现中分别调用用户和用户地址的持久化接口(Dao)?

    • cas_9582

      不对聚合直接进行持久化,能够在聚合的repository中通过数据访问对象(DAO)来进行持久化?如用户中包含用户信息和地址,不将用户这个聚合作为整体持久化 而是在repository中分别调用用户信息DAO和用户地址DAO操作

  10. Sen

    Command对象那一小节最后的图,通过 DomainService完成业务逻辑,中间貌似漏了 Repository.getAggregateRoot() 这个步骤

  11. 笑小刀

    很有收获的一篇文章,拜谢。
    因为是带着疑问来的,所以提几点疑问:
    1. 领域服务是必要的妥协。也就是在聚合能独立完成的,应聚合完成;无法独立完成时,建议采用领域服务吗?
    2. 一个限界上下文内,可能存在多个聚合。如果多个聚合参与协作,可以直接这样操作吗?如:使用领域服务,在领域服务内,设计到其他聚合的业务时:OtherDomainRepo.find() -> otherDomain.execute() -> OtherDomainRepo.save()

    • 滕云

      1. 是的,在笔者所接触过的某些项目中,领域服务完成的功能可能只占整个领域模型的10%不到。
      2. 这个是可以的

      • 宋杰

        第2点的意思是:涉及到多个聚合参与协作的,需要使用妥协的领域服务,然后在领域服务里调用多个领域的repository和领域方法是么?

        • 滕云

          这里的用语“调用多个领域的repository“严格来讲应该为“调用多个聚合根的repository”。

          是的,设计到多个聚合根的操作一般建议创建一个领域服务,该领域服务中可以调用多个聚合根的repository,并且调用多个聚合根上的业务方法。

  12. Application Service遵循注意点的其中有一点是“与UI或通信协议无关”,这一点最近一直困扰我很久,关于这些方面的理论我也看到很多。
    假如Application Service定义了比如”HttpService”的interface,由基础设施层来实现这个interface,那么再注入到applicationService中,则application Service就可以操作一些http请求响应的操作了?比如在application service中进行location重定向?

    就比如那最近的一个例子,OAuth2认证,OAuth2认证分两步,第一步是重定向客户端到认证服务器拿code,再是拿code换accessToken去取用户信息

    那么我在一个application service中实现这个“OAuth2认证”用例,中间的重定向操作,岂不是也得在application service中实现?
    我觉得我对这个用例的拆解有问题,是不是应该直接做成“认证”用例,而不是“OAuth2认证”,我通过controller完成前面的重定向和获取accesstoken,然后通过application service获取accesstoken完成认证?

    • 滕云

      如果基于“原教旨主义”,ApplicationService虽然不直接参与业务逻辑的细节,但是依然是用于辅佐某个业务用例的完成,因此诸如“location重定向”这些纯粹的技术性设施,不应该存在于ApplicationService中。

      不过,具体实操上,为了保证与其他请求的处理的一致性,我通常业务有一个OAuth2ApplicationService之类的,里面做的事情是任何用于“认证”的逻辑。在笔者的某个项目中,我们需要做微信的网页授权,和你的情况相似,但是就用了一个叫做WechatAuthApplicationService的类。

  13. 李康宁

    感觉见讲解很清晰,对DDD有了个整体概念的把我,对其中的Aggregate, Entity, Domain, ValueObject, ApplicationService, DomainService, DomainRepresentationService有了清楚的认识。

  14. anthow

    目前仅仅get到贫血模型的坏处,日常编码中也逐渐往充血模型上面靠。本文讲得一些东西还是比较明了的,谢谢~

  15. 越多越少

    在OrderPaymentService的pay方法中,领域服务(OrderPaymentService)依赖了基础设置(支付网关PaymentProxy),这样是不是不符合洋葱架构?
    如果要使用洋葱架构的话, 应该需要这么调整呢?

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据