DDD 之 实体和值对象

255 阅读2分钟

DDD是反对贫血模型的,所以最后需要在实体里加入复杂的行为方法,这个是极为关键的一个变化。 国内传统的软件架构:数据库表 -> domain -> mapper/sql -> dao -> service -> controller -> 各种接口,这就是贫血模型。

本质是在面向过程开发,程序拆分为 domain 贫血数据 + 三层架构的行为。

(1)实体和值对象

实体的特征:

  1. 唯一标识,对唯一性事物进行建模

  2. 包含了业务的关键行为,可以随着业务持续变化

  3. 修改时,因为有唯一标识,所以还是同一个实体

值对象的特征:

  1. 描述事物的某个特征,通常作为实体属性存在(没有 Id 等标识)
  2. 创建后即不可变
  3. 修改时,用另一个值对象予以替换

public class Order {

    private Long orderId;
    private BigDecimal amount;
    private Address address;
    private List<OrderItem> orderItems;

    /**
     * 更新收获地址
     *
     * @param address 地址
     */
    public void updateAddress(Address address) {
        this.address = address;
    }

    /**
     * 更新订单条项
     *
     * 1. 找到对应订单条项
     * 2. 计算总价
     *
     * @param orderItem 订单条项
     */
    public void updateOrderItems(OrderItem orderItem) {
        // ...
    }
}

class Address {
    private String name;
}

class OrderItem {
    private String orderId;
    private BigDecimal price;
}

(2)聚合

将实体和值对象在一致性边界之内组成合,使用聚合划分限界上下文(微服务)内部的边界,聚合根做为一种特殊的实体,用于管理聚合内部的实体与值对象,并将自身暴露给外部进行引用。

聚合是由多个实体以及值对象组合而成的一个关系,在 DDD 里,一个 Aggregate 都会有一个 root entity,根实体。

举个栗子:

聚合要保持小型,聚合之间通过 id 标识来引用,不要进行面向对象的组合。

(3)战略设计和战术设计

战略设计:划分子系统以及确定子系统集成方式

战术设计: 建表+设计 domain

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情