领域驱动设计(DDD)学习笔记之:战略设计

限界上下文( Bounded Context

上下文边界的确定

在领域驱动设计(DDD)中,限界上下文(Bounded Context)是定义领域模型边界的核心概念。明确和定义上下文边界是DDD战略设计中的重要步骤。正确地确定上下文边界有助于保持模型的清晰性和一致性,降低系统的复杂性,并促进团队之间的协作。以下是确定上下文边界的一些方法和最佳实践:

1. 理解业务领域

业务需求分析
  • 业务专家访谈:与业务专家、产品经理等利益相关者进行深入的访谈和交流,了解业务需求和目标。
  • 业务流程图:绘制业务流程图,标识主要的业务活动和步骤,理解业务的全貌和关键环节。
识别业务子域
  • 核心子域:识别出系统中的核心子域,它们是系统的关键业务功能,通常是系统的核心竞争力所在。
  • 支撑子域:识别出支持核心业务但不直接产生核心价值的子域。
  • 通用子域:识别出可以重复使用的通用功能或服务。

2. 划分上下文边界的方法

业务功能划分

根据业务功能和职责划分上下文,每个上下文对应一个明确的业务功能或业务领域。

  • 订单管理上下文:处理订单的创建、修改、取消等操作。
  • 用户管理上下文:处理用户的注册、登录、信息管理等操作。
  • 库存管理上下文:处理库存的增加、减少、查询等操作。
团队结构和职责

考虑团队的组织结构和职责,确保每个上下文由一个独立的团队负责,从而减少跨团队的依赖和协调成本。

  • 订单团队:负责订单管理上下文。
  • 用户团队:负责用户管理上下文。
  • 库存团队:负责库存管理上下文。
业务边界与事件

通过识别业务事件和边界来确定上下文。当一个业务事件跨越多个子域时,可以将其作为一个新的上下文。

  • 订单完成事件:跨越订单管理上下文和支付上下文,可以定义一个独立的支付上下文来处理支付相关的逻辑。

3. 上下文之间的关系

上下文映射(Context Mapping)

绘制上下文映射图,描述不同上下文之间的关系和交互方式。

  • 客户-供应商模式:一个上下文(客户)依赖于另一个上下文(供应商)提供的服务。
  • 共享内核模式:多个上下文共享一部分公共模型和逻辑。
  • 防腐层模式:通过引入防腐层,保护核心上下文免受外部上下文的影响。
示例:电子商务系统的上下文划分
  • 订单管理上下文:处理订单的创建、修改、取消等操作。

  • 用户管理上下文:处理用户的注册、登录、信息管理等操作。

  • 支付上下文:处理支付相关的逻辑和操作。

  • 库存管理上下文:处理库存的增加、减少、查询等操作。

    graph LR
    A[订单管理上下文]
    B[用户管理上下文]
    C[支付上下文]
    D[库存管理上下文]

      A -->|调用| B
      A -->|发布事件| C
      A -->|查询| D
      C -->|调用| D
    

4. 领域事件驱动的上下文划分

识别领域事件

识别领域中的关键事件,这些事件通常表示状态的变化或重要的业务活动。

  • 订单创建事件:当一个订单被创建时触发。
  • 订单支付事件:当一个订单被支付时触发。
领域事件的传播和处理

通过领域事件在上下文之间传播信息,实现上下文之间的解耦和协作。

  • 订单管理上下文 发布订单创建事件,库存管理上下文处理该事件并更新库存。
  • 订单管理上下文 发布订单支付事件,支付上下文处理该事件并完成支付流程。

5. 实施上下文边界的最佳实践

定义清晰的接口

为每个上下文定义清晰的接口和协议,确保上下文之间的交互规范和稳定。

  • REST API接口:定义上下文之间的REST API接口,规范请求和响应格式。
  • 消息队列:通过消息队列实现上下文之间的异步通信,确保松耦合。
持续评估和优化

上下文边界的划分是一个持续迭代的过程,根据业务需求和系统的发展不断评估和优化上下文边界。

  • 反馈循环:定期与业务专家和开发团队进行反馈交流,评估上下文划分的合理性和有效性。
  • 技术债务管理:及时处理上下文边界划分中的技术债务,确保系统的可维护性和扩展性。

总结

确定限界上下文的边界是DDD战略设计中的关键步骤,通过合理划分上下文边界,可以有效管理复杂业务系统,提高系统的灵活性和可维护性。在实际项目中,结合业务需求、团队结构和领域事件等因素,持续评估和优化上下文边界,确保系统的稳定性和一致性。如果在实际实施过程中遇到问题,可以通过不断学习和实践,逐步提升上下文边界划分的能力和经验。

上下文之间的关系

在领域驱动设计(DDD)中,限界上下文(Bounded Context)是用来划分领域模型边界的核心概念。不同的上下文之间通常存在相互依赖和交互的关系。理解和管理这些关系是确保系统稳定性、灵活性和可维护性的关键。以下是确定和处理上下文之间关系的一些方法和最佳实践。

1. 上下文映射(Context Mapping)

上下文映射是描述不同限界上下文之间关系和交互的工具。它帮助我们理解和管理上下文之间的依赖,确保上下文边界清晰且关系明确。

2. 常见的上下文关系模式

客户-供应商模式(Customer-Supplier Pattern)

定义:一个上下文(客户)依赖另一个上下文(供应商)提供的服务或数据。客户上下文对供应商上下文有要求,并且供应商上下文需要满足这些要求。

示例:订单管理上下文依赖于库存管理上下文提供的库存数据。

graph LR
    Customer[订单管理上下文]
    Supplier[库存管理上下文]
    Customer -->|请求库存数据| Supplier

特点

  • 明确的依赖关系
  • 供应商上下文需要满足客户上下文的需求
共享内核模式(Shared Kernel Pattern)

定义:多个上下文共享一部分公共的模型和逻辑,作为共享内核。

示例:订单管理上下文和用户管理上下文共享用户信息的部分模型。

复制代码
graph LR
    ContextA[订单管理上下文]
    ContextB[用户管理上下文]
    Kernel[共享内核]
    ContextA --> Kernel
    ContextB --> Kernel

特点

  • 共享内核需要非常稳定
  • 共享内核的变更需要协调所有使用它的上下文
防腐层模式(Anti-Corruption Layer, ACL)

定义:在不同上下文之间引入防腐层,保护核心模型免受外部上下文的影响。防腐层负责转换和适配外部模型和数据。

示例:订单管理上下文通过防腐层与遗留系统进行交互,避免直接依赖遗留系统的模型。

复制代码
graph LR
    ContextA[订单管理上下文]
    ACL[防腐层]
    LegacySystem[遗留系统]
    ContextA -->|调用| ACL -->|调用| LegacySystem

特点

  • 保持核心模型的纯粹性和独立性
  • 简化上下文之间的集成和适配
发布-订阅模式(Published Language)

定义:上下文之间通过发布和订阅领域事件进行通信,实现解耦和异步处理。

示例:订单管理上下文发布订单创建事件,支付上下文订阅该事件并处理支付逻辑。

复制代码
graph LR
    Publisher[订单管理上下文]
    Event[订单创建事件]
    Subscriber[支付上下文]
    Publisher -->|发布事件| Event -->|订阅事件| Subscriber

特点

  • 实现上下文之间的松耦合
  • 提高系统的灵活性和可扩展性

3. 上下文映射图

上下文映射图是一种可视化工具,用于描述不同上下文之间的关系和交互模式。通过上下文映射图,可以清晰地看到系统的整体架构和各个上下文之间的依赖关系。

示例:电子商务系统的上下文映射图
复制代码
graph TD
    A[订单管理上下文]
    B[用户管理上下文]
    C[支付上下文]
    D[库存管理上下文]

    A -->|客户-供应商| D
    A -.->|共享内核| B
    A -->|防腐层| E[遗留系统]
    A -->|发布事件| F[订单创建事件]
    C -->|订阅事件| F

4. 实施上下文关系的最佳实践

明确接口和契约

为上下文之间的交互定义清晰的接口和契约,确保接口稳定、明确和易于理解。

避免直接依赖

尽量避免上下文之间的直接依赖,通过模式(如防腐层、发布-订阅)实现上下文之间的解耦。

定期评审和优化

定期评审上下文之间的关系,根据业务需求和系统变化进行必要的调整和优化。

利用工具和框架

使用适当的工具和框架(如消息队列、API网关)来实现上下文之间的通信和集成,简化开发和维护。

总结

在领域驱动设计中,管理上下文之间的关系是确保系统健壮性和可维护性的关键。通过合理应用上下文映射、客户-供应商模式、共享内核、防腐层和发布-订阅等模式,可以有效管理复杂业务系统中的上下文关系,提高系统的灵活性和扩展性。在实际项目中,持续评估和优化上下文关系,确保系统的稳定性和一致性。

子域( Subdomains

核心子域(Core Domain)

核心子域(Core Domain)是领域驱动设计(DDD)中的一个重要概念,指的是系统中最重要的部分,它直接体现了业务的核心价值和竞争力。核心子域通常包含最复杂、最关键的业务逻辑,处理业务中的核心问题。理解和正确设计核心子域对于系统的成功至关重要。

1. 核心子域的定义

定义

核心子域是业务领域中的关键部分,它对业务的成功和竞争力至关重要。核心子域中的模型和逻辑通常是独特的,反映了业务的核心能力和优势。

特点
  • 业务核心:核心子域是业务的核心,直接关系到业务的核心价值和竞争力。
  • 高复杂性:通常包含最复杂的业务逻辑和规则。
  • 高投资回报:对核心子域的投资(时间、资源)回报最高,因为它直接影响业务的成功。
  • 高稳定性:核心子域需要高度稳定和可靠,任何变化都需要慎重考虑。

2. 识别核心子域

识别核心子域是DDD战略设计的重要步骤,需要深入理解业务和其竞争优势。以下是一些识别核心子域的方法:

业务价值评估

评估业务的不同部分,确定哪些部分对业务的成功和竞争力最为重要。

关键业务流程

识别业务中的关键业务流程和活动,通常这些流程和活动集中在核心子域中。

竞争优势

分析业务的竞争优势,确定哪些领域是业务在市场中脱颖而出的关键因素。

专家访谈

与业务专家、产品经理和其他利益相关者进行深入访谈,获取他们对业务核心的见解和观点。

3. 核心子域的设计和实现

高内聚低耦合

核心子域的设计应遵循高内聚低耦合的原则,确保内部逻辑和模型的高度一致性,同时减少对外部系统和上下文的依赖。

领域模型

核心子域的领域模型需要精心设计,确保模型准确反映业务逻辑和规则。使用领域驱动设计中的实体、值对象、聚合等概念来构建高质量的模型。

领域事件

在核心子域中使用领域事件,确保业务逻辑的清晰和可维护性。领域事件帮助捕捉业务中的重要变化和行为。

持续优化

核心子域的设计和实现需要持续优化,根据业务需求和反馈不断改进和调整模型和逻辑。

4. 核心子域的示例

以下是一个电子商务系统中的核心子域示例,假设订单处理是该系统的核心子域。

订单处理核心子域

领域模型

复制代码
java 复制代码
public class Order {
    private String orderId;
    private OrderStatus status;
    private List<OrderItem> items;

    // 构造方法
    public Order(String orderId, List<OrderItem> items) {
        this.orderId = orderId;
        this.items = items;
        this.status = OrderStatus.PENDING;
    }

    // 获取订单ID
    public String getOrderId() {
        return orderId;
    }

    // 获取订单状态
    public OrderStatus getStatus() {
        return status;
    }

    // 添加订单项
    public void addItem(OrderItem item) {
        items.add(item);
    }

    // 支付订单
    public void pay() {
        if (status == OrderStatus.PENDING) {
            status = OrderStatus.PAID;
        } else {
            throw new IllegalStateException("Order cannot be paid in its current state.");
        }
    }

    // 取消订单
    public void cancel() {
        if (status == OrderStatus.PENDING) {
            status = OrderStatus.CANCELED;
        } else {
            throw new IllegalStateException("Order cannot be canceled in its current state.");
        }
    }
}

领域事件

复制代码
java 复制代码
public class OrderCreatedEvent {
    private final String orderId;
    private final LocalDateTime occurredOn;
    private final List<OrderItem> items;

    public OrderCreatedEvent(String orderId, LocalDateTime occurredOn, List<OrderItem> items) {
        this.orderId = orderId;
        this.occurredOn = occurredOn;
        this.items = items;
    }

    public String getOrderId() {
        return orderId;
    }

    public LocalDateTime getOccurredOn() {
        return occurredOn;
    }

    public List<OrderItem> getItems() {
        return items;
    }
}

服务和仓储

复制代码
java 复制代码
public class OrderService {
    private final OrderRepository orderRepository;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    public void placeOrder(Order order) {
        orderRepository.save(order);
        // 发布订单创建事件
        DomainEventPublisher.publish(new OrderCreatedEvent(order.getOrderId(), LocalDateTime.now(), order.getItems()));
    }
}

public interface OrderRepository {
    Order findById(String orderId);
    void save(Order order);
    void delete(Order order);
}

5. 核心子域的最佳实践

聚焦业务价值

始终将核心子域的设计和实现聚焦于业务价值,确保每个决策和改进都能直接提升业务的核心竞争力。

持续学习和优化

核心子域不是一成不变的,需要持续学习和优化,根据市场和业务需求的变化不断调整和改进。

跨团队协作

核心子域的设计和实现需要跨团队的协作,确保所有相关团队的需求和意见都能被考虑和整合。

高质量代码

在核心子域中保持高质量的代码,严格遵循编码规范和最佳实践,确保系统的稳定性和可维护性。

总结

核心子域是DDD中的重要概念,它代表了系统中最重要的部分,直接体现业务的核心价值和竞争力。通过合理设计和实现核心子域,可以有效提升系统的稳定性、灵活性和业务价值。在实际项目中,持续关注和优化核心子域,确保其始终符合业务需求和市场变化。

支持子域(Supporting Subdomain)

支持子域(Supporting Subdomain)

支持子域(Supporting Subdomain)是领域驱动设计(DDD)中的一个重要概念,它指的是那些虽然不是核心竞争力,但对核心子域的功能实现和整体系统的正常运行起到支撑作用的子域。理解和正确设计支持子域对于构建一个完整、健壮的系统是至关重要的。

1. 支持子域的定义

定义

支持子域是业务领域中的一部分,它们提供必要的辅助功能,支持核心子域的业务流程和操作。尽管支持子域本身并不直接产生业务的核心价值,但它们是不可或缺的,能够增强和优化核心子域的运作。

特点
  • 辅助性:支持子域为核心子域提供辅助功能和服务。
  • 非核心竞争力:支持子域的功能通常不是业务的核心竞争力,但它们是确保系统正常运行的重要组成部分。
  • 可重用性:支持子域的功能和服务在不同的核心子域中可能是通用和可重用的。

2. 识别支持子域

业务需求分析

分析业务需求,识别出那些虽然不是核心但对业务流程有支持作用的功能和服务。

支撑功能识别

识别业务流程中的辅助和支撑功能,如数据管理、日志记录、身份验证、通知服务等。

与核心子域的关系

确定支持子域与核心子域的关系,确保支持子域能够有效地支撑和服务于核心子域。

3. 支持子域的设计和实现

高内聚低耦合

支持子域的设计应遵循高内聚低耦合的原则,确保其内部逻辑的一致性,同时减少对其他子域的依赖。

通用服务

设计支持子域时,要考虑其通用性,使其功能和服务能够在不同的核心子域中复用。

领域模型

支持子域的领域模型应尽可能简单、清晰,避免复杂的业务逻辑。使用DDD的实体、值对象等概念来构建模型。

4. 支持子域的示例

以下是一个电子商务系统中的支持子域示例,假设用户管理是该系统的支持子域。

用户管理支持子域

领域模型

复制代码
java 复制代码
public class User {
    private String userId;
    private String username;
    private String email;

    // 构造方法
    public User(String userId, String username, String email) {
        this.userId = userId;
        this.username = username;
        this.email = email;
    }

    // 获取用户ID
    public String getUserId() {
        return userId;
    }

    // 获取用户名
    public String getUsername() {
        return username;
    }

    // 获取邮箱
    public String getEmail() {
        return email;
    }

    // 更新邮箱
    public void updateEmail(String newEmail) {
        this.email = newEmail;
    }
}

服务和仓储

复制代码
java 复制代码
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void registerUser(User user) {
        userRepository.save(user);
    }

    public User findUserById(String userId) {
        return userRepository.findById(userId);
    }

    public void updateUserEmail(String userId, String newEmail) {
        User user = userRepository.findById(userId);
        if (user != null) {
            user.updateEmail(newEmail);
            userRepository.save(user);
        }
    }
}

public interface UserRepository {
    User findById(String userId);
    void save(User user);
}

5. 支持子域的最佳实践

明确职责

明确支持子域的职责范围,确保其功能和服务能够有效地支撑核心子域。

可重用性设计

在设计支持子域时,要考虑其可重用性,使其功能和服务能够在不同的核心子域中复用。

简化复杂性

支持子域的设计应尽可能简化,避免引入复杂的业务逻辑,确保其功能清晰、易于维护。

持续优化

定期评审和优化支持子域,根据业务需求和系统变化不断改进其功能和服务。

总结

支持子域在DDD中扮演着重要的角色,尽管它们不是业务的核心竞争力,但它们为核心子域提供了必要的辅助功能和服务。通过合理设计和实现支持子域,可以有效增强系统的健壮性和灵活性,确保核心子域能够高效运作。在实际项目中,持续关注和优化支持子域,确保其能够满足业务需求和系统发展的需要。

通用子域(Generic Subdomain)

在领域驱动设计(DDD)中,通用子域(Generic Subdomain)指的是那些虽然重要但不具有业务独特性的部分。通用子域通常包含在多个业务领域中都需要的共性功能或服务,可以复用并且通常可以通过现成的解决方案来实现。理解和合理利用通用子域对于提高开发效率和系统一致性至关重要。

1. 通用子域的定义

定义

通用子域是指那些在不同业务领域中通用的、非特定业务的功能或服务。这些功能和服务不是业务的核心竞争力,可以通过标准化或购买现成的软件解决方案来实现。

特点
  • 通用性:功能和服务在多个业务领域中是通用的,没有特定的业务逻辑。
  • 非核心竞争力:通用子域的功能不直接构成业务的核心竞争力。
  • 标准化:通常可以通过标准化的方式实现,或者使用现成的解决方案。

2. 识别通用子域

业务需求分析

分析业务需求,识别出那些在多个领域中都需要的功能和服务。

复用性评估

评估功能和服务的复用性,确定哪些功能可以在不同业务领域中共享使用。

标准化评估

评估哪些功能和服务可以通过标准化的方式实现,或者使用现成的解决方案来满足需求。

3. 通用子域的设计和实现

高内聚低耦合

通用子域的设计应遵循高内聚低耦合的原则,确保其功能的一致性和独立性,同时减少对其他子域的依赖。

标准化实现

尽量采用标准化的实现方式,使用行业标准和最佳实践,确保通用子域的可复用性和可维护性。

使用现成解决方案

在可能的情况下,使用现成的解决方案(如开源库、第三方服务)来实现通用子域,减少开发成本和时间。

4. 通用子域的示例

以下是一个电子商务系统中的通用子域示例,假设日志记录和身份验证是该系统的通用子域。

日志记录通用子域

领域模型

复制代码
java 复制代码
public class LogEntry {
    private String id;
    private LocalDateTime timestamp;
    private String message;
    private LogLevel level;

    // 构造方法
    public LogEntry(String id, LocalDateTime timestamp, String message, LogLevel level) {
        this.id = id;
        this.timestamp = timestamp;
        this.message = message;
        this.level = level;
    }

    // 获取日志条目ID
    public String getId() {
        return id;
    }

    // 获取时间戳
    public LocalDateTime getTimestamp() {
        return timestamp;
    }

    // 获取日志消息
    public String getMessage() {
        return message;
    }

    // 获取日志级别
    public LogLevel getLevel() {
        return level;
    }
}

服务和仓储

复制代码
java 复制代码
public class LoggingService {
    private final LogRepository logRepository;

    public LoggingService(LogRepository logRepository) {
        this.logRepository = logRepository;
    }

    public void log(LogEntry entry) {
        logRepository.save(entry);
    }
}

public interface LogRepository {
    void save(LogEntry logEntry);
    List<LogEntry> findAll();
}
身份验证通用子域

领域模型

复制代码
java 复制代码
public class User {
    private String userId;
    private String username;
    private String passwordHash;

    // 构造方法
    public User(String userId, String username, String passwordHash) {
        this.userId = userId;
        this.username = username;
        this.passwordHash = passwordHash;
    }

    // 获取用户ID
    public String getUserId() {
        return userId;
    }

    // 获取用户名
    public String getUsername() {
        return username;
    }

    // 获取密码哈希
    public String getPasswordHash() {
        return passwordHash;
    }
}

服务和仓储

java 复制代码
public class AuthenticationService {
    private final UserRepository userRepository;

    public AuthenticationService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public boolean authenticate(String username, String password) {
        User user = userRepository.findByUsername(username);
        if (user != null) {
            // 验证密码哈希
            return PasswordHasher.verify(password, user.getPasswordHash());
        }
        return false;
    }
}

public interface UserRepository {
    User findByUsername(String username);
    void save(User user);
}

5. 通用子域的最佳实践

标准化接口

为通用子域定义标准化接口和契约,确保其功能和服务在不同领域中可以一致地使用。

利用现成解决方案

尽量使用现成的解决方案来实现通用子域,减少开发成本和时间。

持续优化

定期评审和优化通用子域,根据业务需求和技术进步不断改进其功能和服务。

高可用性和可维护性

确保通用子域的实现具有高可用性和可维护性,使用可靠的技术和工具,确保其能够稳定运行和易于维护。

总结

通用子域在DDD中扮演着重要的角色,尽管它们不是业务的核心竞争力,但它们为多个业务领域提供了必要的共性功能和服务。通过合理设计和实现通用子域,可以有效提高系统的开发效率和一致性。在实际项目中,持续关注和优化通用子域,确保其能够满足业务需求和系统发展的需要。

上下文映射(Context Mapping

上下文映射图(Context Map)

在领域驱动设计(DDD)中,上下文映射图(Context Map)是一种用于描述不同限界上下文(Bounded Context)之间关系和交互模式的可视化工具。上下文映射图帮助团队理解和管理系统中的各个上下文及其相互依赖关系,从而确保系统的整体架构清晰且可维护。

1. 上下文映射图的定义

定义

上下文映射图是一种图示,用于描述不同限界上下文之间的关系和交互模式。它提供了一种全局视角,使团队能够识别和理解各个上下文的边界、依赖关系和交互方式。

目的
  • 清晰边界:明确各个上下文的边界和职责。
  • 描述关系:描述上下文之间的依赖关系和交互模式。
  • 统一视图:提供系统整体架构的统一视图,帮助团队协调和沟通。

2. 上下文映射图的组成部分

上下文(Contexts)

每个限界上下文在图中表示为一个独立的区域,通常用矩形表示,并标注上下文的名称和职责。

关系和交互(Relationships and Interactions)

上下文之间的关系和交互用箭头和连接线表示,不同的关系类型可以使用不同的箭头和线条样式来区分。

上下文映射模式(Context Mapping Patterns)

上下文映射图通常使用一些标准的模式来描述上下文之间的关系,包括:

  • 客户-供应商(Customer-Supplier):一个上下文(客户)依赖另一个上下文(供应商)提供的服务或数据。
  • 共享内核(Shared Kernel):多个上下文共享一部分公共的模型和逻辑。
  • 防腐层(Anti-Corruption Layer, ACL):在上下文之间引入防腐层,保护核心模型免受外部上下文的影响。
  • 发布-订阅(Published Language):上下文通过发布和订阅领域事件进行通信,实现解耦和异步处理。

3. 上下文映射图的示例

以下是一个电子商务系统的上下文映射图示例,其中包括订单管理、用户管理、支付和库存管理等上下文。

java 复制代码
graph TD
    A[订单管理上下文]
    B[用户管理上下文]
    C[支付上下文]
    D[库存管理上下文]

    A -->|客户-供应商| D
    A -.->|共享内核| B
    A -->|防腐层| E[遗留系统]
    A -->|发布事件| F[订单创建事件]
    C -->|订阅事件| F

4. 上下文映射模式详解

客户-供应商模式(Customer-Supplier)

定义:一个上下文(客户)依赖于另一个上下文(供应商)提供的服务或数据。客户上下文对供应商上下文有需求,而供应商上下文需要满足这些需求。

示例:订单管理上下文依赖库存管理上下文提供的库存数据。

java 复制代码
graph LR
    Customer[订单管理上下文]
    Supplier[库存管理上下文]
    Customer -->|请求库存数据| Supplier
共享内核模式(Shared Kernel)

定义:多个上下文共享一部分公共的模型和逻辑,这些共享部分被称为共享内核。

示例:订单管理上下文和用户管理上下文共享用户信息的部分模型。

复制代码
java 复制代码
graph LR
    ContextA[订单管理上下文]
    ContextB[用户管理上下文]
    Kernel[共享内核]
    ContextA --> Kernel
    ContextB --> Kernel
防腐层模式(Anti-Corruption Layer, ACL)

定义:在不同的上下文之间引入防腐层,保护核心模型免受外部上下文的影响。防腐层负责适配和转换外部系统的数据和接口。

示例:订单管理上下文通过防腐层与遗留系统进行交互。

复制代码
java 复制代码
graph LR
    ContextA[订单管理上下文]
    ACL[防腐层]
    LegacySystem[遗留系统]
    ContextA -->|调用| ACL -->|调用| LegacySystem
发布-订阅模式(Published Language)

定义:上下文之间通过发布和订阅领域事件进行通信,实现解耦和异步处理。

示例:订单管理上下文发布订单创建事件,支付上下文订阅该事件并处理支付逻辑。

复制代码
java 复制代码
graph LR
    Publisher[订单管理上下文]
    Event[订单创建事件]
    Subscriber[支付上下文]
    Publisher -->|发布事件| Event -->|订阅事件| Subscriber

5. 实施上下文映射图的最佳实践

清晰定义上下文

确保每个上下文的边界和职责清晰定义,避免职责重叠和不明确的依赖关系。

使用标准模式

使用标准的上下文映射模式来描述上下文之间的关系,确保图示的统一性和可理解性。

持续更新和维护

上下文映射图是一个动态的工具,随着系统和业务的发展需要持续更新和维护,确保其始终反映系统的最新状态。

团队协作

在绘制和维护上下文映射图时,确保团队的每个成员都参与其中,并且理解和认同图示的内容和意义。

总结

上下文映射图是DDD中的一个强大工具,通过可视化的方式描述不同限界上下文之间的关系和交互模式,帮助团队理解和管理系统的整体架构。合理使用上下文映射图,可以有效提升系统的清晰性、灵活性和可维护性。在实际项目中,持续评审和优化上下文映射图,确保其始终能够准确反映系统的结构和演进。

上下文间的集成模式(如共享内核、客户-供应商关系、发布-订阅模式等)

在领域驱动设计(DDD)中,不同的限界上下文(Bounded Context)之间通常需要进行集成和交互。为了管理和优化这些集成关系,DDD提供了多种上下文间的集成模式。以下是几种常见的集成模式,包括共享内核、客户-供应商关系和发布-订阅模式等,以及它们的详细解释和示例。

1. 共享内核模式(Shared Kernel Pattern)

定义

共享内核模式指的是多个上下文共享一部分公共的模型和逻辑,这些共享部分被称为共享内核。共享内核需要非常稳定,因为任何变更都会影响所有依赖它的上下文。

特点
  • 高稳定性:共享内核需要非常稳定,变更需要所有依赖上下文的协调。
  • 代码复用:共享内核中的代码和模型在多个上下文中复用。
  • 协作:共享内核的变更需要团队之间的密切协作和沟通。
示例

订单管理上下文和用户管理上下文共享用户信息的部分模型。

复制代码
java 复制代码
graph LR
    ContextA[订单管理上下文]
    ContextB[用户管理上下文]
    Kernel[共享内核]
    ContextA --> Kernel
    ContextB --> Kernel

2. 客户-供应商模式(Customer-Supplier Pattern)

定义

客户-供应商模式描述了一个上下文(客户)依赖于另一个上下文(供应商)提供的服务或数据。客户上下文对供应商上下文有需求,而供应商上下文需要满足这些需求。

特点
  • 明确依赖:客户上下文明确依赖于供应商上下文。
  • 双向反馈:供应商上下文需要考虑客户上下文的需求,但客户上下文不应该直接影响供应商上下文的内部实现。
示例

订单管理上下文依赖库存管理上下文提供的库存数据。

复制代码
java 复制代码
graph LR
    Customer[订单管理上下文]
    Supplier[库存管理上下文]
    Customer -->|请求库存数据| Supplier

3. 发布-订阅模式(Published Language)

定义

发布-订阅模式指的是上下文之间通过发布和订阅领域事件进行通信。发布者发布事件,订阅者订阅并处理这些事件。这种模式实现了解耦和异步处理。

特点
  • 松耦合:上下文之间通过事件通信,减少直接依赖。
  • 灵活性:可以方便地添加或移除事件的发布者和订阅者。
  • 异步处理:支持异步处理,提高系统的扩展性和响应能力。
示例

订单管理上下文发布订单创建事件,支付上下文订阅该事件并处理支付逻辑。

复制代码
java 复制代码
graph LR
    Publisher[订单管理上下文]
    Event[订单创建事件]
    Subscriber[支付上下文]
    Publisher -->|发布事件| Event -->|订阅事件| Subscriber

4. 防腐层模式(Anti-Corruption Layer, ACL)

定义

防腐层模式是在不同的上下文之间引入一个防腐层,保护核心模型免受外部上下文的影响。防腐层负责适配和转换外部系统的数据和接口。

特点
  • 隔离外部影响:防腐层隔离了外部系统对内部模型的直接影响。
  • 转换和适配:防腐层处理外部模型和内部模型之间的转换。
示例

订单管理上下文通过防腐层与遗留系统进行交互。

复制代码
java 复制代码
graph LR
    Publisher[订单管理上下文]
    Event[订单创建事件]
    Subscriber[支付上下文]
    Publisher -->|发布事件| Event -->|订阅事件| Subscriber

5. 上下文映射(Context Mapping)

上下文映射图是一种可视化工具,用于描述不同上下文之间的关系和交互模式。它帮助团队理解和管理系统中的各个上下文及其相互依赖关系。

示例:电子商务系统的上下文映射图
复制代码
java 复制代码
graph TD
    A[订单管理上下文]
    B[用户管理上下文]
    C[支付上下文]
    D[库存管理上下文]

    A -->|客户-供应商| D
    A -.->|共享内核| B
    A -->|防腐层| E[遗留系统]
    A -->|发布事件| F[订单创建事件]
    C -->|订阅事件| F

实施集成模式的最佳实践

清晰定义接口

确保各个上下文之间的接口和契约清晰定义,避免接口不明确导致的集成问题。

持续评审和优化

定期评审上下文之间的集成关系,根据业务需求和系统变化进行必要的调整和优化。

利用工具和框架

使用适当的工具和框架(如消息队列、API网关)来实现上下文之间的通信和集成,简化开发和维护。

团队协作

在实现集成模式时,确保各个团队之间的密切协作和沟通,确保所有成员理解和认同集成方案。

总结

在领域驱动设计中,不同的限界上下文之间通常需要进行集成和交互。通过合理应用共享内核、客户-供应商关系、发布-订阅模式、防腐层等集成模式,可以有效管理复杂业务系统中的上下文关系,提高系统的灵活性和扩展性。在实际项目中,持续评审和优化上下文集成模式,确保系统的稳定性和一致性。

相关推荐
老肖相当外语大佬2 天前
解决DDD最大难题-如何划分领域
ddd·领域驱动设计·软件设计
rolt6 天前
[pdf,epub]105页《分析模式》漫谈合集01
ddd·架构师·uml·领域驱动设计·分析模式
rolt13 天前
[答疑]是不是互联网更适合用DDD
ddd·领域驱动设计
rolt22 天前
有向无环图的约束怎么表达-《分析模式》漫谈39
ddd·uml·领域驱动设计·面向对象
老肖相当外语大佬2 个月前
反DDD模式之“复用”
开源·实战·ddd·领域驱动设计
xin4972 个月前
领域模型和数据模型还傻傻分不清? 如何实现领域模型
后端·领域驱动设计
老肖相当外语大佬2 个月前
反DDD模式之关系型数据库
ddd·领域驱动设计·关系数据库·三范式
老肖相当外语大佬2 个月前
欢迎加入d3shop,一个DDD实战项目
开源·实战·ddd·领域驱动设计
老肖相当外语大佬2 个月前
图穷匕见-所有反DDD模式都是垃圾
ddd·领域驱动设计
老肖相当外语大佬2 个月前
主观与客观,破除DDD凭经验魔咒
java·ddd·领域驱动设计·dotnet