当前位置: 首页 > news >正文

DDD领域驱动与传统CRUD

DDD 是一套 应对复杂业务系统 的设计方法论,核心是 让代码直接映射业务逻辑,避免技术实现与业务需求脱节。
关键区别

  • 传统开发:根据数据库表写 CRUD(技术驱动)。
  • DDD:根据业务行为建模(业务驱动)。

举例

  • 传统方式:设计 orders 表 → 写 OrderDAO → 实现增删改查。
  • DDD 方式:先分析业务如何描述“订单”(如“下单”、“取消”、“支付超时”)→ 再建模为 Order 对象的行为。

贫血模型与充血模型

本质特征

特征贫血模型充血模型
业务逻辑存放位置Service层领域对象(Entity/Value Object)内部
领域对象职责仅作为数据载体(DTO)封装数据和行为
代码表现大量Getter/Setter,无业务方法包含业务方法
适用场景简单CRUD系统复杂业务系统(DDD推荐)

代码实现对比

贫血模型实现

  • Order 只是数据的容器,业务逻辑散落在 Service 中。
  • 当业务复杂时,Service 会变成“上帝类”(God Class)。
// 1. 贫血的Order类(仅有数据)
public class Order {private String orderId;private String productId;private int quantity;private String status;// 只有Getter/Setter,无业务逻辑public String getOrderId() { return orderId; }public void setOrderId(String orderId) { this.orderId = orderId; }// 其他Getter/Setter省略...
}// 2. 业务逻辑全在Service中
@Service
public class OrderService {public void createOrder(String productId, int quantity) {Order order = new Order();order.setOrderId(UUID.randomUUID().toString());order.setProductId(productId);order.setQuantity(quantity);order.setStatus("CREATED");// 校验逻辑也在Service中if (quantity <= 0) {throw new IllegalArgumentException("Quantity must be positive");}orderRepository.save(order);}
}

充血模型实现

  • Order 自己负责业务规则(如创建校验、状态转换)。
  • 业务逻辑高内聚,Service层变薄。
// 1. 充血的Order类(封装数据和行为)
public class Order {private String orderId;private String productId;private int quantity;private OrderStatus status; // 枚举// 私有构造方法,强制通过工厂方法创建private Order(String productId, int quantity) {this.orderId = UUID.randomUUID().toString();this.productId = productId;this.quantity = quantity;this.status = OrderStatus.CREATED;}// 静态工厂方法(封装创建逻辑)public static Order create(String productId, int quantity) {if (quantity <= 0) {throw new IllegalArgumentException("Quantity must be positive");}return new Order(productId, quantity);}// 领域行为public void cancel() {if (this.status == OrderStatus.PAID) {throw new IllegalStateException("Paid order cannot be cancelled");}this.status = OrderStatus.CANCELLED;}
}// 2. 应用层Service(仅协调流程)
@Service
public class OrderAppService {public void createOrder(String productId, int quantity) {Order order = Order.create(productId, quantity); // 调用领域对象orderRepository.save(order);}
}

DDD实战

架构图

架构设计

src/
├── presentation/    # 用户接口层
├── application/     # 应用层
├── domain/          # 领域层
│   ├── model/       # 领域模型(实体、值对象等)
│   └── repository/  # 仓储接口
└── infrastructure/  # 基础设施层(简单实现)

代码示例

(1) 用户接口层(Presentation Layer)

处理HTTP请求,接收用户输入。

// presentation/OrderController.java
@RestController
@RequestMapping("/orders")
public class OrderController {private final OrderAppService orderAppService; // 依赖应用层@PostMappingpublic ResponseEntity<String> createOrder(@RequestBody CreateOrderRequest request) {orderAppService.createOrder(request.toCommand()); // 转换为命令对象return ResponseEntity.ok("Order created");}
}// DTO:用户请求参数
public class CreateOrderRequest {private String productId;private int quantity;// 转换为应用层命令对象public CreateOrderCommand toCommand() {return new CreateOrderCommand(productId, quantity);}
}

(2) 应用层(Application Layer)

协调领域对象完成用例,不包含业务逻辑

// application/OrderAppService.java
@Service
public class OrderAppService {private final OrderRepository orderRepository; // 依赖领域层仓储public void createOrder(CreateOrderCommand command) {// 1. 调用领域层创建订单Order order = Order.create(command.getProductId(), command.getQuantity());// 2. 通过仓储保存聚合根orderRepository.save(order);// 3. 可发布领域事件(此处省略)}
}// 应用层命令对象
public class CreateOrderCommand {private String productId;private int quantity;// 构造方法、getter省略...
}

(3) 领域层(Domain Layer)

核心业务逻辑,包含实体、值对象、仓储接口等。

3.1 实体(Entity)与聚合根
// domain/model/Order.java
public class Order {private String orderId;      // 唯一标识private String productId;private int quantity;private OrderStatus status;  // 枚举:CREATED, PAID, CANCELLED等// 私有构造方法,强制通过工厂方法创建private Order(String productId, int quantity) {this.orderId = UUID.randomUUID().toString();this.productId = productId;this.quantity = quantity;this.status = OrderStatus.CREATED;}// 工厂方法(封装创建逻辑)public static Order create(String productId, int quantity) {if (quantity <= 0) {throw new IllegalArgumentException("Quantity must be positive");}return new Order(productId, quantity);}// 领域行为public void cancel() {this.status = OrderStatus.CANCELLED;}
}
3.2 仓储接口(Repository)
// domain/repository/OrderRepository.java
public interface OrderRepository {void save(Order order);// 其他查询方法省略...
}

(4) 基础设施层(Infrastructure Layer)

实现领域层定义的仓储接口(如数据库操作)。

// infrastructure/persistence/OrderRepositoryImpl.java
@Repository
public class OrderRepositoryImpl implements OrderRepository {// 模拟数据库(实际可用JPA/MyBatis等)private Map<String, Order> orders = new HashMap<>();@Overridepublic void save(Order order) {orders.put(order.getOrderId(), order);System.out.println("Order saved: " + order.getOrderId());}
}

调用流程图

对比传统CRUD

DDD传统CRUD
先设计Order的行为方法直接操作orders
业务逻辑在领域层业务逻辑散落在Service中
通过聚合根保证一致性需手动校验外键约束

充血模型特点

  1. 禁止Setter:通过构造方法或工厂方法创建对象。
  2. 领域方法命名:使用业务语言(如 cancel() 而非 setStatus("CANCELLED"))。
  3. 避免“贫血”的充血模型
    • 错误示例:在 Order 中加了方法,但核心逻辑仍在Service中。

常见误区

  • ❌ 认为充血模型等于“把所有代码塞进Entity”
    • 跨聚合逻辑应放在领域服务(Domain Service)中。
  • ❌ 忽视聚合根的一致性边界
    • 例如订单和库存属于不同聚合,不能直接在 Order 中修改库存,应通过领域事件解耦。

相关文章:

  • Datawhale AI春训营——用AI帮助老人点餐
  • 前端跨端框架的开发以及IOS和安卓的开发流程和打包上架的详细流程
  • (done) 吴恩达版提示词工程 3. 迭代 (控制输出长度、提取特定细节、输出 HTML 格式)
  • Ubuntu下软件运行常见异常退出问题汇总分析
  • Qt本地化 - installTranslator不生效
  • HarmonyOs @hadss/hmrouter路由接入
  • 外观模式:简化复杂系统接口的设计模式
  • RS232转ProfibusDP网关:连接未来传感器的关键
  • 4.1 融合架构设计:LLM与Agent的协同工作模型
  • 2025上海车展:光峰科技全球首发“灵境”智能车载光学系统
  • 倚光科技:柱面透镜加工工艺详解,解锁光学新境界
  • 构建企业官方网站有哪些必备因素?
  • vue3--手写手机屏组件
  • java Springboot使用扣子Coze实现实时音频对话智能客服
  • dockercompose文件仓库
  • Ubuntu22学习记录
  • 部署本地deepseek并在调用的详细步骤以及解决一些可能出现的问题(Windows,Linux, WSL)
  • 【数据可视化-30】Netflix电影和电视节目数据集可视化分析
  • 【记录手贱bug日常】IDEA 配置vmoptions后打不开,重新安装,删注册表均无用
  • ESP32_IDF_VScode安装多版本共存
  • 铜钴巨头洛阳钼业一季度净利润同比大增九成,最新宣布首度进军黄金矿产
  • 金隅集团:今年拿地将选择核心热门地块,稳健审慎投资
  • 上海发布一组人事任免信息:钱晓、翁轶丛任市数据局副局长
  • 国防部:“台独”武装摆练纯属搞心理安慰,怎么演都是溃败的死局
  • 特写|“三峡千古情”出圈,一场演出给宜昌留下更多游客
  • 苗旋已任民航局空管局局长、党委副书记