DDD领域设计战术篇

文章目录

  • 一、什么是DDD
  • 二、领域(Domain)
  • 三、贫血模型、充血模型
  • 四、实体、值对象、领域服务
  • 五、保护领域模型
  • 六、仓库(Repository)

一、什么是DDD

  • 领域驱动设计(Domain-Driven Design),简称DDD。
    DDD并不是一种独立的新的技术体系,它是在传统开发经验基础上总结的一种方法论,在应对复杂程序设计时候很有效。
    通过强调使用充血模型,并结合传统贫血模型,取长补短,提出设计核心 --> 领域服务、实体、值对象。
    而为了保证领域模型的设计不被破坏,提出聚合的划分与聚合根的唯一定义,形成领域边界的松耦合,从而保证领域之间的边界不被打破。
    DDD还抽象出适配层,仓库与工厂可以说是领域中充血模型的一个重要支柱,对于业务代码只需要关注仓库而不需要关注数据库等底层存储,大大降低技术门槛与数据变化成本,

二、领域(Domain)

  • 领域:将真是世界与软件世界联系在一起,以领域划分替代功能模块划分。

三、贫血模型、充血模型

  • 贫血模型:映射的普通类,只有getter、setter方法。不包含任何业务逻辑的类。

  • 充血模型:有赋予业务动作的实体类。
    DDD领域设计战术篇_第1张图片

    贫血模型下的业务变更必然会带来大量的代码变更。
    充血模型描的变更变得简单,模型变更的影响范围变得有效收敛。

    贫血模型与充血模型对业务有不一样的定义。在贫血模型下,业务覆盖增删改查,都会被定义为业务行为。
    而充血模型下,被定义为业务的是有可能引起实体变更的行为,也就是增删改。

四、实体、值对象、领域服务

  • 实体(Entity):代表具有唯一id的领域对象。
    例如:
    订单系统中,一个订单就可以看做一个实体,它可以串联后续的支付、退款、收货等一系列业务中的生命周期。

  • 值对象(Value Object):值对象代表一些一成不变的、本质性的事务。
    例如:
    比如订单中的收货地址,包括地址信息、邮编、收货人姓名、手机号等。
    不论有多少个属性,整体的本质是订单中的一个值。当下订单成功之后,他的值就不能改变,所以,它不需要唯一的id。

  • 服务:服务表示的是在领域对象之外的操作和行为。跨实体的业务操作,交由服务来协调。服务用来隔离业务逻辑与技术实现。

  • 如何确定一个业务是实体还是值对象?
    实体与值对象本质是对真是世界事务可变性的一种抽象。
    首先,实体是一个多变的业务数据,它的每一个属性都具有很强的业务关联,除了id不会变,随着业务的变更其他都会发生改变。而值对象往往依附于实体,才会赋予它真正的业务价值。比如地址信息,只有在订单中,才是会被赋予一个收货地址的业务价值。

    实体与值对象不能完全区分开来,在不同的业务中被赋予不同的含义。

  • 实体与值对象之间的转变
    例如:
    地址信息,在订单中是一个值对象。但是,在用户信息维护中,地址信息又会被赋予实体的概念。

    实体与实体之间通过唯一id进行关联,实体与值对象之间通过信息冗余进行关联。

五、保护领域模型

  • 聚合:是用来确保领域对象在实现共同业务逻辑时,能保证数据一致性。

  • 聚合与聚合根的作用
    在DDD设计思想中,会将领域对象划分在不同的聚合中,在聚合中指定唯一的聚合根,并且约定聚合的依赖关系只能通过聚合根来进行。通过这种方式,将复杂的业务划分成一个一个整体与部分的关系,并且每个部分的变化,被隔离在聚合的内部。从而使系统在面对复杂多变的业务变得相对稳定。

  • 如何判断聚合关系
    判断聚合关系最有效的方式,就是去探讨是否符合整体与部分的关系。在划分聚合关系的时候,就要考虑,如果整体不存在了,那么部分是否存在。如果部分不存在了,那就是聚合关系。反之就不能算是一个聚合。

    例如:
    用户与地址关系。地址在用户领域中划分聚合,就可以被看做是一种聚合,因为地址随着用户不存在了,那么用户的地址就不存在了。
    在看订单与地址关系。订单领域与用户领域中地址划分聚合,这样是不能看做一种聚合的。订单不存在了,那么用户地址是依然存在的。但是,
    在实际中,订单领域中的地址多是值对象,用户领域中的地址是实体。所以,这样来看订单中的地址其实与订单领域可以看做是聚合。

  • 聚合根:每个聚合内部有一个外部访问聚合的唯一入口,成为聚合根,每个聚合根应确定唯一的聚合根实体。聚合根的主要目的是为了防止由于复杂数据模型缺少统一业务规则控制而导致的聚合实体之间的数据不一致的问题。

    例如:
    在用户领域中,要获取订单领域中所有交易的订单详情,就需要从用户领域中,通过订单领域中的聚合根来获取具体的数据,
    而不是直接在用户领域中直接调用关联数据。这样的好处在于,当订单领域中的聚合根发生改变之后,只跟新内部模型,不会影响到外部程序。
    降低了业务变更时的成本。

六、仓库(Repository)

  • 仓库:是为了解耦领域层与数据库存储之间的解耦。仓库负责所有领域对象的管理,当应用需要某个领域对象,只需要从仓库中申请。

    例如
    比如在传统设计中,通过领域直接访问数据库,如果想要在数据库中,做Redis缓存、ES存储、MQ异步存储等各种复杂的存储方案,这样,往往会对我们上层的业务逻辑带来很大的影响。而在DDD思想中,通过抽象出仓库层,不论底层存储如何变化,上层都能得到想要的结果。

你可能感兴趣的:(DDD领域驱动设计,java)