modular-architecture

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Modular Architecture

模块化架构

When to Use This Skill

何时使用该技能

Use this skill when you need to:
  • Structure a modular monolith application
  • Define boundaries between modules (bounded contexts)
  • Set up inter-module communication patterns
  • Implement ports and adapters (hexagonal) architecture
  • Isolate database contexts between modules
  • Configure MediatR for internal domain events
Keywords: modular monolith, modules, bounded contexts, ports and adapters, hexagonal architecture, module communication, data isolation, separate DbContext, MediatR, domain events, internal events, module boundaries
当你需要以下操作时,可使用本技能:
  • 构建模块化单体应用
  • 定义模块间的边界(限界上下文)
  • 搭建模块间通信模式
  • 实现端口与适配器(六边形)架构
  • 在模块间隔离数据库上下文
  • 为内部领域事件配置MediatR
关键词: 模块化单体、模块、限界上下文、端口与适配器、六边形架构、模块通信、数据隔离、独立DbContext、MediatR、领域事件、内部事件、模块边界

Module Structure Pattern

模块结构模式

Core Principle

核心原则

Organize code by modules (business capabilities), not layers. Each module is a self-contained vertical slice with its own:
  • Domain entities and value objects
  • Application services and handlers
  • Infrastructure implementations
  • Data transfer objects for external communication
按**模块(业务能力)**而非代码层来组织代码。每个模块是一个独立的垂直切片,拥有自己的:
  • 领域实体与值对象
  • 应用服务与处理器
  • 基础设施实现
  • 用于外部通信的数据传输对象

Standard Module Layout

标准模块布局

text
src/
├── Modules/
│   ├── Ordering/
│   │   ├── Ordering.Core/           # Domain + Application
│   │   │   ├── Domain/              # Entities, Value Objects, Events
│   │   │   ├── Application/         # Commands, Queries, Handlers
│   │   │   └── Ports/               # Interfaces (driven/driving)
│   │   ├── Ordering.Infrastructure/ # External dependencies
│   │   │   ├── Persistence/         # EF Core, DbContext
│   │   │   └── Adapters/            # External service implementations
│   │   └── Ordering.DataTransfer/   # DTOs for module-to-module communication
│   ├── Inventory/
│   │   ├── Inventory.Core/
│   │   ├── Inventory.Infrastructure/
│   │   └── Inventory.DataTransfer/
│   └── Shared/                      # Truly shared kernel (minimal)
│       └── Shared.Kernel/           # Common value objects, interfaces
└── Host/                            # Composition root, startup
    └── Api/                         # Controllers, middleware
text
src/
├── Modules/
│   ├── Ordering/
│   │   ├── Ordering.Core/           # 领域层 + 应用层
│   │   │   ├── Domain/              # 实体、值对象、事件
│   │   │   ├── Application/         # 命令、查询、处理器
│   │   │   └── Ports/               # 接口(驱动/被驱动)
│   │   ├── Ordering.Infrastructure/ # 外部依赖实现
│   │   │   ├── Persistence/         # EF Core、DbContext
│   │   │   └── Adapters/            # 外部服务实现
│   │   └── Ordering.DataTransfer/   # 模块间通信的DTO
│   ├── Inventory/
│   │   ├── Inventory.Core/
│   │   ├── Inventory.Infrastructure/
│   │   └── Inventory.DataTransfer/
│   └── Shared/                      # 真正的共享核心(最小化)
│       └── Shared.Kernel/           # 通用值对象、接口
└── Host/                            # 组合根、启动项
    └── Api/                         # 控制器、中间件

Key Principles

关键原则

  1. No cross-module domain references - Modules cannot reference each other's Core projects
  2. DataTransfer for communication - Use DTOs to pass data between modules
  3. Infrastructure stays internal - Each module owns its persistence
  4. Minimal shared kernel - Only truly universal concepts go in Shared
  1. 禁止跨模块领域引用 - 模块之间不能引用彼此的Core项目
  2. 通过DataTransfer通信 - 使用DTO在模块间传递数据
  3. 基础设施内部化 - 每个模块独立管理自己的持久化逻辑
  4. 最小化共享核心 - 只有真正通用的概念才放入Shared目录

Ports and Adapters (Hexagonal) Pattern

端口与适配器(六边形)模式

The hexagonal architecture separates business logic from external concerns through ports (interfaces) and adapters (implementations).
Detailed guide: See
references/ports-adapters-guide.md
六边形架构通过端口(接口)和适配器(实现)将业务逻辑与外部依赖分离。
详细指南: 参见
references/ports-adapters-guide.md

Quick Reference

快速参考

text
┌─────────────────────────────────────────────────────────────┐
│                    DRIVING SIDE (Primary)                   │
│         Controllers, CLI, Message Handlers, Tests           │
│                           │                                 │
│                    ┌──────▼──────┐                          │
│                    │   PORTS     │  (Input interfaces)      │
│                    │ IOrderService│                         │
│                    └──────┬──────┘                          │
│                           │                                 │
│              ┌────────────▼────────────┐                    │
│              │      APPLICATION        │                    │
│              │    (Use Cases/Handlers) │                    │
│              └────────────┬────────────┘                    │
│                           │                                 │
│              ┌────────────▼────────────┐                    │
│              │        DOMAIN           │                    │
│              │  (Entities, Value Objs) │                    │
│              └────────────┬────────────┘                    │
│                           │                                 │
│                    ┌──────▼──────┐                          │
│                    │   PORTS     │  (Output interfaces)     │
│                    │IOrderRepository│                       │
│                    └──────┬──────┘                          │
│                           │                                 │
│                    DRIVEN SIDE (Secondary)                  │
│         Databases, External APIs, File Systems, Queues      │
└─────────────────────────────────────────────────────────────┘
Driving Ports: Interfaces the application exposes (implemented by the application) Driven Ports: Interfaces the application needs (implemented by adapters)
text
┌─────────────────────────────────────────────────────────────┐
│                    驱动端(主端)                           │
│         控制器、CLI、消息处理器、测试                        │
│                           │                                 │
│                    ┌──────▼──────┐                          │
│                    │   端口      │  (输入接口)              │
│                    │ IOrderService│                         │
│                    └──────┬──────┘                          │
│                           │                                 │
│              ┌────────────▼────────────┐                    │
│              │      应用层             │                    │
│              │    (用例/处理器)       │                    │
│              └────────────┬────────────┘                    │
│                           │                                 │
│              ┌────────────▼────────────┐                    │
│              │        领域层           │                    │
│              │  (实体、值对象)       │                    │
│              └────────────┬────────────┘                    │
│                           │                                 │
│                    ┌──────▼──────┐                          │
│                    │   端口      │  (输出接口)              │
│                    │IOrderRepository│                       │
│                    └──────┬──────┘                          │
│                           │                                 │
│                    被驱动端(次端)                         │
│         数据库、外部API、文件系统、队列                      │
└─────────────────────────────────────────────────────────────┘
驱动端口: 应用对外暴露的接口(由应用层实现) 被驱动端口: 应用所需的外部接口(由适配器实现)

Module Communication

模块通信

Modules must communicate without creating tight coupling. Two primary patterns:
Detailed guide: See
references/module-communication.md
模块通信必须避免产生紧耦合。主要有两种模式:
详细指南: 参见
references/module-communication.md

Synchronous Communication (DataTransfer)

同步通信(DataTransfer方式)

For query operations where immediate response is needed:
csharp
// In Inventory module - needs to check product availability
public class CheckStockHandler
{
    private readonly IOrderingModuleApi _orderingApi;

    public async Task<StockStatus> Handle(CheckStockQuery query)
    {
        // Get order info through DataTransfer DTO
        var orderDto = await _orderingApi.GetOrderSummary(query.OrderId);
        // orderDto is from Ordering.DataTransfer project
    }
}
适用于需要即时响应的查询操作:
csharp
// 在Inventory模块中 - 需要检查产品库存
public class CheckStockHandler
{
    private readonly IOrderingModuleApi _orderingApi;

    public async Task<StockStatus> Handle(CheckStockQuery query)
    {
        // 通过DataTransfer DTO获取订单信息
        var orderDto = await _orderingApi.GetOrderSummary(query.OrderId);
        // orderDto来自Ordering.DataTransfer项目
    }
}

Asynchronous Communication (MediatR Domain Events)

异步通信(MediatR领域事件)

For state changes that other modules need to react to:
csharp
// In Ordering module - publishes event after order is placed
public class PlaceOrderHandler
{
    private readonly IMediator _mediator;

    public async Task Handle(PlaceOrderCommand command)
    {
        // ... create order ...

        // Publish integration event (handled by other modules)
        await _mediator.Publish(new OrderPlacedIntegrationEvent(
            order.Id, order.Items.Select(i => i.ProductId)));
    }
}

// In Inventory module - handles the event
public class OrderPlacedHandler : INotificationHandler<OrderPlacedIntegrationEvent>
{
    public async Task Handle(OrderPlacedIntegrationEvent notification, CancellationToken ct)
    {
        // Reserve inventory for the order
        await _inventoryService.ReserveStock(notification.ProductIds);
    }
}
适用于其他模块需要响应的状态变更场景:
csharp
// 在Ordering模块中 - 下单完成后发布事件
public class PlaceOrderHandler
{
    private readonly IMediator _mediator;

    public async Task Handle(PlaceOrderCommand command)
    {
        // ... 创建订单 ...

        // 发布集成事件(由其他模块处理)
        await _mediator.Publish(new OrderPlacedIntegrationEvent(
            order.Id, order.Items.Select(i => i.ProductId)));
    }
}

// 在Inventory模块中 - 处理该事件
public class OrderPlacedHandler : INotificationHandler<OrderPlacedIntegrationEvent>
{
    public async Task Handle(OrderPlacedIntegrationEvent notification, CancellationToken ct)
    {
        // 为订单预留库存
        await _inventoryService.ReserveStock(notification.ProductIds);
    }
}

Data Isolation Patterns

数据隔离模式

Each module should own its data to prevent tight coupling at the database level.
Detailed guide: See
references/data-patterns.md
每个模块应独立管理自己的数据,避免在数据库层面产生紧耦合。
详细指南: 参见
references/data-patterns.md

Separate DbContext Per Module

每个模块独立使用DbContext

csharp
// Ordering module's DbContext
public class OrderingDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<OrderItem> OrderItems { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        // Only configure Ordering entities
        builder.ApplyConfigurationsFromAssembly(typeof(OrderingDbContext).Assembly);
    }
}

// Inventory module's DbContext
public class InventoryDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<StockLevel> StockLevels { get; set; }
}
csharp
// Ordering模块的DbContext
public class OrderingDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<OrderItem> OrderItems { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        // 仅配置Ordering模块的实体
        builder.ApplyConfigurationsFromAssembly(typeof(OrderingDbContext).Assembly);
    }
}

// Inventory模块的DbContext
public class InventoryDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<StockLevel> StockLevels { get; set; }
}

Key Rules

关键规则

  1. No foreign keys between modules - Use IDs as value objects instead
  2. No shared tables - Each module owns its tables completely
  3. Same database is acceptable - Separate schema/prefix per module
  4. Eventual consistency - Accept that cross-module data may be stale
  1. 模块间禁止外键关联 - 改用ID作为值对象
  2. 禁止共享数据表 - 每个模块完全独立拥有自己的表
  3. 可共用同一数据库 - 每个模块使用独立的数据库架构/表前缀
  4. 最终一致性 - 接受跨模块数据可能存在延迟的情况

MediatR Integration

MediatR集成

MediatR provides the messaging infrastructure for both in-module CQRS and cross-module integration events.
Detailed guide: See
references/mediatr-integration.md
MediatR为模块内的CQRS模式和跨模块的集成事件提供消息传递基础设施。
详细指南: 参见
references/mediatr-integration.md

Registration Pattern

注册模式

csharp
// In each module's registration
public static class OrderingModule
{
    public static IServiceCollection AddOrderingModule(this IServiceCollection services)
    {
        services.AddMediatR(cfg =>
            cfg.RegisterServicesFromAssembly(typeof(OrderingModule).Assembly));

        services.AddScoped<IOrderingModuleApi, OrderingModuleApi>();
        services.AddDbContext<OrderingDbContext>();

        return services;
    }
}
csharp
// 在每个模块的注册代码中
public static class OrderingModule
{
    public static IServiceCollection AddOrderingModule(this IServiceCollection services)
    {
        services.AddMediatR(cfg =>
            cfg.RegisterServicesFromAssembly(typeof(OrderingModule).Assembly));

        services.AddScoped<IOrderingModuleApi, OrderingModuleApi>();
        services.AddDbContext<OrderingDbContext>();

        return services;
    }
}

Event Types

事件类型

TypeScopeUse Case
Domain EventWithin moduleAggregate state changes
Integration EventCross-moduleNotify other modules of changes
类型范围适用场景
领域事件模块内部聚合根状态变更
集成事件跨模块通知其他模块发生的变更

Integration with Event Storming

与事件风暴的集成

This skill works with the
event-storming
skill for bounded context discovery:
  1. Event Storming discovers bounded contexts and events
  2. Modular Architecture implements those contexts as modules
  3. Events become MediatR integration events
  4. Context boundaries become module boundaries
Workflow:
text
Event Storming (discover "what")
Bounded Contexts identified
Modular Architecture (implement "where")
Module structure created
Fitness Functions (enforce boundaries)
本技能可与
event-storming
技能配合使用,用于限界上下文的发现:
  1. 事件风暴 发现限界上下文与事件
  2. 模块化架构 将这些上下文实现为模块
  3. 事件转化为MediatR集成事件
  4. 上下文边界成为模块边界
工作流程:
text
事件风暴(发现“是什么”)
识别出限界上下文
模块化架构(实现“放在哪里”)
创建模块结构
适配函数(强制执行边界)

Fitness Functions

适配函数

Use the
fitness-functions
skill to enforce module boundaries:
  • No cross-module domain references
  • DataTransfer project rules (only DTOs)
  • Infrastructure isolation (no leaking implementations)
使用
fitness-functions
技能来强制执行模块边界:
  • 禁止跨模块领域引用
  • DataTransfer项目规则(仅包含DTO)
  • 基础设施隔离(禁止泄露实现细节)

Quick Start Checklist

快速启动检查清单

When starting a new modular monolith:
  • Create Modules/ directory structure
  • Define Shared.Kernel with minimal shared types
  • Create per-module projects (Core, Infrastructure, DataTransfer)
  • Configure separate DbContext per module
  • Set up MediatR for domain/integration events
  • Add architecture tests to enforce boundaries
  • Document module APIs in DataTransfer projects
启动新的模块化单体应用时:
  • 创建Modules/目录结构
  • 定义包含最小共享类型的Shared.Kernel
  • 为每个模块创建项目(Core、Infrastructure、DataTransfer)
  • 为每个模块配置独立的DbContext
  • 为领域/集成事件搭建MediatR
  • 添加架构测试以强制执行边界
  • 在DataTransfer项目中记录模块API

References

参考资料

  • references/ports-adapters-guide.md
    - Detailed hexagonal architecture patterns
  • references/module-communication.md
    - Sync and async communication patterns
  • references/data-patterns.md
    - Database isolation strategies
  • references/mediatr-integration.md
    - MediatR configuration and patterns
  • references/ports-adapters-guide.md
    - 六边形架构模式详细指南
  • references/module-communication.md
    - 同步与异步通信模式
  • references/data-patterns.md
    - 数据库隔离策略
  • references/mediatr-integration.md
    - MediatR配置与模式

Version History

版本历史

  • v1.0.0 (2025-12-22): Initial release
    • Module structure patterns
    • Ports and adapters overview
    • Module communication (sync/async)
    • Data isolation patterns
    • MediatR integration
    • Event storming integration

  • v1.0.0(2025-12-22):初始版本
    • 模块结构模式
    • 端口与适配器概述
    • 模块通信(同步/异步)
    • 数据隔离模式
    • MediatR集成
    • 事件风暴集成

Last Updated

最后更新

Date: 2025-12-22 Model: claude-opus-4-5-20251101
日期: 2025-12-22 模型: claude-opus-4-5-20251101