第二十二课:领域建模实战——订单系统最小闭环(实战篇)

在上一篇《领域建模入门》中,我们讲了:

  • Entity
  • Value Object
  • Aggregate
  • Domain Service
  • Bounded Context
  • 统一语言
  • 状态机
  • 规则归属

但如果只停留在概念层面,领域建模很容易变成"看懂却不会用"。

这一篇,我们用一个 最小订单系统闭环

把领域建模从"概念"落到"结构"。

一、实战目标

我们只实现三个功能:

  1. 创建订单
  2. 支付订单
  3. 取消订单

不引入:

  • MQ
  • Redis
  • 微服务
  • 分布式锁

目标只有一个:

看清规则归属,而不是炫技术。

二、业务规则梳理

先从业务说起,而不是从代码说起。

订单规则

  • 创建时必须有金额
  • 未支付可以取消
  • 已支付不能取消
  • 支付后状态变更

你会发现:

这些规则都属于"订单本身"。

这就是 Domain。

三、模块结构设计

复制代码
order
 ├─ domain
 ├─ biz
 ├─ repository
 ├─ api
 └─ dto

四、Domain 层建模

1. Value Object:Money

java 复制代码
public class Money {
    private final BigDecimal amount;

    public Money(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("金额不能为负");
        }
        this.amount = amount;
    }

    public BigDecimal getAmount() {
        return amount;
    }
}

特点:

  • 不可变
  • 无 ID
  • 只代表值

2. Entity:Order

java 复制代码
public class Order {

    private Long id;
    private Money money;
    private OrderStatus status;

    public Order(Money money) {
        this.money = money;
        this.status = OrderStatus.CREATED;
    }

    public void pay() {
        if (status != OrderStatus.CREATED) {
            throw new RuntimeException("当前状态不可支付");
        }
        status = OrderStatus.PAID;
    }

    public void cancel() {
        if (status == OrderStatus.PAID) {
            throw new RuntimeException("已支付订单不能取消");
        }
        status = OrderStatus.CANCELLED;
    }
}

体现点:

  • 状态机
  • 规则归属
  • 行为内聚

3. 状态枚举

java 复制代码
public enum OrderStatus {
    CREATED,
    PAID,
    CANCELLED
}

五、Repository(持久化接口)

java 复制代码
public interface OrderRepository {
    void save(Order order);
    Order findById(Long id);
}

关键点:

Domain 不直接写 SQL。

六、Biz 层(流程编排)

java 复制代码
public class OrderBizService {

    private OrderRepository repository;

    public void createOrder(BigDecimal amount) {
        Order order = new Order(new Money(amount));
        repository.save(order);
    }

    public void payOrder(Long id) {
        Order order = repository.findById(id);
        order.pay();
        repository.save(order);
    }

    public void cancelOrder(Long id) {
        Order order = repository.findById(id);
        order.cancel();
        repository.save(order);
    }
}

Biz 做的事:

  • 串联流程
  • 调用 Domain
  • 持久化

Biz 不做的事:

  • 不判断规则
  • 不计算金额

七、Controller 层(简化示意)

java 复制代码
@RestController
public class OrderController {

    private OrderBizService service;

    @PostMapping("/create")
    public void create(BigDecimal amount) {
        service.createOrder(amount);
    }
}

Controller 只负责:

输入输出,不负责业务。

八、这个实战体现了哪些建模点?

知识点 体现位置
Entity Order
Value Object Money
Aggregate Order
状态机 OrderStatus
规则归属 pay / cancel
Repository OrderRepository
Biz 编排 OrderBizService

九、为什么不加 MQ / Redis?

因为这篇的目标不是"系统复杂度",

而是:

规则清晰度。

一旦加太多技术,读者会迷失。

十、实战结论

你会发现:

Controller 没有业务逻辑

Biz 没有规则判断

Domain 没有 SQL

Repository 没有业务规则

这就是领域建模的落地效果。

十一、实战口诀

可以记这四句:

规则进 Domain

流程进 Biz

数据进 Repository

输入输出给 Controller

做到这四点,

你的系统就从"堆代码"进化为"有结构"。

相关推荐
bksczm几秒前
linux之线程概念和控制
linux·开发语言·c++
SamDeepThinking2 分钟前
Vibe Coding最重要的是Spec
后端·程序员·ai编程
掘金_答案5 分钟前
上线那天,一个 ConcurrentHashMap 差点送走我的 AI 客服——3 天排查 JVM 血泪史
java·后端·架构
妙码生花10 分钟前
从 PHP 到 AI + Golang,程序员自救转型手记(三十三):权限规则管理器
后端·go·gin
JackieZhengChina33 分钟前
零依赖轻量级JS悬浮提示插件title2tip-js的使用教程
开发语言·javascript·ecmascript
MindUp37 分钟前
企业网盘权限模型解析:多层级访问控制与审计能力选型指南
java·linux·运维
Kim_wang41 分钟前
agent项目部署流程
人工智能·后端
NG4771 小时前
【软件设计与体系结构】-策略设计模式
java·设计模式·软件工程
程序员天天困1 小时前
优雅记录操作日志:从注解到 SpEL 的全链路实践与开源方案对比
java·后端
战血石LoveYY2 小时前
Integer类型超限,导致数据异常
java·算法