惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
雷峰网
雷峰网
小众软件
小众软件
博客园 - 【当耐特】
J
Java Code Geeks
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
Engineering at Meta
Engineering at Meta
aimingoo的专栏
aimingoo的专栏
A
About on SuperTechFans
H
Help Net Security
博客园_首页
P
Proofpoint News Feed
GbyAI
GbyAI
大猫的无限游戏
大猫的无限游戏
N
Netflix TechBlog - Medium
爱范儿
爱范儿
MyScale Blog
MyScale Blog
Blog — PlanetScale
Blog — PlanetScale
The Cloudflare Blog
MongoDB | Blog
MongoDB | Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Google DeepMind News
Google DeepMind News

博客园 - lightsong

LoRA unsloth比transformer库本身的微调有什么优点? offline-llms +++ transformer + peft 微调 Train and Fine-Tune Sentence Transformers Models Symmetric vs. Asymmetric Semantic Search Hierarchical Navigable Small Worlds (HNSW) Vision Transformer + BentoML ML Serving/编排工具 Introducing Gemma 3 270M: The compact model for hyper-efficient AI Utopia -- 企业世界模型 trustgraph semantica semantica vs graphti Industrial-Strength Natural Language Processing seata reference with springboot and other valuable demo outbox pattern with springboot Saga pattern with springboot 基于 Sentence Transformers 的具体应用案例 Vault with Keycloak as workload IAM Ontology Reasoning System ADR Claude Code的hook The AI-Native SDLC playbook Introduction to Dapper Introduction to FluentValidation Introduction to AutoFixture Introduction to FluentAssertions Understanding Return Types: IEnumerable, IReadOnlyCollection, and List Introduction to Refit Introduction to Carter
A Complete Guide to Clean Architecture
lightsong · 2026-08-25 · via 博客园 - lightsong

A Complete Guide to Clean Architecture

https://jdaniel1987.github.io/CleanArchitecture

image

这篇博文的核心在于通过分层来解耦,而 Program.cs 正是实现这种解耦的“总装车间”。将两者结合,能完美地展示从理论到实践的闭环。

https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/architectural-principles

image

https://github.com/fanqingsong/CleanArchitecture_extension

https://github.com/fanqingsong/CleanArchitecture/tree/main/MinimalClean


🏛️ 整洁架构实战:用“构造与运行分离”打造纯净核心

整洁架构(Clean Architecture)由罗伯特·C·马丁(Robert C. Martin,又称 Uncle Bob)推广,它强调通过清晰的分层和边界来分离软件系统,确保业务逻辑独立于 UI、数据库或框架等外部细节。这种分离使得系统更易于维护、测试和扩展。

本文将深入探讨整洁架构的核心概念,并展示如何通过“构造与运行分离”这一关键实践,在 .NET 项目中落地这些原则。

🧠 整洁架构的核心原则

整洁架构的魅力在于其清晰的规则,这些规则共同守护着核心业务逻辑的纯净。

1. 关注点分离 (Separation of Concerns)
整洁架构通过将代码组织成不同的层来实现清晰的职责划分。依赖关系应该单向流动:从外层(基础设施、UI)指向内层(业务逻辑)。

2. 依赖倒置原则 (Dependency Inversion Principle, DIP)
这是实现解耦的基石。它指出:高层模块不应该依赖低层模块,二者都应该依赖其抽象

在整洁架构中,这意味着我们的业务逻辑(高层模块)只依赖接口,而具体的数据库或外部服务实现(低层模块)也去实现这些接口。

示例:依赖倒置

// 高层模块 - 业务逻辑
public class OrderService
{
    private readonly IOrderRepository _orderRepository;

    // 依赖通过构造函数注入,只依赖抽象 IOrderRepository
    public OrderService(IOrderRepository orderRepository)
    {
        _orderRepository = orderRepository;
    }

    public void PlaceOrder(Order order)
    {
        // 业务逻辑
        _orderRepository.Save(order);
    }
}

// 低层模块 - 具体实现
public class SqlOrderRepository : IOrderRepository
{
    public void Save(Order order)
    {
        // 将订单保存到 SQL 数据库
    }
}

3. 实体 (Entities)
实体是封装了企业级业务规则的核心业务对象。它们应该完全独立于外部服务、数据库和 UI。

public class Order
{
    public Guid Id { get; set; }
    public DateTime OrderDate { get; set; }
    public Customer Customer { get; set; }
    public List<OrderItem> Items { get; set; }

    // 业务逻辑:计算订单总额
    public decimal TotalAmount => Items.Sum(item => item.Price * item.Quantity);
}

4. 用例 (Use Cases / Application Layer)
用例层包含特定于应用程序的业务逻辑。它协调实体和外部服务(如仓储、通知)之间的交互,但同样是通过抽象接口进行的。

public class PlaceOrderUseCase
{
    private readonly IOrderRepository _orderRepository;
    private readonly IPaymentService _paymentService;

    public PlaceOrderUseCase(IOrderRepository orderRepository, IPaymentService paymentService)
    {
        _orderRepository = orderRepository;
        _paymentService = paymentService;
    }

    public void Execute(Order order)
    {
        // 协调业务逻辑
        _paymentService.ProcessPayment(order);
        _orderRepository.Save(order);
    }
}

5. 接口适配器 (Interface Adapters)
这一层负责数据格式的转换。例如,将数据库的数据模型转换为用例层需要的实体,或将实体转换为 UI 层需要的 DTO。

public class OrderDto
{
    public Guid Id { get; set; }
    public DateTime OrderDate { get; set; }
    public string CustomerName { get; set; }
}

// 在某个 Mapper 类中
public OrderDto ToOrderDto(Order order)
{
    return new OrderDto()
    {
        Id = order.Id,
        OrderDate = order.OrderDate,
        CustomerName = order.Customer.Name
    };
}

6. 框架与外部工具 (Frameworks and External Tools)
最外层由数据库、Web 框架等具体技术实现组成。它们不包含业务逻辑,只负责实现内层定义的接口。

🏗️ 整洁架构的分层结构

整洁架构通常被描绘成同心圆,依赖关系由外向内。

  • 表现层 (Presentation):负责与用户交互,如 MVC 控制器、Razor 页面或 API 端点。
  • 基础设施层 (Infrastructure):提供技术能力,如数据库访问(Entity Framework)、发送邮件、日志记录等。
  • 应用层 (Application):包含用例和应用程序特定的逻辑,协调数据流。
  • 领域层 (Domain):核心,包含实体、值对象和核心业务规则。

🔗 依赖方向 vs 数据流向

一个常见的误区是混淆依赖方向和数据流向。

  • 依赖方向:代码的引用关系,始终由外层指向内层。
  • 数据流向:请求和响应的流动路径,通常是从表现层进入,穿过各层到达领域层,再原路返回。

🚀 实践关键:构造与运行分离

理解了分层和依赖倒置,我们如何实现它?答案就是“构造与运行分离”。这个思想在 .NET 中通过依赖注入(DI)容器完美实现。

  • 构造 (Construction):负责创建对象及其所有依赖。这发生在应用程序启动时,在一个集中的地方,称为“组合根”(Composition Root)。
  • 运行 (Runtime):负责执行具体的业务逻辑。运行时的对象(如 OrderService)不关心依赖是如何创建的,只通过构造函数接收它们。

在 ASP.NET Core 中,Program.cs 文件就是我们的“组合根”。

完整的 Program.cs 示例

using Infrastructure; // 基础设施层
using Application;    // 应用层
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// ==============================================================================
// 1. 构造阶段 (Construction Phase)
// ==============================================================================
// 这是“组合根”,所有依赖关系都在这里集中配置。
// 业务逻辑层(Application 和 Domain)完全不知道这里的存在。

// --- 1.1 添加框架服务 ---
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// --- 1.2 添加基础设施层服务 ---
// 配置数据库上下文
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// 注册具体实现:当需要 IOrderRepository 时,提供 SqlOrderRepository 实例
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
builder.Services.AddScoped<IEmailSender, SmtpEmailSender>();

// --- 1.3 添加应用层服务 ---
// 注册用例或 MediatR
builder.Services.AddScoped<PlaceOrderUseCase>();

var app = builder.Build();

// ==============================================================================
// 2. 运行阶段 (Runtime Phase)
// ==============================================================================
// 配置 HTTP 请求处理管道。应用程序开始监听并响应请求。

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

这段代码清晰地展示了分离:

  1. 构造阶段:在 builder 部分,我们告诉 DI 容器如何组装对象。例如,AddScoped<IOrderRepository, SqlOrderRepository>() 这条规则,就是连接抽象与实现的桥梁。
  2. 运行阶段app.Run() 之后,当请求到达 OrderController 时,框架会自动根据我们设定的规则,创建 PlaceOrderUseCase,并自动注入它所需的 IOrderRepository 实现。业务代码本身完全干净,不涉及任何 new 操作。

✨ 整洁架构的优势与挑战

优势

  • 可维护性:关注点分离,修改外部框架或数据库对核心业务影响极小。
  • 可测试性:业务逻辑不依赖外部资源,可以轻松编写单元测试。
  • 灵活性:可以轻松替换 UI 框架、数据库或任何外部服务。

挑战

  • 复杂性:对于小型项目,过多的抽象和分层可能显得繁琐。
  • 学习曲线:团队需要理解依赖倒置、依赖注入等概念才能有效实施。

📌 总结

整洁架构提供了一套强大的原则来构建可维护、可测试和灵活的系统。而“构造与运行分离”是实现这些原则的关键实践。通过在 Program.cs 中集中管理对象的创建,我们可以确保核心业务逻辑的纯净和独立,从而构建出真正健壮的软件。

出处:http://www.cnblogs.com/lightsong/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。