DDD实战课
欧创新
人保高级架构师
立即订阅
4865 人已学习
课程目录
已完结 23 讲
0/2登录后,你可以任选2讲全文学习。
开篇词 (1讲)
开篇词 | 学好了DDD,你能做什么?
免费
基础篇 (5讲)
01 | 领域驱动设计:微服务设计为什么要选择DDD?
02 | 领域、子域、核心域、通用域和支撑域:傻傻分不清?
03 | 限界上下文:定义领域边界的利器
04 | 实体和值对象:从领域模型的基础单元看系统设计
05 | 聚合和聚合根:怎样设计聚合?
进阶篇 (6讲)
06 | 领域事件:解耦微服务的关键
07 | DDD分层架构:有效降低层与层之间的依赖
08 | 微服务架构模型:几种常见模型的对比和分析
09 | 中台:数字转型后到底应该共享什么?
10 | DDD、中台和微服务:它们是如何协作的?
答疑:有关3个典型问题的讲解
实战篇 (10讲)
11 | DDD实践:如何用DDD重构中台业务模型?
12 | 领域建模:如何用事件风暴构建领域模型?
13 | 代码模型(上):如何使用DDD设计微服务代码模型?
14 | 代码模型(下):如何保证领域模型与代码模型的一致性?
15 | 边界:微服务的各种边界在架构演进中的作用?
16 | 视图:如何实现服务和数据在微服务各层的协作?
17 | 从后端到前端:微服务后,前端如何设计?
18 | 知识点串讲:基于DDD的微服务设计实例
19 | 总结(一):微服务设计和拆分要坚持哪些原则?
20 | 总结(二):分布式架构关键设计10问
结束语 (1讲)
结束语 | 所谓高手,就是跨过坑和大海!
DDD实战课
登录|注册

答疑:有关3个典型问题的讲解

欧创新 2019-11-06
你好,我是欧创新。
截至今天这一讲,我们的基础篇和进阶篇的内容就结束了。在这个过程中,我一直有关注大家提的问题。那在实战篇正式开始之前啊,我想针对 3 个比较典型的问题,做一个讲解,希望你也能同步思考,调动自己已学过的内容,这对我们后面实战篇的学习也是有一定帮助的。
问题 1:有关于领域可以划分为核心域、通用域和支撑域,以及子域和限界上下文关系的话题,还有是否有边界划分的量化标准?
我在 [第 02 讲] 中讲到了,在领域不断划分的过程中,领域会被细分为不同的子域,这个过程实际上是将问题范围不断缩小的过程。
借用读者“密码 123456”的总结,他认为:“对于领域问题来说,可以理解为,对一个问题不断地划分,直到划分为我们熟悉的、能够快速处理的小问题。然后再对小问题的处理排列一个优先级。”
这个理解是很到位的。在领域细分到一定的范围后,我们就可以对这个子域进行事件风暴,为这个子域划分限界上下文,建立领域模型,然后就可以基于领域模型进行微服务设计了。
虽然 DDD 没有明确说明子域和限界上下文的关系。我个人认为,子域的划分是一种比较粗的领域边界的划分,它不考虑子域内的领域对象、对象之间的关系和结构。子域的划分往往按照业务阶段或者功能模块边界进行粗分,其目的就是为了让你能够在一个相对较小的问题空间内,比较方便地用事件风暴来梳理业务场景。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《DDD实战课》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(16)

  • 张迪
    基础层依赖领域层。能录个例子吗?如何反转依赖的,还是不明白

    作者回复: 一个非常简单的例子,有Person聚合根,Person仓储接口和仓储实现。
    /**
     * Person聚合根
     */
    public class Person{
      private String id;
      private String name;
      private int age;
      private boolean gender;
    }

    /**
     * Person仓储接口
     */
    public interface PersonRepositoryInterface {
      void save(Person person);
      void delete(String id);
     }

    /**
     *Person仓储实现
     */
    @Repository
    public class PersonRepositoryImp implements PersonRepositoryInterface {
      private PersonMapper mapper;
      public void save( Person person) {
          mapper.create(person);
      }
      public void delete((String id) {
        mapper.delete(id);
      }
     }
    在应用逻辑中直接用仓储的接口就可以了,数据库相关的逻辑在PersonMapper里面实现。
    PersonRepositoryInterface personRepos;
    personRepos.save(person)

    2019-11-07
    2
    5
  • 吃饭饭
    事件风暴?为什么一有关键词总会出现这个,它不就是一个集中讨论定需求的动作?陌生词汇太多,如果夹杂一些白话最好了,感觉这一套字眼真的是越说越迷糊了,DDD 我感觉说白了就是一种划分手段,核心最终都会落在为服务上
    2019-11-06
    1
    5
  • 祥敏
    您好,领域层提供仓储接口,基础层实现仓储接口,依赖倒置的设计是非常好的,能够拆除领域层对基础层的依赖。
    上层向下依赖领域层,领域层通过依赖倒置,让基础层也依赖领域层,这样就实现了领域层为核心的设计理念。
    领域驱动设计提出了全新的设计思路,讲述偏抽象,重点在如何落地,期待实战篇。
    2019-11-06
    3
    3
  • 陈华应
    老师,实体内可以调用他所在聚合的仓储吗?

    作者回复: 一般通过聚合根来做。

    2019-11-06
    2
  • Jade
    事件总线 实现思路?用到什么技术或来源组件?还是说事件总线就是消息队列呢

    作者回复: 事件总线就是一个带发布和监听功能的jar包,直接跟你的微服务代码放一起就行了,它属于基础层的代码。提的比较多的是EventBus。你可以去网上找找资料。

    2019-11-06
    3
    2
  • 张迪
    微服务内不使用事件总线,如何保证两个聚合操作的一致性?

    作者回复: 这个需要权衡,看看引入事件总线后,这个复杂度可不可以接受。通过应用服务加事务机制应该也可以解决,在同一个进程内的事务应该比跨微服务的事务相对来说还是好控制,对性能影响也会小一些吧。

    2019-11-07
    1
  • zj
    提个问题,接口层是DTO,应用层是DO,那在接口层将DTO将DTO转换成DO是否会用到工厂模式来转换实体,工厂依赖仓储查询实体依赖数据。因为有些时候DTO要想转换成DO可能需要通过仓储来查询依赖属性的吧?

    作者回复: 工厂模式一般用于比较复杂的聚合的数据初始化。仓储一般是PO和DO之间的转换。
    DTO和DO之间一般都是应用层与外部,比如前端或者其它微服务之间的转换,转换过程一般不会太复杂,直接转换就可以了。

    2019-11-27
    1
  • 观弈道人
    事件风暴与头脑风暴究竟啥区别?

    作者回复: 事件风暴是领域建模的手段,头脑风暴是事件风暴中梳理业务场景和旅程的一种交流方式。详细信息你可以了解一下实战篇的第12节。

    2019-11-21
  • 夙梦流尘
    有个问题想请教下。现在A聚合里面有B、C实体,是通过A的主键去关联的(我知道这样不好但是目前老项目就是这么搞的,重新定义实体标识风险有点大)。导致现在我用工厂创建A聚合的话,要先把A的数据落地,才能拿到A的主键,然后才能创建A聚合里的BC实体。这样的话只能 1.在工厂里就把A落地,然后填充BC实体返回完整聚合。2. 工厂只返回A聚合,然后在填充BC实体。这样工厂就没返回一个完整聚合。
    这两种我觉得都不好,麻烦指导下

    作者回复: A的主键是由数据库的序列号生成的吗?
    如果是这样,在A的方法里面增加一个生成主键的方法呢。这样就可以在形成PO前,拿到所有实体的数据了。

    2019-11-21
  • 宝宝太喜欢极客时间了
    仓储层跟传统的dao层感觉没啥区别?

    作者回复: 仓储只是一种应用和数据库解耦的手段,它是一种手段和方法,传统架构也是可以用的。

    2019-11-11
  • 瓜瓜
    使用充血模型,比如RPC的接口包,接口包的实体为充血模型,该实体的很多功能需要引用很多第三方jar包,这样会不会导致接口包很沉重,比如说一个图片上传服务,客户端和服务端交互是通过图片实体来进行交互的,而图片的下载和上传是属于图片实体的内部功能,这样图片实体就会引用apahce.httpclient的很多jar包,该怎样解决这个问题呢

    作者回复: 你这种方式可能就不适合充血模型了。
    DDD用充血模型的主要目的是为了在领域模型中体现实体的业务行为,而不是所有实体的行为混杂在一起。但是这只是一个建议的设计原则,贫血模型有时候也是不可避免的。

    2019-11-07
    1
  • Paul Yao
    老师,您好!有一些设计实现上的疑问:
    领域服务的CRUD是不是都是操作聚合根或整个实体对象,比如我只想根据ID判断记录是否存在,或者返回个别字段,需要返回整个实体对象吗?

    作者回复: 其实查询类业务可以不必经过聚合根和仓储。传统方法也可以了。
    如果聚合数据比较多,会有延迟加载影响性能。
    聚合根的主要目的是为了保证数据的一致性,这些场景一般在CU的场景。

    2019-11-07
  • 陈华应
    工厂创建出实体或者是聚合跟之后再加到仓储中吗(持久化)?

    作者回复: 创建完后会初始化数据,变更后的数据会通过仓储持久化。

    2019-11-06
  • 小明
    之前提过这个问题,基础依赖领域的仓储接口,领域不还得依赖基础层的通用组件吗?这不循环依赖了吗。

    作者回复: 用仓储的目的是为了隔离相互影响。
    你说的这种情况我理解是从哪里调仓储接口的问题吧,比如一个基础层组件A依赖领域层,另一个基础层组件B,依赖基础层组件A,然后B只能从领域层仓储接口调A的接口,不知道理解的对不对哈?
    其实在微服务内只要你能够做好代码逻辑隔离,仓储接口放哪里都无所谓。
    这样设计只是考虑大部分的情况,为了让代码更清晰一些,毕竟大部分的数据仓储的服务都是从领域层发起的。

    2019-11-06
  • FIGNT
    讲的很精简,把《实现领域驱动设计》的主要内容讲的很清楚了。但是还是很抽象的,关键还是要实战,加深理解
    2019-11-06
  • 密码123456
    感觉有点像,设计模式中核心的一句话。封装变化。变化是无穷的,但是我们尽可能的把,变化引起的改动降到最小。
    2019-11-06
收起评论
16
返回
顶部