• 陈 争
    2019-11-13
    不知道我这样理解的对不对
    比如执行一个创建用户的命令,
    1.用户接口层:
      1.1)Assembler->将CustomerDTO转换为CustomerEntity
      1.2)Dto->接收请求传入的数据CustomerDTO
      1.3)Facade->调用应用层创建用户方法
    2.应用层
      2.1)Event->发布用户创建事件给其它微服务
      2.2)Service:
        内部服务->创建用户
        外部服务->创建日志
    3. 领域层
      3.1)Aggregate->进入用户聚合目录下(如:CustomerAggregate)
      3.2)Entity->用户聚合跟
      3.3)Event->创建用户事件
      3.4)Service->具体的创建用户逻辑,比如用户是否重复校验,分配初始密码等
      3.5)Repository->将用户信息保存到数据库
    展开

    作者回复: 是的,就是这样的。理解的很到位。

     2
     13
  • xj_zh
    2019-11-18
    老师,求DDD的系统样例代码。

    作者回复: 代码样例还没准备好,后面我找时间整理一下吧。

    
     7
  • Farewell丶
    2019-11-13
    1.应用服务只能调用领域服务和实体的方法,能调用仓储接口的方法么?
    按理说应该隔离,也就是说应用服务应该调用领域服务的方法,再让领域服务调用仓储接口的方法吧?

    2.实体的转换只有从用户接口层到应用服务层一次是么?也就是说,到应用服务层之后,以及之后的仓储接口都是可以直接对领域实体进行操作的?

    3.参考了Spring Data Jdbc项目,里边也采用了DDD的设计思路,但是发现会需要在实体中配置一些和底层存储相关的注解,这样会不会不能把领域层可仓储实现进行隔离?如果是这样的化,那么Spring Data Jdbc是不是没有严格遵守DDD的一些设计?而且它提供的领域事件的发布机制实现,是在对应的实体中产生的,例如在某一个实体中定义产生领域事件的源头,当对应的实体保存或更新时,就会发出这样一个领域事件。按照咱们文章中讲解的事件的发布是在应用层,那么如果要这样做的话,是不是就需要在应用层重新转发领域层实体内产生的领域事件呢?
    因为看到Spring Data这样比较广泛的项目实现和咱们文章的描述有一些我理解上的区别,所以比较困惑和疑问。
    展开

    作者回复: 1、如果是应用服务直接调用文件或者缓存之类的,应用服务是可以之间调用仓储的。但如果中间有领域实体和数据库,则需通过领域服务,然后通过聚合根来调用仓储。
    2、用户接口层大多是DTO,应用层和领域层大多是DO,基础层则是PO,在不同层之间是需要进行数据转换的。我有一节专门讲这个。
    3、如果是这样的话,确实领域层与数据库层会有耦合。领域事件其实放领域层也是可以的,放应用层主要是为了统一管理。如果领域事件放在实体内部,查找和运维起来就不是太方便,而且这个实体还需要对领域事件的实体进行操作。目录结构的设计主要是从边界、分层和便利性考虑的。

    
     2
  • zj
    2019-11-21
    请教一个问题,考虑这样一个场景,主播账户作为一个聚合,优惠券模块作为一个聚合。那主播选券这个命令是不是应该属于主播账户这个聚合里。然后主播账户里的优惠券是不是就是这个聚合里的值对象了

    作者回复: 可以这样设计的。

     1
     1
  • 杨杰
    2019-11-18
    关于微服务的用户接口层和应用层有点儿疑问。在整个微服务架构里面一般微服务上层还有BFF层、聚合服务层,一般BFF层或聚合服务层用来协调多个微服务或者做数据转换。那么对于某个具体的微服务是否还需要用户接口层和应用层的区分呢?如果DTO是在用户接口层,那么这些数据如何传入到应用服务层呢?

    作者回复: 你可以这样定位。微服务内的应用层主要处理自己的逻辑编排,bff主要处理微服务之间的逻辑。

    
     1
  • FIGNT
    2019-11-14
    我们在设计领域模型时,遇到一些问题
    1. 查询聚合的操作应该放在哪一层?
    2. entity的实体和值对象太多需要分目录吗?
    3. 针对实体的维护,需要通过聚合去维护吗?可以直接修改实体吗?
    4. 一个聚合保存在一个库里,还是多个聚合都在一个库里?一个实体需要单独放一个库吗?如果一个实体被修改了。用到这个实体的聚合需要更新吗?
    5. 聚合是设计成单个的还是批处理的?比如一棵树,业务上是以一片叶子为单位的,那么是以树为聚合还是以叶子为聚合?
    展开

    作者回复: 1、个人感觉批量大数据量的查询用仓储有点勉强,你可以用传统的方式来做。如果不涉及到领域逻辑的话,可以放应用层。
    2、一个微服务的聚合内部应该不会有太多的实体和值对象吧。在目录结构里面是一个聚合一个代码目录。当然如果实在太多,你是可以再分目录的。
    3、聚合内的实体数据维护是通过聚合根通过仓储来统一维护的。
    4、一个微服务一个库,微服务内的多个聚合可以共用一个库,但是尽量避免聚合之间的表关联,聚合之间的数据要做到松耦合。
    5、不清楚你说的单个和批处理是什么意思?聚合是具有一个完整业务功能的单位,就看你业务的粒度大小。多个不同功能的聚合是可以构成一个比较大的业务模块。

    
     1
  • 瓜瓜
    2019-11-13
    还有这个依赖倒置,一开始感觉很清晰,现在感觉越看越懵,老师能给再解答下吗?

    作者回复: 我在你的上个问题回复了,不知道解答你的问题了没有。不知道你的疑问在哪里?如果没解答清楚,麻烦告诉一下你的疑惑在哪里哈。

     1
     1
  • 包子
    2020-01-09
    您好老师,有个疑问。

    聚合如果做了数据切片,比如账户的聚合acc001和acc002的数据库做客分库分表。那么在应用层发起一个转账请求就会出现分布事务问题,这种情况怎么解决呢?

    作者回复: 数据是水平切分吧,是不是这样切分后就会跨业务单元调用或者说跨中心调用?
    这样的业务单元实际是不同的微服务了,你需要在应用层去做分布式事务控制,或者不同的业务单元之间用消息机制也可以。不知道我对你的场景理解的对不对?

     1
    
  • 燕羽阳
    2020-01-03
    在《实现领域驱动设计》这本书中,Demo(https://github.com/VaughnVernon/IDDD_Samples)。
    会倾向于:在application中调用repository, 领域实体和领域服务是不应当调用repository的,这样领域层会保持独立。在实际写代码的过程中,发现这样代码写比较麻烦。
    老师能在详细对比讲讲,对repository和第三方接口依赖的情况,在哪一层处理么?

    作者回复: 是的,我感觉对应复杂的聚合在领域服务中调用repository比较顺手。第三方接口我建议放在应用服务中处理,应用服务主要对服务进行组合和编排。

    
    
  • Geek_45ddff
    2020-01-02
    一个聚合的实体,他的持久化在实体内部完成,还是在领域服务完成,还是应用服务完成

    作者回复: 都可以实现。但建议放在领域服务或者实体方法中。由于聚合的持久化是将所以聚合内对象作为一个整体操作,建议采用工厂和仓储模式,在领域服务中实现。

    
    
  • Jerry银银
    2019-12-30
    我的理解是各个不同的微服务应该是共享一套infrastructure的吧?如果是的话,代码结构是不是不应该这样?

    作者回复: 这里的基础层应该与基础层的技术组件有些差异。比如数据库、api网关之类的基础组件是单独部署而且可能是很多微服务共享的。这里的基础层更多的是偏向于应用与这些基础组件的交互相关的内容,比如组件驱动以及适配相关的代码等内容。

     1
    
  • Jerry银银
    2019-12-30
    请教一下老师:客户端开发中,存在着UI层,那UI层的代码也放在哪儿呢?

    作者回复: 微服务架构下前后端分离,前端会有自己的工程的。

     1
    
  • 东方奇骥
    2019-12-16
    Controller, Service, Repository。Controller相当于用户接口层里的Facade???由于采用了充血模型,之前三层模型中的Service的业务逻辑被封装在了domain的各个聚合下的实体之中。如果需要使用到多个实体来完成某个操作,就要使用聚合中的service.

    作者回复: 是这样的。

    
    
  • 嘉嘉☕
    2019-12-07
    老师好!
    请问,
    同一个微服务内, 跨领域的方法调用, 我们可以在应用层进行组合和编排,
    那么,
    微服务间的领域方法调用是怎样的呢 ?
    被调用者, 方法是从哪一层暴露出去的 ?
    调用者, 是从哪一层发起调用请求的 ?
    谢谢!
    展开

    作者回复: 是从应用层发起的。方法是逐层封装,一直到应用服务。微服务内应尽量避免领域服务在不同聚合之间的调用,这样聚合之间耦合度会比较高。

    
    
  • OTM
    2019-12-06
    如果在接口层需要返回:用户名称,积分数,卡券数,向后续应用层传递的不一定是领域对象 返回的业不一定是具体领域,可能是一个聚合服务,那这里返回的对象应该再那里定义,应用层,还是接口曾

    作者回复: 在接口层定义DTO对象。数据可能来源于多个DO对象。

     1
    
  • Geek_aa8017
    2019-12-05
    老师,跨微服务调用用的是dubbo, dubbo暴露的接口应该定义在哪里

    作者回复: 用户接口层就是用来封装应用服务和对外暴露接口的。

     4
    
  • 瓜瓜
    2019-12-03
    Entity(实体):它存放聚合根、实体、值对象以及工厂模式(Factory)相关代码;此处的工厂模式,主要是来实现实体吗??这块理解的不是很清晰,望老师帮忙解答。感谢!

    作者回复: 工厂模式主要是实现复杂聚合的实体的数据初始化。如果实体太多,聚合根处理起来会很复杂,通过工厂一次初始化。

    
    
  • vivi
    2019-11-26
    老师,像COMMAND,QUERY 层这种CQRS的什么场景下使用呢?

    作者回复: 大量复杂查询的场景下使用。DDD不擅长大量数据查询。其实CQRS查询也可以在同一个微服务内。数据分库也可以,但数据实时性不好保证。

    
    
  • 陈云
    2019-11-17
    有一个细节,想问下是如何处理的,接口层接收到的DTO对象,里面的字段跨多个DO,你没办法将一个DTO 完全转成一个DO,这里可能一个DTO的一些字段压根DO里就没有,这个时候 如果 从接口层 传到应用层,再传到 领域层?再封装一个VO对象?然后这个VO对象 是属于领域层?

    作者回复: 不同的对象在不同的层转换。用户接口层DTO和DO转换,应用层主要是DO,调外部微服务的服务的时候应用层有dto和do的转换。领域层与基础层之间,在基础层有DO和PO的转换。

    
    
  • 小美
    2019-11-15
    今天的文章中写到应用层编排领域服务和外部服务。领域服务可以直接调用外部服务吗?比如一项业务是先根据实体组装调用参数,然后调用外部服务,再根据结果更新前面实体的状态,那这项业务是由领域服务整体实现?还是由应用层来编排,调实体获取参数,调外部服务,调实体更新状态?

    作者回复: 对外还是尽量靠应用服务来实现。
    领域服务也不是不能做,要考虑耦合和对核心逻辑的影响,综合考虑成本吧。

    
    
我们在线,来聊聊吧