AI技能包赋能.NET整洁架构:27个技能提升开发效率与代码一致性
1. 项目概述用AI技能包重塑.NET整洁架构开发体验如果你和我一样在.NET领域摸爬滚打了几年肯定经历过这样的场景每次启动一个新项目都要重新搭建一遍整洁架构的架子从领域层到基础设施层各种模式、接口、配置一遍遍地复制粘贴。更头疼的是当你试图用GitHub Copilot或者Claude Code这类AI助手来加速开发时你会发现它生成的代码风格各异有时候是贫血模型有时候又忘了加验证你不得不花大量时间在代码审查和重构上反复向AI解释“这里要用私有setter”、“那里要加领域事件”。这就是我接触到ronnythedev/dotnet-clean-architecture-skills这个项目时感觉眼前一亮的原因。它不是一个框架也不是一个代码生成器而是一套精心设计的“AI技能包”。简单来说它教会你的AI编码助手Claude Code、GitHub Copilot、Cursor如何按照生产级的整洁架构、CQRS和DDD模式来生成代码。你不用再在每次提示词里重复解释那些设计模式只需要说“用04-domain-entity-generator技能创建一个产品聚合根”AI就能吐出一套风格统一、包含工厂方法、私有setter、领域事件和仓储接口的标准代码。这套技能包包含了27个独立的技能覆盖了从项目脚手架、领域建模、CQRS实现、数据访问、安全认证到测试的完整开发生命周期。它解决的核心痛点就是让AI生成的代码从一开始就符合团队约定的最佳实践极大减少了模式不一致带来的技术债务和沟通成本。无论你是正在从传统三层架构向整洁架构迁移还是希望在新项目中快速落地一套规范的技术栈这套技能包都能让你和你的AI助手配合得更默契。2. 核心设计理念与技能包架构解析2.1 从“描述模式”到“调用技能”的范式转变传统的AI辅助编码我们和工具的交互模式是“描述需求解释模式”。比如你想要一个遵循DDD的实体你得写“创建一个Product实体作为聚合根包含Name必填最大长度200、Price正小数和CategoryId外键。请使用私有setter提供一个静态的Create工厂方法创建成功时发布一个ProductCreated领域事件并定义对应的仓储接口。”这个过程冗长且容易遗漏细节。而dotnet-clean-architecture-skills引入了一种新的范式技能调用。它将上述一长串描述封装成了一个名为04-domain-entity-generator的技能。现在你的提示词简化为“使用技能04-domain-entity-generator创建一个Product聚合根包含Name必填最大长度200、Price正小数和CategoryId外键。”背后的逻辑是每个技能都是一个自包含的“知识胶囊”里面定义了目标模式要生成什么如DDD实体。代码模板具体的代码结构、命名约定、设计选择如用record类型定义命令用ResultT处理错误。上下文关联该技能如何与其他技能衔接如实体生成器技能知道要同时生成对应的仓储接口。最佳实践与反模式提醒AI避免生成哪些不好的代码。这种转变带来的直接好处是提示词效率的指数级提升和代码风格的高度一致性。团队新成员或者AI不需要深刻理解每个模式的所有细节只需要知道“调用哪个技能能达到什么目的”就能产出符合标准的代码。2.2 分层架构与技能映射这套技能包严格遵循经典的整洁架构分层并将每一层的具体实现细节封装成了对应的技能。理解这个映射关系是有效使用它的关键。领域层Domain Layer这是业务核心不依赖任何外部框架。对应的技能确保你的业务模型纯净且富有表达力。04-domain-entity-generator 这是基石。它生成的不是简单的POCO类而是真正的DDD实体。你会得到带有private setter的属性、基于业务规则的验证在构造函数或工厂方法内、唯一的身份标识如ProductId、以及可选的领域事件定义。它强制你思考“这个对象如何被创建和变更”而不是简单地暴露一堆公共属性。09-domain-events-generator 用于实现事件驱动设计。技能会引导AI生成轻量的、不可变的领域事件类如ProductPriceChangedDomainEvent以及对应的事件处理器接口。它通常会与14-outbox-pattern技能结合确保事件发布的可靠性。08-result-pattern 错误处理的艺术。它用Result和ResultT类型替代简单的异常抛出或返回null。这让你的领域服务和应用层服务的方法签名变得非常清晰明确声明了可能发生的错误类型比如ResultProduct Create(string name, decimal price)调用方必须处理Success或Failure的情况。20-specification-pattern 封装复杂的查询逻辑。将“获取所有上架且价格低于100元的产品”这样的业务规则封装成一个ProductIsActiveAndUnderPriceSpecification类避免查询逻辑在应用层或仓储中扩散提升可测试性和复用性。应用层Application Layer协调领域对象完成用例是业务逻辑的编排者。这里主要采用CQRS模式。02-cqrs-command-generator03-cqrs-query-generator CQRS的核心技能。命令生成器会创建Command/CommandHandler/Validator这一套组合拳。查询生成器则倾向于生成简单的Query/QueryHandler并常常与19-dapper-query-builder技能搭配为读操作优化性能。它们都内置了对MediatR库的集成。11-fluent-validation 专用于命令/查询的输入验证。技能模板会生成继承自AbstractValidatorT的验证器包含同步和异步的验证规则并确保这些验证器被正确地注册到DI容器中并通过10-pipeline-behaviors技能提供的管道行为自动执行。10-pipeline-behaviors 实现横切关注点。日志、性能监控、验证、事务——这些都不应该污染业务处理器。这个技能教你创建IPipelineBehavior的实现并以装饰者模式注入到MediatR的处理管道中让业务代码保持干净。基础设施层Infrastructure Layer包含所有外部依赖的实现是变化最多的一层。技能包在这里提供了丰富的、可插拔的选项。05-repository-pattern06-ef-core-configuration 数据访问的黄金搭档。仓储模式技能定义清晰的接口如IProductRepository而EF配置技能则提供具体的实现和精细化的Fluent API映射配置索引、关系、并发令牌等。这严格遵循了依赖倒置原则。19-dapper-query-builder 针对复杂查询或性能敏感读操作的优化方案。它提供了使用Dapper进行多表映射、动态条件构建和分页查询的模板与EF Core的写模型形成互补。14-outbox-pattern15-quartz-background-jobs 实现可靠的后台处理。领域事件发布后不是直接发送到消息总线而是作为一条记录持久化到数据库的“发件箱”Outbox表。然后由一个后台Quartz作业定期扫描并处理这些事件确保至少一次投递解决了分布式事务难题。16-email-service-*18-audit-trail 其他外部集成的样板。邮件服务提供了适配不同提供商SendGrid, AWS SES的统一接口。审计追踪技能则通过EF Core拦截器自动记录实体的创建/修改人和时间。表现层API Layer暴露API端点处理HTTP请求/响应。07.1-legacy-api-controllers07.2-minimal-api-endpoints 适应不同的API风格。无论是传统的基于Controller的MVC API还是.NET 6推崇的Minimal API都有对应的技能来生成结构清晰、包含认证授权、版本管理、模型绑定的端点代码。12-jwt-authentication13-permission-authorization 安全基石。JWT认证技能处理令牌的生成、刷新和验证。权限授权技能则实现基于声明的细粒度访问控制例如[HasPermission(“product:write”)]这样的属性注解。2.3 技能包的组织哲学模块化与可组合性这是该项目最精妙的设计之一。27个技能并非一个庞然大物而是高度模块化的。你可以像搭积木一样只选取你项目需要的部分。无强制耦合 你可以只用04-domain-entity-generator和08-result-pattern来规范领域层而不采用CQRS。你也可以在已有项目中单独引入24-rate-limiting技能来增加API限流而不影响其他部分。“配方”Recipes引导 对于新手或常见场景项目提供了“配方”Recipes。例如“配方1添加一个CRUD功能”就清晰地告诉你按顺序组合使用技能04实体、02命令、03查询、11验证、07API就能快速搭建一个完整的功能模块。这极大地降低了学习曲线。技术栈中立性 技能包核心是模式和约定它推荐了如PostgreSQL/SQL Server、Dapper、Serilog等技术但技能模板本身并不强制绑定某个特定库的某个版本除非该技能就是为该库定制的如06-ef-core-configuration。你完全可以根据自己团队的技术选型进行调整。3. 深度实操从零开始应用技能包构建用户管理模块理论说得再多不如亲手搭一遍。我们假设要为一个内部管理系统构建一个用户管理模块包含用户的创建、查询、更新和删除软删除。我们将使用这套技能包并选择Minimal API PostgreSQL CQRS的技术组合。3.1 环境准备与技能安装首先确保你的开发环境已经就绪安装.NET 8 SDK。安装IDE/编辑器 Visual Studio 2022、VS Code或Rider并确保已安装GitHub Copilot或Claude Code插件。获取技能包 推荐使用克隆仓库的方式这样能获得所有技能和配方文档。git clone https://github.com/ronnydelgado/dotnet-clean-architecture-skills.git为你的项目启用技能Claude Code 在项目根目录创建.claude/skills/文件夹然后将克隆的skills/目录下的所有子文件夹如01-dotnet-clean-architecture复制进去。或者直接建立一个符号链接ln -s /path/to/dotnet-clean-architecture-skills/skills .claude/skills。GitHub Copilot 更简单直接在项目根目录创建一个skills/文件夹把技能子文件夹复制进去即可。Copilot会自动读取该目录下的技能。实操心得路径与生效我第一次使用时把技能文件夹放错了位置导致AI完全“看不见”它们。关键是要弄清楚你的AI工具从哪里读取技能。Claude Code通常看项目内的.claude/skills或用户全局的~/.claude/skills。GitHub Copilot则读取项目内skills/文件夹。最稳妥的方法是先在项目里用AI生成一个简单类然后打开它的“Completions Panel”或类似功能看看它引用了哪些上下文文件就能确定技能目录是否正确加载。3.2 遵循“配方”搭建项目骨架对于一个全新项目我们从“配方0搭建新项目”开始。虽然我们可以手动执行但思路是遵循它的指引。创建解决方案与项目 手动或使用dotnet new sln和dotnet new webapi等命令创建出src/放核心项目、tests/放测试项目的目录结构。对应技能01-dotnet-clean-architecture提供了理想的项目结构模板。安装核心NuGet包 根据Technology Stack表格在对应的项目如Application层安装MediatR、FluentValidation、MediatR.Extensions.FluentValidation等包。在Infrastructure层安装Npgsql.EntityFrameworkCore.PostgreSQL、Dapper、Quartz等。配置基础设施 参考技能17-health-checks和23-logging-configuration在Program.cs或启动类中配置Serilog结构化日志和健康检查端点。这是生产级应用的基础。设置数据库上下文 参考技能06-ef-core-configuration创建你的AppDbContext并在其中配置模型。同时应用技能18-audit-trail通过实现IAuditable接口和配置拦截器为实体自动添加CreatedBy,CreatedOn,ModifiedBy,ModifiedOn等审计字段。此时你的解决方案大概长这样MyCompany.ManagementSystem.sln ├── src/ │ ├── MyCompany.ManagementSystem.Domain/ (领域模型实体值对象领域事件) │ ├── MyCompany.ManagementSystem.Application/ (用例CQRS 接口) │ ├── MyCompany.ManagementSystem.Infrastructure/ (EF Core, Dapper, 邮件等实现) │ └── MyCompany.ManagementSystem.Api/ (Minimal API 端点) └── tests/ ├── MyCompany.ManagementSystem.UnitTests/ └── MyCompany.ManagementSystem.IntegrationTests/3.3 使用技能驱动开发用户聚合根现在进入具体的功能开发。我们打开MyCompany.ManagementSystem.Domain项目准备创建User聚合根。不使用技能的提示词低效且易出错“在Domain项目里创建一个User类作为聚合根。属性要有Id (Guid) UserName (字符串必填唯一) Email (字符串必填邮箱格式) HashedPassword (字符串) IsActive (布尔值默认true)。属性都用私有setter。提供一个Create静态方法来创建用户传入用户名、邮箱和明文密码在方法里检查用户名和邮箱是否为空邮箱格式对不对然后给密码加盐哈希最后返回User对象。再提供一个ChangeEmail方法可以改邮箱要验证新邮箱格式并且发布一个UserEmailChangedDomainEvent领域事件。再定义一个IUserRepository接口里面有Add, GetById, GetByUserName, Update方法。”使用技能的提示词高效且标准“在MyCompany.ManagementSystem.Domain项目中使用技能04-domain-entity-generator创建一个User聚合根。要求如下属性UserId(Guid, 主键)UserName(string, 必填最大50字符唯一)Email(string, 必填需符合邮箱格式)HashedPassword(string)IsActive(bool, 默认true)。需要一个Create工厂方法接收userName,email,plainPassword参数。在方法内验证参数并对明文密码进行哈希处理假设有一个IPasswordHasher服务可通过依赖注入在应用层调用领域层只定义接口。需要一个ChangeEmail方法接收新邮箱验证格式后更新并发布一个UserEmailChangedDomainEvent领域事件。同时生成对应的IUserRepository接口。”AI在技能指导下可能会生成如下核心代码// 在 Domain 项目中 namespace MyCompany.ManagementSystem.Domain.Users; // 技能引导生成的领域事件 public sealed record UserEmailChangedDomainEvent(Guid UserId, string OldEmail, string NewEmail) : IDomainEvent; // 技能引导生成的实体 public sealed class User : AggregateRoot, IAuditable { public Guid UserId { get; private set; } public string UserName { get; private set; } string.Empty; public string Email { get; private set; } string.Empty; public string HashedPassword { get; private set; } string.Empty; public bool IsActive { get; private set; } true; // 审计字段 (来自技能18) public string CreatedBy { get; set; } string.Empty; public DateTime CreatedOn { get; set; } public string? ModifiedBy { get; set; } public DateTime? ModifiedOn { get; set; } // 私有构造函数强制使用工厂方法 private User() { } // 工厂方法 - 技能模板会引导包含参数验证和错误返回 public static ResultUser Create(string userName, string email, IPasswordHasher passwordHasher, string plainPassword) { // 验证逻辑 (技能04的模板通常会引导使用Guard子句或FluentValidation结果) if (string.IsNullOrWhiteSpace(userName)) return Result.FailureUser(DomainErrors.User.UserNameEmpty); if (string.IsNullOrWhiteSpace(email) || !new EmailAddressAttribute().IsValid(email)) return Result.FailureUser(DomainErrors.User.InvalidEmail); var hashedPassword passwordHasher.Hash(plainPassword); // 依赖在应用层注入 var user new User { UserId Guid.NewGuid(), UserName userName.Trim(), Email email.Trim().ToLowerInvariant(), HashedPassword hashedPassword, IsActive true, CreatedOn DateTime.UtcNow, // CreatedBy 将在应用层处理器中由当前用户服务设置 }; // 技能模板可能会引导发布一个 UserCreatedDomainEvent // user.RaiseDomainEvent(new UserCreatedDomainEvent(user.UserId)); return user; } public Result ChangeEmail(string newEmail) { if (string.IsNullOrWhiteSpace(newEmail) || !new EmailAddressAttribute().IsValid(newEmail)) return Result.Failure(DomainErrors.User.InvalidEmail); var oldEmail Email; Email newEmail.Trim().ToLowerInvariant(); ModifiedOn DateTime.UtcNow; // 发布领域事件 (技能09) RaiseDomainEvent(new UserEmailChangedDomainEvent(UserId, oldEmail, Email)); return Result.Success(); } // 其他业务方法如 Deactivate, ChangePassword 等 } // 技能引导生成的错误类型 (与技能08 Result模式配套) public static partial class DomainErrors { public static class User { public static readonly Error UserNameEmpty new( User.UserNameEmpty, User name cannot be empty.); public static readonly Error InvalidEmail new( User.InvalidEmail, The provided email address is invalid.); // ... 更多错误 } } // 技能引导生成的仓储接口 (技能05) public interface IUserRepository : IRepositoryUser { TaskUser? GetByIdAsync(Guid userId, CancellationToken cancellationToken default); TaskUser? GetByUserNameAsync(string userName, CancellationToken cancellationToken default); Taskbool IsUserNameUniqueAsync(string userName, CancellationToken cancellationToken default); // AddAsync 和 UpdateAsync 可能已在 IRepositoryT 中定义 }注意事项密码哈希的领域归属这是一个经典的DDD边界讨论。在上面的示例中IPasswordHasher接口定义在领域层但具体实现如使用BCrypt或Argon2在基础设施层。工厂方法Create接收这个接口来执行哈希操作。另一种做法是将明文密码作为参数传入哈希操作在应用层的命令处理器中完成。技能包模板倾向于前者因为它将“密码必须被哈希”这一核心业务规则约束在了领域实体内部即使调用方忘记了实体创建也会失败。你需要根据团队对领域纯洁性和实用性的权衡来决定。3.4 构建应用层用例创建用户命令有了领域模型接下来在MyCompany.ManagementSystem.Application项目中实现“创建用户”这个用例。我们使用技能02-cqrs-command-generator。给AI的提示词“在Application.Users.Commands命名空间下使用技能02-cqrs-command-generator创建一个CreateUserCommand。它包含UserName,Email,Password属性。同时生成对应的CreateUserCommandHandler和CreateUserCommandValidator。Handler需要调用之前定义的User.Create工厂方法并依赖IUserRepository和IPasswordHasher。使用Result模式返回操作结果。”AI生成的代码骨架会非常标准// Application.Users.Commands.CreateUser // 命令对象 (通常是record不可变) public sealed record CreateUserCommand(string UserName, string Email, string Password) : ICommandResultGuid; // 验证器 (技能11) public sealed class CreateUserCommandValidator : AbstractValidatorCreateUserCommand { public CreateUserCommandValidator() { RuleFor(x x.UserName) .NotEmpty().WithMessage(UserName is required.) .MaximumLength(50).WithMessage(UserName must not exceed 50 characters.); RuleFor(x x.Email) .NotEmpty().WithMessage(Email is required.) .EmailAddress().WithMessage(A valid email address is required.); RuleFor(x x.Password) .NotEmpty().WithMessage(Password is required.) .MinimumLength(8).WithMessage(Password must be at least 8 characters long.) .Matches([A-Z]).WithMessage(Password must contain at least one uppercase letter.) .Matches([a-z]).WithMessage(Password must contain at least one lowercase letter.) .Matches(\d).WithMessage(Password must contain at least one number.); } } // 命令处理器 internal sealed class CreateUserCommandHandler : ICommandHandlerCreateUserCommand, ResultGuid { private readonly IUserRepository _userRepository; private readonly IPasswordHasher _passwordHasher; private readonly IUnitOfWork _unitOfWork; // 假设有工作单元技能 public CreateUserCommandHandler(IUserRepository userRepository, IPasswordHasher passwordHasher, IUnitOfWork unitOfWork) { _userRepository userRepository; _passwordHasher passwordHasher; _unitOfWork unitOfWork; } public async TaskResultGuid Handle(CreateUserCommand request, CancellationToken cancellationToken) { // 1. 业务规则验证如用户名唯一性这里可能涉及数据库查询 var isUserNameUnique await _userRepository.IsUserNameUniqueAsync(request.UserName, cancellationToken); if (!isUserNameUnique) { return Result.FailureGuid(ApplicationErrors.Users.UserNameAlreadyExists(request.UserName)); } // 2. 调用领域工厂创建实体 var userResult User.Create(request.UserName, request.Email, _passwordHasher, request.Password); if (userResult.IsFailure) { return Result.FailureGuid(userResult.Error); } var user userResult.Value; // 设置审计信息例如从当前用户服务获取 user.CreatedBy system; // 应从 ICurrentUserService 获取 // 3. 持久化 _userRepository.Add(user); await _unitOfWork.SaveChangesAsync(cancellationToken); // 工作单元提交包含领域事件调度 // 4. 返回成功结果 return Result.Success(user.UserId); } }3.5 暴露API端点与配置依赖注入最后在API层使用技能07.2-minimal-api-endpoints创建端点并配置所有依赖。API端点// 在 Api 项目中 app.MapPost(/api/users, async (CreateUserCommand command, ISender sender, CancellationToken cancellationToken) { var result await sender.Send(command, cancellationToken); return result.Match( onSuccess: userId Results.Created($/api/users/{userId}, new { UserId userId }), onFailure: error Results.Problem( title: Could not create user, detail: error.Message, statusCode: GetStatusCode(error) // 根据错误类型映射HTTP状态码 ) ); }) .WithTags(Users) .RequireAuthorization() // 如果需要结合技能12/13 .ProducesGuid(StatusCodes.Status201Created) .ProducesProblem(StatusCodes.Status400BadRequest);依赖注入配置在基础设施层或API层的Program.cs 这是一个需要精细配置的环节技能包通过各技能的文档给出了指引。领域服务 注册IPasswordHasher的具体实现如BCryptPasswordHasher。应用层 通过services.AddMediatR()注册所有命令/查询处理器和验证器。通过services.AddValidatorsFromAssembly()注册FluentValidation验证器。基础设施层 注册IUserRepository的实现如EfUserRepository注册AppDbContext配置Quartz作业用于Outbox模式注册邮件服务等。管道行为 注册ValidationBehavior,LoggingBehavior,TransactionBehavior等。实操心得依赖注入的模块化组织手动在Program.cs里写几十行services.AddScoped很容易混乱。一个最佳实践是在每个项目特别是Infrastructure中创建一个DependencyInjection静态类里面包含一个Add[ProjectName]扩展方法。例如在Infrastructure项目中public static class DependencyInjection { public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) { services.AddScopedIUserRepository, EfUserRepository(); services.AddDbContextAppDbContext(options ...); services.AddQuartz(...); // ... 其他注册 return services; } }然后在Program.cs中只需一行builder.Services.AddInfrastructure(builder.Configuration);。技能包的模板虽然没有强制这样写但强烈推荐采用这种模式来保持启动代码的整洁。4. 高级技巧、常见问题与避坑指南4.1 技能包的定制化与扩展这套技能包是开源的这意味着你可以且应该根据自己团队的规范进行定制。不要把它当作黑盒。修改现有技能模板 如果你团队规定所有Id属性都叫Id而不是EntityId或者你更喜欢用Ardalis.Result而不是自定义的Result类直接去修改对应技能文件夹下的模板文件通常是.prompt或.md文件具体看技能包结构。这是让技能包真正为你所用的关键一步。创建自定义技能 如果团队有特有的模式或内部库你可以仿照现有技能的结构创建自己的技能。例如如果你公司统一使用一个特定的缓存库可以创建一个caching-with-redis技能教会AI如何生成缓存装饰器或缓存查询模式。管理技能版本 当你克隆仓库后可以将其作为项目的子模块git submodule或者定期拉取更新。但要注意上游的更新可能会覆盖你的定制。建议团队内部维护一个fork的版本定期有选择地合并上游更新。4.2 与不同AI助手的兼容性实践项目声称支持Claude Code、GitHub Copilot和Cursor。但在实际使用中细微差别需要注意。GitHub Copilot 它对项目内skills/目录的识别非常直接。你只需要把技能文件夹放进去在编写代码时Copilot会根据当前文件路径和上下文自动建议使用相关技能的代码片段。它的补全更“碎片化”可能一次只生成一个方法但连贯性很好。Claude Code 它更擅长处理长上下文和复杂的指令。你可以直接在新文件中输入“使用技能04创建一个XXX实体”它可能会生成一个更完整的文件。Claude Code对技能描述的阅读理解能力似乎更强。Cursor 作为后起之秀Cursor同样支持类似的技能/规则系统。你需要将技能文件放在Cursor能识别的特定目录如.cursor/rules并可能需要调整文件格式。具体需参考Cursor的文档。常见问题技能不生效或生成代码不符合预期检查技能加载路径 这是最常见的问题。用你的AI工具打开一个技能文件如skills/04-domain-entity-generator/README.md看看它是否能正确读取和理解其中的内容。有些工具可能需要重启IDE或重新索引。提示词不够具体 技能是指导不是魔法。你的提示词仍需清晰。例如“使用技能04”不如“使用技能04-domain-entity-generator创建一个Order聚合根包含OrderNumber字符串唯一和ListOrderLine集合”。提供具体的属性名和约束。上下文窗口限制 如果技能描述非常长而你的提示词也很长可能会超出AI的上下文窗口。尝试先让AI生成核心部分如实体类再通过后续对话补充其他部分如仓储接口。版本差异 技能包是基于特定版本的库如.NET 8, EF Core 8编写的。如果你的项目用的是旧版本生成的代码可能需要手动调整例如Top-Level Statements的API差异。4.3 性能与架构权衡思考引入这套模式尤其是CQRS和领域事件会带来一定的架构复杂度。技能包帮你解决了“如何做”的问题但“何时用”需要你自己判断。CQRS的适用性 对于简单的CRUD应用严格的CQRS读写分离模型可能过度设计。你可以先从“命令-查询职责分离”的思想入手即用MediatR处理命令但读操作仍直接通过仓储调用。技能包允许你只使用02-cqrs-command-generator而不使用03-cqrs-query-generator和19-dapper-query-builder。领域事件的滥用 领域事件用于解耦核心领域逻辑与副作用如发送邮件、更新报表。不要为了用事件而用事件。如果某个操作如“用户注册后发送欢迎邮件”是当前限界上下文的直接、同步的组成部分那么在应用层服务中直接调用邮件服务可能更简单清晰。技能09-domain-events-generator和14-outbox-pattern更适合用于跨上下文集成或需要保证最终一致性的场景。测试策略 技能21-unit-testing和22-integration-testing提供了测试模板。对于领域实体和值对象单元测试是核心。对于命令处理器由于依赖仓储等外部服务更适合用集成测试或使用Mock的单元测试。技能包引导的清晰分层和依赖注入使得测试变得相对容易。4.4 团队协作与知识传承这套技能包最大的价值或许不在于提升单个开发者的效率而在于统一团队认知和降低新人上手成本。作为团队规范 将定制好的技能包纳入团队代码仓库模板。新成员入职第一天配置好AI助手和技能包他写出的第一行代码就符合团队架构规范。这比一份无人阅读的架构文档有效得多。作为代码审查清单 技能包本身就是一个活的最佳实践清单。在代码审查时可以对照检查“这个实体符合04-domain-entity-generator的规范吗”“这个命令的验证器是否像11-fluent-validation技能描述的那样完备”促进架构讨论 当团队对某个模式比如是否使用Specification Pattern有分歧时可以一起研究对应的技能讨论其利弊并共同决定是否采用、如何修改。技能包成为了一个共同的技术锚点。从我个人的实践来看dotnet-clean-architecture-skills项目代表了一种未来软件工程的新范式将团队知识编码化、工具化。它不仅仅是一套AI提示词更是一份活的、可执行的架构决策记录。它不能替代开发者对设计模式的深入理解但它能极大地降低正确应用这些模式的门槛让团队能把更多精力聚焦在解决真正的业务问题上而不是反复争论代码应该怎么写。如果你和你的团队正在.NET整洁架构的道路上探索花一个下午时间尝试一下这个技能包很可能会让你和你的AI助手的工作方式发生一次质的改变。