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

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

  • 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

做到这四点,

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

相关推荐
Moment1 天前
Vibe Coding 时代,到底该选什么样的工具来提升效率❓❓❓
前端·后端·github
Victor3561 天前
MongoDB(27)什么是文本索引?
后端
可夫小子1 天前
OpenClaw基础-3-telegram机器人配置与加入群聊
后端
IT_陈寒1 天前
SpringBoot性能飙升200%?这5个隐藏配置你必须知道!
前端·人工智能·后端
aiopencode1 天前
使用 Ipa Guard 命令行版本将 IPA 混淆接入自动化流程
后端·ios
掘金者阿豪1 天前
Kavita+cpolar 打造随身数字书房,让资源不再混乱,通勤 、出差都能随心读。
后端
心之语歌1 天前
Spring Security api接口 认证放行
后端
用户8356290780511 天前
Python 实现 PPT 转 HTML
后端·python
0xDevNull1 天前
MySQL索引进阶用法
后端·mysql
舒一笑1 天前
程序员效率神器:一文掌握 tmux(服务器开发必备工具)
运维·后端·程序员