一、DDD概述领域驱动设计Domain-Driven DesignDDD是一种软件设计方法论DDD核心思想将业务领域知识作为软件设计的核心通过深入理解业务来构建领域模型让软件更好地反映业务本质DDD的价值解决复杂业务系统的设计问题提高代码的可维护性和可扩展性促进业务人员与技术人员的沟通二、DDD核心概念1. 领域Domain┌─────────────────────────────────────────────────────────────┐ │ 领域 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ 子域1 │ │ 子域2 │ │ 子域3 │ │ │ │ (支撑子域) │ │ (核心子域) │ │ (通用子域) │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────┘子域类型核心域Core Domain业务的核心竞争力支撑子域Supporting Subdomain支撑核心业务的领域通用子域Generic Subdomain通用的、通用的领域2. 限界上下文Bounded Context┌──────────────────┐ ┌──────────────────┐ │ 订单上下文 │ │ 库存上下文 │ │ │ │ │ │ - Order │────▶│ - Inventory │ │ - OrderItem │ │ - Stock │ │ - Customer │ │ - Warehouse │ │ │ │ │ │ 统一语言订单 │ │ 统一语言库存 │ └──────────────────┘ └──────────────────┘限界上下文的作用明确模型的边界定义团队的职责保持语言的统一性三、战略设计1. 战略建模流程业务分析 → 识别限界上下文 → 定义上下文映射 → 战略设计输出2. 上下文映射上下文映射关系// 订单上下文上游publicinterfaceOrderService{OrdercreateOrder(OrderDTOdto);// 暴露给其他上下文的服务OrderSnapshotgetOrderSnapshot(LongorderId);}// 库存上下文下游- 通过防腐层访问ComponentpublicclassInventoryFacade{AutowiredprivateOrderServiceorderService;// 远程调用AutowiredprivateAntiCorruptionLayeracl;// 防腐层publicbooleanreserveStock(LongorderId){// 获取订单上下文的数据OrderSnapshotorderorderService.getOrderSnapshot(orderId);// 转换为自己上下文的实体OrderItemsitemsacl.toOrderItems(order);// 调用本上下文的服务returninventoryService.reserve(items);}}// 防腐层隔离不同上下文的模型差异ComponentpublicclassAntiCorruptionLayer{publicOrderItemstoOrderItems(OrderSnapshotsnapshot){returnOrderItems.builder().productId(snapshot.getProductId()).quantity(snapshot.getQuantity()).build();}}3. 上下文映射类型映射类型说明耦合度共享内核两个上下文共享部分模型高客户-供应商上游提供服务下游消费中跟随者跟随上游变化高防腐层隔离转换低开放主机服务提供公开API低独立方式彻底解耦最低四、战术设计1. 聚合Aggregate// 订单聚合根EntitypublicclassOrderextendsAggregateRoot{IdprivateOrderIdid;privateCustomerIdcustomerId;EmbeddedprivateOrderStatusstatus;OneToMany(cascadeCascadeType.ALL)privateListOrderItemitemsnewArrayList();privateMoneytotalAmount;// 聚合根负责维护内部一致性publicvoidaddItem(Productproduct,intquantity){// 业务规则检查if(status!OrderStatus.DRAFT){thrownewBusinessException(只有草稿状态的订单可以添加商品);}OrderItemitemOrderItem.builder().productId(product.getId()).productName(product.getName()).price(product.getPrice()).quantity(quantity).build();items.add(item);recalculateTotal();}publicvoidsubmit(){// 业务规则if(items.isEmpty()){thrownewBusinessException(订单不能为空);}this.statusOrderStatus.SUBMITTED;this.submittedAtLocalDateTime.now();// 发布领域事件registerEvent(newOrderSubmittedEvent(this));}privatevoidrecalculateTotal(){this.totalAmountitems.stream().map(item-item.getPrice().multiply(item.getQuantity())).reduce(Money.ZERO,Money::add);}}// 值对象EmbeddablepublicclassMoney{privateBigDecimalamount;privateStringcurrency;publicMoneymultiply(intquantity){returnnewMoney(this.amount.multiply(BigDecimal.valueOf(quantity)),this.currency);}publicstaticMoneyadd(Moneya,Moneyb){returnnewMoney(a.amount.add(b.amount),a.currency);}}2. 实体Entity// 实体有唯一标识的对象publicclassProduct{IdprivateProductIdid;privateStringname;privateMoneyprice;privateProductStatusstatus;// 实体的相等性基于IDOverridepublicbooleanequals(Objecto){if(thiso)returntrue;if(onull||getClass()!o.getClass())returnfalse;Productproduct(Product)o;returnObjects.equals(id,product.id);}OverridepublicinthashCode(){returnObjects.hash(id);}}// 标识对象EmbeddablepublicclassProductId{privateStringvalue;publicstaticProductIdof(Stringvalue){returnnewProductId(value);}}3. 领域服务Domain Service// 领域服务不属于任何实体的业务逻辑ServiceDomainServicepublicclassOrderDomainService{// 跨多个聚合的业务逻辑publicvoidtransferOrder(LongorderId,CustomerIdnewCustomerId){OrderorderorderRepository.findById(orderId).orElseThrow(()-newEntityNotFoundException(Order not found));// 业务规则if(order.getStatus()!OrderStatus.DRAFT){thrownewBusinessException(只有草稿订单可以转让);}// 检查新客户是否有未完成的订单if(customerService.hasPendingOrder(newCustomerId)){thrownewBusinessException(该客户有待处理订单);}order.changeCustomer(newCustomerId);orderRepository.save(order);}}4. 领域事件Domain Event// 领域事件publicclassOrderSubmittedEventextendsDomainEvent{privatefinalOrderIdorderId;privatefinalCustomerIdcustomerId;privatefinalMoneytotalAmount;publicOrderSubmittedEvent(Orderorder){super(EventId.generate(),LocalDateTime.now());this.orderIdorder.getId();this.customerIdorder.getCustomerId();this.totalAmountorder.getTotalAmount();}// Getter...}// 聚合根发布事件publicabstractclassAggregateRoot{privateListDomainEventdomainEventsnewArrayList();protectedvoidregisterEvent(DomainEventevent){domainEvents.add(event);}publicListDomainEventpullDomainEvents(){ListDomainEventeventsnewArrayList(domainEvents);domainEvents.clear();returnevents;}}// 事件发布处理器ComponentpublicclassDomainEventPublisher{AutowiredprivateApplicationEventPublisherpublisher;publicvoidpublish(DomainEventevent){// 发布到消息队列kafkaTemplate.send(domain-events,event.getClass().getSimpleName(),event);// 本地发布可选publisher.publishEvent(event);}}5. 仓储Repository// 仓储接口属于应用层但定义在领域层publicinterfaceOrderRepository{OptionalOrderfindById(OrderIdid);ListOrderfindByCustomerId(CustomerIdcustomerId);voidsave(Orderorder);voiddelete(OrderIdid);}// JPA实现RepositorypublicclassJpaOrderRepositoryimplementsOrderRepository{AutowiredprivateOrderJpaRepositoryjpaRepository;OverridepublicOptionalOrderfindById(OrderIdid){returnjpaRepository.findById(id.getValue()).map(this::toDomain);}Overridepublicvoidsave(Orderorder){OrderEntityentitytoEntity(order);jpaRepository.save(entity);}privateOrdertoDomain(OrderEntityentity){// 将实体转换为领域对象returnOrder.builder().id(OrderId.of(entity.getId())).status(entity.getStatus())// ... 转换其他字段.build();}}五、DDD分层架构1. 分层结构┌─────────────────────────────────────────────────────────────┐ │ 用户接口层 (Interface) │ │ Controllers, DTOs, Presenters, ViewModels │ ├─────────────────────────────────────────────────────────────┤ │ 应用层 (Application) │ │ Application Services, Commands, │ │ Queries, Event Handlers │ ├─────────────────────────────────────────────────────────────┤ │ 领域层 (Domain) │ │ Entities, Value Objects, Aggregates, Domain Services, │ │ Repositories (interfaces), Domain Events │ ├─────────────────────────────────────────────────────────────┤ │ 基础设施层 (Infrastructure) │ │ Repository Implementations, External Services, │ │ Message Publishers, Database Config │ └─────────────────────────────────────────────────────────────┘2. 代码结构com.example.ecommerce ├── interface # 接口层 │ ├── controller │ ├── dto │ └── presenter ├── application # 应用层 │ ├── command │ ├── query │ ├── service │ └── eventhandler ├── domain # 领域层 │ ├── model │ │ ├── order │ │ │ ├── Order.java │ │ │ ├── OrderItem.java │ │ │ ├── OrderId.java │ │ │ └── OrderStatus.java │ │ ├── product │ │ └── customer │ ├── service │ ├── repository │ └── event └── infrastructure # 基础设施层 ├── persistence │ ├── entity │ ├── dao │ └── repository ├── messaging └── external六、DDD实践案例1. 电商订单场景// 应用服务ServicepublicclassOrderApplicationService{AutowiredprivateOrderRepositoryorderRepository;AutowiredprivateProductRepositoryproductRepository;TransactionalpublicOrderDTOcreateOrder(CreateOrderCommandcommand){// 1. 创建订单聚合OrderorderOrder.create(command.getCustomerId());// 2. 添加商品for(OrderItemDTOitemDTO:command.getItems()){ProductproductproductRepository.findById(ProductId.of(itemDTO.getProductId())).orElseThrow(()-newEntityNotFoundException(Product not found));order.addItem(product,itemDTO.getQuantity());}// 3. 提交订单order.submit();// 4. 保存orderRepository.save(order);// 5. 返回DTOreturntoDTO(order);}}// DTOpublicclassOrderDTO{privateStringorderId;privateStringstatus;privateListOrderItemDTOitems;privateBigDecimaltotalAmount;// Getter/Setter...}2. 事件驱动协作// 订单提交事件监听ComponentpublicclassOrderEventHandler{AutowiredprivateInventoryServiceinventoryService;AutowiredprivateNotificationServicenotificationService;KafkaListener(topicsOrderSubmittedEvent)publicvoidhandleOrderSubmitted(OrderSubmittedEventevent){// 扣减库存inventoryService.reserveStock(event.getOrderId(),event.getItems());// 发送通知notificationService.notifyCustomer(event.getCustomerId(),订单已提交: event.getOrderId());}}七、DDD实施建议1. 实施步骤1. 业务调研 → 理解业务领域 2. 识别限界上下文 → 划分系统边界 3. 定义通用语言 → 统一团队沟通 4. 战略设计 → 定义上下文映射 5. 战术设计 → 实现领域模型 6. 持续重构 → 深化领域理解2. 常见问题问题解决方案DDD太复杂先从核心域开始逐步推广贫血模型将业务逻辑移到领域层滥用仓储仓储对应聚合非所有实体过度设计保持简单避免过度抽象3. 团队协作业务人员提供领域知识开发人员实现领域模型领域专家深入理解业务持续沟通保持语言统一八、总结DDD是一种强大的软件设计方法战略设计确定系统的边界和关系战术设计构建丰富的领域模型分层架构保持代码的清晰结构持续演进通过重构深化领域理解最佳实践从核心域开始逐步推广保持领域模型的纯粹性重视统一语言的建立通过事件驱动实现解耦个人观点仅供参考