name: modular-architecture description: 包括端口和适配器(六边形)的模块组织模式、模块通信和数据隔离。在构建模块化单体应用、定义模块边界、设置模块间通信或隔离数据库上下文时使用。包括用于内部事件的MediatR模式。 allowed-tools: Read, Write, Glob, Grep, Skill
模块化架构
何时使用此技能
使用此技能当您需要:
- 构建模块化单体应用程序
- 定义模块之间的边界(有界上下文)
- 设置模块间通信模式
- 实现端口和适配器(六边形)架构
- 隔离模块之间的数据库上下文
- 配置MediatR用于内部域事件
关键词: 模块化单体、模块、有界上下文、端口和适配器、六边形架构、模块通信、数据隔离、单独DbContext、MediatR、域事件、内部事件、模块边界
模块结构模式
核心原则
按**模块(业务能力)**组织代码,而非层次。每个模块是一个自包含的垂直切片,拥有自己的:
- 域实体和值对象
- 应用服务和处理器
- 基础设施实现
- 用于外部通信的数据传输对象
标准模块布局
src/
├── Modules/
│ ├── Ordering/
│ │ ├── Ordering.Core/ # 域 + 应用
│ │ │ ├── Domain/ # 实体、值对象、事件
│ │ │ ├── Application/ # 命令、查询、处理器
│ │ │ └── Ports/ # 接口(驱动/被驱动)
│ │ ├── Ordering.Infrastructure/ # 外部依赖
│ │ │ ├── Persistence/ # EF Core、DbContext
│ │ │ └── Adapters/ # 外部服务实现
│ │ └── Ordering.DataTransfer/ # 用于模块间通信的DTOs
│ ├── Inventory/
│ │ ├── Inventory.Core/
│ │ ├── Inventory.Infrastructure/
│ │ └── Inventory.DataTransfer/
│ └── Shared/ # 真正共享的内核(最小化)
│ └── Shared.Kernel/ # 通用值对象、接口
└── Host/ # 组合根、启动
└── Api/ # 控制器、中间件
关键原则
- 无跨模块域引用 - 模块不能引用彼此的Core项目
- DataTransfer用于通信 - 使用DTOs在模块间传递数据
- 基础设施保持内部 - 每个模块拥有其持久化
- 最小共享内核 - 只有真正通用的概念放入Shared
端口和适配器(六边形)模式
六边形架构通过端口(接口)和适配器(实现)将业务逻辑与外部关注点分离。
详细指南: 参见 references/ports-adapters-guide.md
快速参考
┌─────────────────────────────────────────────────────────────┐
│ 驱动侧(主要) │
│ 控制器、CLI、消息处理器、测试 │
│ │ │
│ ┌──────▼──────┐ │
│ │ 端口 │ (输入接口) │
│ │ IOrderService│ │
│ └──────┬──────┘ │
│ │ │
│ ┌────────────▼────────────┐ │
│ │ 应用层 │ │
│ │ (用例/处理器) │ │
│ └────────────┬────────────┘ │
│ │ │
│ ┌────────────▼────────────┐ │
│ │ 域层 │ │
│ │ (实体、值对象) │ │
│ └────────────┬────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ 端口 │ (输出接口) │
│ │IOrderRepository│ │
│ └──────┬──────┘ │
│ │ │
│ 被驱动侧(次要) │
│ 数据库、外部API、文件系统、队列 │
└─────────────────────────────────────────────────────────────┘
驱动端口: 应用程序暴露的接口(由应用程序实现) 被驱动端口: 应用程序需要的接口(由适配器实现)
模块通信
模块必须通信而不创建紧耦合。两种主要模式:
详细指南: 参见 references/module-communication.md
同步通信(DataTransfer)
对于需要立即响应的查询操作:
// 在库存模块 - 需要检查产品可用性
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项目
}
}
异步通信(MediatR域事件)
对于其他模块需要反应的状态变化:
// 在订单模块 - 下单后发布事件
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)));
}
}
// 在库存模块 - 处理事件
public class OrderPlacedHandler : INotificationHandler<OrderPlacedIntegrationEvent>
{
public async Task Handle(OrderPlacedIntegrationEvent notification, CancellationToken ct)
{
// 为订单预留库存
await _inventoryService.ReserveStock(notification.ProductIds);
}
}
数据隔离模式
每个模块应拥有其数据以防止数据库级别的紧耦合。
详细指南: 参见 references/data-patterns.md
每个模块单独的DbContext
// 订单模块的DbContext
public class OrderingDbContext : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
// 仅配置订单实体
builder.ApplyConfigurationsFromAssembly(typeof(OrderingDbContext).Assembly);
}
}
// 库存模块的DbContext
public class InventoryDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<StockLevel> StockLevels { get; set; }
}
关键规则
- 模块间无外键 - 使用ID作为值对象代替
- 无共享表 - 每个模块完全拥有其表
- 同一数据库可接受 - 每个模块单独模式/前缀
- 最终一致性 - 接受跨模块数据可能过时
MediatR集成
MediatR提供消息基础设施,用于模块内CQRS和跨模块集成事件。
详细指南: 参见 references/mediatr-integration.md
注册模式
// 在每个模块的注册中
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-storming 技能配合用于有界上下文发现:
- 事件风暴 发现有界上下文和事件
- 模块化架构 将这些上下文实现为模块
- 事件成为MediatR集成事件
- 上下文边界成为模块边界
工作流:
事件风暴(发现“什么”)
↓
有界上下文识别
↓
模块化架构(实现“哪里”)
↓
模块结构创建
↓
适应度函数(强制边界)
适应度函数
使用 fitness-functions 技能强制模块边界:
- 无跨模块域引用
- DataTransfer项目规则(仅DTOs)
- 基础设施隔离(无泄漏实现)
快速启动清单
当启动新的模块化单体时:
- [ ] 创建Modules/目录结构
- [ ] 定义最小共享类型的Shared.Kernel
- [ ] 创建每个模块项目(Core、Infrastructure、DataTransfer)
- [ ] 配置每个模块单独的DbContext
- [ ] 设置MediatR用于域/集成事件
- [ ] 添加架构测试强制边界
- [ ] 在DataTransfer项目中记录模块API
参考文献
references/ports-adapters-guide.md- 详细六边形架构模式references/module-communication.md- 同步和异步通信模式references/data-patterns.md- 数据库隔离策略references/mediatr-integration.md- MediatR配置和模式
版本历史
- v1.0.0 (2025-12-22): 初始发布
- 模块结构模式
- 端口和适配器概述
- 模块通信(同步/异步)
- 数据隔离模式
- MediatR集成
- 事件风暴集成
最后更新
日期: 2025-12-22 模型: claude-opus-4-5-20251101