ddd

领域对象(Domain Object)

  • 领域模型对象(Domain Model Object)
  • 资源库(Repository)
  • 领域事件(Domain Event)
  • 应用服务所涉及到的命令(Command)
  • 查询(Query)对象

角色

  • 数据模型:面向持久化,数据的载体。
  • 领域模型:面向业务,行为的载体。
  • 视图模型:面向UI(向外),数据的载体。
  • 命令模型:面向UI(向内),数据的载体。

领域模型

  • 实体:包含数据,可对数据进行赋值
  • 值对象:包含数据,只能new,不可更改其值
  • 聚合根:聚合根也是实体,但包含其它实体和值对象,并有对应的业务逻辑。在聚合根里,不能和其它系统(DB、RPC等)有交互

名词解释

  • ACL:防腐层(Anticorruption Layer,ACL)
  • UP:统一协议(Unified Protocol,UP)
  • EDA:事件驱动架构(Event-Driven Architecture,EDA)
  • CQRS:的全称是 Command Query Responsibility Segregation,也就是命令和查询职责分离
  • CRUD:增加(Create)、检索(Retrieve)、更新(Update)和删除(Delete)
  • DMO:领域模型对象(Domain Model Object)
  • AOP:切面
  • DMO:领域模型对象(Domain Model Object),聚合根、实体、值对象
  • DO:领域对象(Domain Object),包含领域模型对象(Domain Model Object)、资源库(Repository)、领域事件(Domain Event)以及应用服务所涉及到的命令(Command)和查询(Query)对象
  • PO:资源库实现部分所对应的数据对象称为是一种持久化对象(Persistence Object,PO)
  • DM:数据映射器(Data Mapper) 的概念。映射(Mapping)思想在软件设计过程中非常常用,主要用于分离不同层次之间的数据耦合。对于数据访问而言,数据映射器的作用在于分离领域对象和持久化媒介。
  • VO(View Object)视图对象:和视图打交道的,那么经历了视图的都归属于这个类,所以我们的输入输出类都是属于VO
  • DTO(Data Transfer Object)数据传输对象:我们sql查询的时候是通过Id查询的,但是查询是可以查询出很多条信息的,但是我们给前端的数据只要某一部分,比如上例有4个属性,但是只要求输出3个。
  • DAO:Data Access Object,数据访问对象1.用来封装对数据库的访问(CRUD)2.通过接收Business层的数据,将POJO持久化为PO
  • BO( Business Object):业务对象。由Service层输出的封装业务逻辑的对象。

CQRS

将 command 与 query 分离的一种模式
https://martinfowler.com/bliki/CommandOrientedInterface.html
CQRS 将系统中的操作分为两类,即命令(Command) 与查询(Query)。命令则是对会引起数据发生变化操作的总称,即我们常说的新增,更新,删除这些操作,都是命令。而查询则和字面意思一样,即不会对数据产生变化的操作,只是按照某些条件查找数据
当 command 系统完成数据更新的操作后,会通过「领域事件」的方式通知 query 系统。query 系统在接受到事件之后更新自己的数据源。所有的查询操作都通过 query 系统暴露的接口完成。

ACL

一个上下文通过一些适配和转换与另一个上下文交互


image.png

防腐层是一种在不同应用间转换的机制。创建一个防腐层,以根据客户端自己的领域模型为客户提供功能。该层通过其现有接口与另一个系统进行通信,几乎不需要对其进行任何修改。
在不共享相同领域模型的不同子系统之间实施防腐层(或外观或适配器层),此层转换一个子系统向另一个子系统发出的请求。 使用防腐层(Anti-corruption layer)模式可确保应用程序的设计不受限于对外部子系统的依赖。 防腐层(Anti-corruption layer)模式最先由 Eric Evans 在 Domain-Driven Design(领域驱动的设计)中描述。
因此,防腐层隔离不仅是为了保护自身领域模型免受其他领域模型的代码的侵害,还在于分离不同的域并确保它们在将来保持分离。

EDA

  1. 当类或组件之间内聚性很高,它们的耦合度应该很低,也就是说当组件需要相互协作调用时,比如我们假设一个组件“A”需要触发组件“B”中的一些逻辑,自然的方式是直接让组件A调用组件B中的一个方法。但前提是A必须知道B的存在,这样它们之间就是耦合的,A必须依赖于B了,这会使得系统更难以改变和维护。因此,这里可以使用事件来防止这种直接调用的耦合。
  2. 此外,使用事件实现组件解耦也有其另外的,如果我们有一个只负责组件B的工作团队,那么他们则可能不需要与负责组件A的团队进行交流,直接针对组件A中的逻辑改变在组件B中做出相对反应。两个组件团队可以独立发展, 我们的应用系统变得更灵活。
  • 去耦组件
    当组件A执行的逻辑需要触发组件B的逻辑时,不要直接调用它,我们可以将触发事件发送到事件分派器。组件B将侦听调度程序中的特定事件,并在事件发生时执行操作。
    这意味着A和B都将取决于调度器和事件,但他们之间将不会知道对方存在,它们将被解耦。
    理想情况下,调度员和事件都不应该在两个组件之间存在:
    (1)调度员应该是完全独立于我们应用程序的库,因此使用依赖管理系统安装在通用位置。
    (2) 事件是我们的应用程序的一部分,应该在两个组件之间生存,组件之间通过事件进行通讯(结构上解耦,行为上耦合)。事件在组件之间共享,它是应用程序的核心部分。事件在DDD中属于共享内核Shared Kernel的一部分。这样,两个组件都将依赖于共享内核,但彼此不会意识到。然而在单体Monolithic应用程序中,为方便起见,可以将其放在触发事件的组件中。
    DDD共享内核

    • 明确界定指定团队同意分享的领域模型的一些子集。保持这个内核很小。
    • 这个明确共享的东西有特殊的地位,如果没有与其他团队协商,不应该改变。
  • 执行异步任务
    有时候我们有一个我们想要执行的逻辑,但它可能需要相当长的时间来执行,我们不想让用户等待它完成。在这种情况下,希望将其作为异步工作运行,并立即返回给用户的消息,通知他请求将在以后异步执行。
    例如,在网上商店下订单可以同步完成,但发送通知用户的电子邮件可以进行异步。
    在这种情况下,我们可以做的是触发一个将被排队的事件,直到一个工作任务可以获得这个事件并执行它,只要系统有资源。
    在这些情况下,相关联的逻辑是否在相同的有界环境中并不重要,无论哪种方式,逻辑都是去耦的。

  • 跟踪状态变化(审计日志)
    以传统的数据存储方式,我们拥有一些数据的实体。当这些实体中的数据发生变化时,我们只需更新数据库表行以反映新值。
    这里的问题是,我们并不存储这些值为什么改变且什么时候改变。
    我们可以将这些改变的事件存储在审计日志中。
    更多关于这个进一步的前景,在关于事件溯源的解释。
    Martin Fowler确定了三种不同类型的事件模式:

    • 事件通知
    • 事件执行状态转移
    • 事件溯源Event Sourcing

    所有这些模式共享相同的关键概念:

    • 事件是代表发生了一些事情(发生在某事之后)
    • 事件被广播到正在监听的任何代码(代码可以对事件做出反应)

DMO

和数据模型区分开即可

参考

  • 《实现领域驱动设计》- 沃恩·弗农
  • 《领域驱动设计——软件核心复杂性应对之道》- Eric Evans

你可能感兴趣的:(ddd)