快速上手领域驱动设计:基于 Ncp.CleanDDD 的 .NET 架构模板实践

4 阅读4分钟

快速上手领域驱动设计:基于 Ncp.CleanDDD 的 .NET 架构模板实践

在现代软件开发中,领域驱动设计(Domain-Driven Design, DDD)已成为构建复杂业务系统的核心方法论。然而,DDD 概念抽象、分层繁多,初学者常因“不知如何落地”而望而却步。为降低 DDD 实践门槛,社区涌现出多个标准化架构模板,其中 Ncp.CleanDDD 作为一款轻量、规范且面向 .NET 开发者的开源项目,提供了开箱即用的 Clean Architecture + DDD 融合结构。

本文将带你全面了解 Ncp.CleanDDD 模板的设计理念、核心分层、关键组件,并演示如何快速创建一个符合 DDD 原则的 .NET 应用。


一、什么是 Ncp.CleanDDD?

Ncp.CleanDDD 是由国内开发者社区维护的一个 .NET 解决方案模板(GitHub 项目名通常为 Ncp.CleanDDD 或类似变体),它深度融合了:

  • 领域驱动设计(DDD):聚焦业务核心,划分聚合、实体、值对象、领域服务等。
  • 整洁架构(Clean Architecture):通过依赖倒置实现内外层解耦。
  • CQRS 模式:命令与查询分离,提升可维护性与扩展性。
  • MediatR、FluentValidation、EF Core 等主流库:提供现代化 .NET 开发体验。

💡 注:虽然 “Ncp.CleanDDD” 并非官方 Microsoft 项目,但其命名和结构代表了一类广泛采用的 DDD 实践模板(类似 Jason Taylor 的 CleanArchitecture 演进版)。本文以典型结构为准进行说明。


二、项目结构解析

典型的 Ncp.CleanDDD 解决方案包含以下核心项目(按依赖方向从内到外):

src/
├── MyProject.Domain          ← 领域层(纯业务逻辑,无外部依赖)
├── MyProject.Application     ← 应用层(用例、DTO、MediatR Handlers)
├── MyProject.Infrastructure  ← 基础设施层(EF Core、邮件、文件存储等实现)
├── MyProject.WebApi          ← 表示层(ASP.NET Core Web API)
tests/
├── MyProject.Application.UnitTests
├── MyProject.Domain.UnitTests
└── MyProject.IntegrationTests

1. Domain 层 —— 业务核心

  • Entities / Aggregates:如 Order, Customer
  • Value Objects:如 Address, Money
  • Domain Events:如 OrderCreatedEvent
  • Interfaces:仓储接口(IOrderRepository)、领域服务接口
  • Enums / Exceptions:业务异常(InsufficientBalanceException

特点:零外部 NuGet 包依赖,100% 聚焦业务规则。

2. Application 层 —— 用例协调者

  • Commands / Queries:使用 MediatR 定义操作(如 CreateOrderCommand
  • DTOs:请求/响应模型(CreateOrderRequest, OrderDto
  • Validators:基于 FluentValidation 的输入校验
  • Behaviors:管道行为(日志、事务、授权)
  • Implementations:调用 Domain 层执行业务

特点:依赖 Domain,不依赖 Infrastructure 或 Web。

3. Infrastructure 层 —— 技术实现

  • Persistence:EF Core DbContext、仓储实现
  • Services:邮件发送、文件上传、第三方 API 封装
  • Dependency Injection:注册所有服务(AddInfrastructure 扩展方法)

特点:实现 Domain 中定义的接口,完成“脏活”。

4. WebApi 层 —— 对外暴露

  • Controllers:极薄,仅转发请求给 MediatR
  • Program.cs:配置 DI、中间件、Swagger
  • appsettings.json:配置管理

特点:可随时替换为 gRPC、Worker Service 或 Blazor Server。


三、关键代码示例

1. 定义聚合根(Domain)

// Domain/Orders/Order.cs
public class Order : AggregateRoot
{
    public Guid CustomerId { get; private set; }
    public DateTime CreatedAt { get; private set; }
    public OrderStatus Status { get; private set; }

    public static Order Create(Guid customerId)
    {
        var order = new Order
        {
            Id = Guid.NewGuid(),
            CustomerId = customerId,
            CreatedAt = DateTime.UtcNow,
            Status = OrderStatus.Pending
        };
        order.AddDomainEvent(new OrderCreatedEvent(order.Id));
        return order;
    }

    public void Approve() => Status = OrderStatus.Approved;
}

2. 应用层命令处理(Application)

// Application/Orders/CreateOrderCommand.cs
public record CreateOrderCommand(Guid CustomerId) : IRequest<Guid>;

public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, Guid>
{
    private readonly IOrderRepository _orderRepository;
    private readonly IUnitOfWork _unitOfWork;

    public CreateOrderCommandHandler(IOrderRepository orderRepository, IUnitOfWork unitOfWork)
    {
        _orderRepository = orderRepository;
        _unitOfWork = unitOfWork;
    }

    public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken ct)
    {
        var order = Order.Create(request.CustomerId);
        await _orderRepository.AddAsync(order, ct);
        await _unitOfWork.SaveChangesAsync(ct); // 提交事务
        return order.Id;
    }
}

3. 控制器(WebApi)

// WebApi/Controllers/OrdersController.cs
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly IMediator _mediator;

    public OrdersController(IMediator mediator) => _mediator = mediator;

    [HttpPost]
    public async Task<Guid> Create(CreateOrderCommand command)
        => await _mediator.Send(command);
}

四、为什么选择 Ncp.CleanDDD 类模板?

优势说明
清晰分层业务与技术分离,新人易上手
测试友好Domain 和 Application 可独立单元测试
演进灵活可轻松替换数据库、消息队列或前端
社区成熟基于大量实战经验,避免“纸上谈兵”式 DDD

五、快速启动项目

  1. 克隆模板(假设存在 GitHub 仓库):

    git clone https://github.com/your-org/Ncp.CleanDDD.Template.git MyProject
    cd MyProject
    dotnet new --install ./template/
    dotnet new cleanddd -n MyECommerceApp
    
  2. 或手动创建结构,参考 Jason Taylor 的 CleanArchitecture 并融入 DDD 聚合设计。


六、结语

Ncp.CleanDDD 不是一个框架,而是一种架构约定。它通过标准化项目结构,帮助团队聚焦领域建模,避免陷入“技术细节先行”的陷阱。对于中大型业务系统,采用此类模板可显著提升代码可维护性、团队协作效率和长期演进能力。

📌 建议:不要盲目套用所有概念。从小聚合开始,逐步引入领域事件、防腐层(ACL)、Saga 等高级模式。

通过 Ncp.CleanDDD 这样的模板,DDD 不再是“空中楼阁”,而是可落地、可迭代、可持续的工程实践。立即尝试,让你的 .NET 项目从“能跑”走向“优雅”。