1. 从CRUD到DDD架构演进的必然选择第一次接触领域驱动设计DDD是在一个电商系统的重构项目中。当时我们的代码库已经膨胀到难以维护的地步——超过2000张数据库表业务逻辑散落在各个Service层新功能的开发周期越来越长。这让我意识到传统的CRUD模式已经无法应对复杂业务场景的挑战。CRUDCreate, Read, Update, Delete是大多数开发者最早接触的数据操作模式。它简单直接适合业务规则简单的场景。但随着系统复杂度提升CRUD架构会暴露出几个致命问题贫血模型业务逻辑分散在Service层实体对象沦为数据容器数据库驱动设计表结构直接决定业务实现技术细节与业务概念混淆SQL语句中掺杂业务规则相比之下DDD提供了一套完整的架构方法论统一语言Ubiquitous Language建立业务与技术间的沟通桥梁分层架构明确各层的职责边界领域模型将业务知识显式转化为代码结构关键区别CRUD关注数据如何存储DDD关注业务如何运作。当你的系统开始出现业务逻辑看不懂、改一处动全身的情况时就是考虑DDD的最佳时机。2. DDD核心模式解析2.1 战略设计划分问题空间战略设计解决做什么的问题核心是识别和划分业务边界。我们通过事件风暴Event Storming工作坊来实施领域Domain业务范围如电商领域的订单、支付子域Subdomain核心/支撑/通用子域划分限界上下文Bounded Context明确的语义边界在电商系统中典型的限界上下文划分| 上下文 | 职责 | 示例模型 | |---------------|-----------------------|--------------------| | 订单上下文 | 订单创建与跟踪 | Order, OrderItem | | 支付上下文 | 支付处理 | Payment, Transaction| | 库存上下文 | 库存管理 | Inventory, SKU |2.2 战术设计构建解决方案战术设计解决怎么做的问题包含以下核心模式实体Entity具有唯一标识的对象如User的userId值对象Value Object通过属性定义的对象如Address聚合根Aggregate Root一致性边界如Order是聚合根包含OrderItems领域服务Domain Service不适合放在实体中的业务逻辑仓储Repository持久化接口工厂Factory复杂对象创建以订单系统为例的领域模型实现// 聚合根 public class Order { private OrderId id; private ListOrderItem items; private OrderStatus status; public void addItem(Product product, int quantity) { // 业务规则校验 if (status ! OrderStatus.DRAFT) { throw new IllegalStateException(只能修改草稿订单); } items.add(new OrderItem(product, quantity)); } } // 值对象 public record OrderItem(Product product, int quantity) { public BigDecimal calculateAmount() { return product.getPrice().multiply(BigDecimal.valueOf(quantity)); } }3. 分层架构实践3.1 经典四层架构DDD推荐的分层架构从上到下用户接口层Interface处理用户交互REST API、页面等应用层Application协调领域对象完成用例领域层Domain核心业务逻辑基础设施层Infrastructure技术实现数据库、消息等Spring Boot中的典型包结构src/ ├── main/ │ ├── java/ │ │ └── com/ │ │ └── example/ │ │ ├── application/ # 应用服务 │ │ ├── domain/ # 领域模型 │ │ ├── infrastructure/ # 基础设施 │ │ └── interfaces/ # 接口层3.2 六边形架构变体更现代的架构变体强调内外分离内部领域模型领域服务外部数据库/UI/第三方服务等适配器优势领域核心完全独立于技术实现更容易替换基础设施如切换数据库测试时可以用内存实现替代真实数据库4. 迁移实战从CRUD到DDD4.1 迁移步骤识别核心域80%价值来自20%功能建立统一语言术语表示例代码渐进式重构先从新增功能按DDD实现逐步改造历史功能上下文映射确定各上下文间关系合作关系/客户-供应商等4.2 代码改造示例改造前贫血模型Service public class OrderService { Autowired private OrderRepository repository; public void addItem(Long orderId, Long productId, int quantity) { Order order repository.findById(orderId); Product product productService.getById(productId); // 业务逻辑散落在Service中 if (order.getStatus() ! DRAFT) { throw new RuntimeException(非法状态); } OrderItem item new OrderItem(); item.setProductId(productId); item.setQuantity(quantity); order.getItems().add(item); repository.save(order); } }改造后充血模型// 领域层 public class Order { public void addItem(Product product, int quantity) { validateStatus(); items.add(new OrderItem(product, quantity)); } private void validateStatus() { if (status ! OrderStatus.DRAFT) { throw new DomainException(只能修改草稿订单); } } } // 应用层 Service public class OrderApplicationService { public void addItem(Long orderId, Long productId, int quantity) { Order order repository.findById(orderId); Product product productGateway.getById(productId); order.addItem(product, quantity); repository.save(order); } }5. 常见问题与解决方案5.1 性能优化策略懒加载问题明确聚合边界避免过大聚合使用CQRS模式分离读写模型事务管理一个事务只修改一个聚合最终一致性通过领域事件实现// 领域事件示例 public class OrderPaidEvent { private OrderId orderId; private BigDecimal amount; private LocalDateTime paidTime; } // 事件发布 order.pay(); eventPublisher.publish(new OrderPaidEvent(order));5.2 团队协作建议统一建模工具使用PlantUML绘制领域模型图代码与模型保持同步代码评审重点业务逻辑是否在领域层聚合是否保持完整性领域术语使用是否一致测试策略单元测试覆盖领域模型集成测试验证仓储实现契约测试验证上下文交互6. 进阶实践与工具链6.1 事件溯源Event Sourcing将状态变更记录为事件序列优势完整审计追踪、时间旅行调试挑战处理快照、事件版本迁移实现示例public class Order { private ListDomainEvent changes new ArrayList(); public void cancel() { apply(new OrderCancelledEvent(this.id)); } private void apply(DomainEvent event) { changes.add(event); handle(event); // 更新状态 } }6.2 CQRS模式命令查询职责分离写模型保持DDD纯度读模型优化查询性能Spring实现示例RestController RequestMapping(/orders) public class OrderQueryController { GetMapping(/{id}) public OrderView getOrder(PathVariable Long id) { return queryService.getOrderView(id); } } Service public class OrderCommandService { Transactional public void cancelOrder(Long id) { Order order repository.findById(id); order.cancel(); repository.save(order); } }6.3 现代架构组合DDD与以下架构的融合微服务每个限界上下文对应一个服务云原生使用Serverless实现领域服务响应式领域事件驱动架构技术选型建议框架Axon Framework, Spring Modulith数据库PostgreSQL支持JSONB, MongoDB消息Kafka, RabbitMQ在实施DDD的三年实践中最大的体会是不要追求完美的领域模型。DDD的本质是建立业务与技术的沟通机制模型会随着业务理解不断演进。建议从一个小而核心的限界上下文开始积累经验后再逐步扩展。记住可演进的架构比正确的架构更重要。
阅读完成 · 觉得有帮助?