跳到主要内容

8.2 分层架构与依赖方向

分层架构的目标不是让项目看起来复杂,而是让业务规则、接口入口和基础设施依赖各自待在合适位置。小项目也可以保持简单分层,避免后期难以测试和修改。

学习目标

  • 能解释 API、Application、Domain、Infrastructure 的职责。
  • 能设计正确的项目依赖方向。
  • 能把业务规则从 Controller 或 Minimal API 中抽离。
  • 能判断什么时候不需要过度抽象。

推荐分层

职责不应该做什么
APIHTTP、认证、模型绑定、响应写复杂业务规则
Application用例编排、事务边界、DTO依赖 Web 框架细节
Domain业务实体、值对象、领域规则依赖数据库或 HTTP
InfrastructureEF Core、外部服务、文件、消息反向依赖 API

依赖方向

API 和 Infrastructure 都是外层,Domain 是最内层。内层不应该知道外层框架细节。

案例:完成任务用例

public sealed class CompleteTodoHandler(ITodoRepository repository)
{
public async Task<CompleteTodoResult> HandleAsync(
int todoId,
CancellationToken cancellationToken)
{
var todo = await repository.FindByIdAsync(todoId, cancellationToken);
if (todo is null)
{
return CompleteTodoResult.NotFound;
}

todo.Complete();
await repository.SaveChangesAsync(cancellationToken);

return CompleteTodoResult.Completed;
}
}

API 层只负责把 HTTP 请求转换成用例调用,真正的业务行为放在 Application 或 Domain。

重点难点

  • 分层不是按文件夹摆放,而是控制依赖方向和职责边界。
  • 不要为了模式而模式;简单 CRUD 可以保持简单,但规则复杂时要抽离。
  • Domain 不应该依赖 EF Core 特性、HTTP Context 或配置系统。
  • 接口要服务测试和替换需求,不要给每个类机械加接口。

常见误区

误区推荐做法
Controller 里写所有业务把用例放到 Application 层
Domain 直接调用数据库通过仓储或应用服务协调持久化
层数越多越专业按复杂度选择最小够用结构

练习

  • 把创建任务逻辑从 Minimal API 抽到 CreateTodoHandler
  • TodoItem.Complete() 增加“已完成不能重复完成”的业务规则。
  • 画出当前项目的依赖方向图。