CleanArchitecture 项目分析
清洁架构之项目分析
一、Core (Domain Model) Project 领域模型项目,领域层
- 在清洁架构中,中心焦点应该是实体 Entities 和业务规则 business logic。
- 在领域驱动设计中,这个项目就是领域模型。
- 该项目应包含所有实体、值对象和业务逻辑 Entities, Value Objects, and business logic.
- 相关且应一起变更 change 的实体应分组grouped成一个聚合 Aggregate,以实现高内聚。例如:订单和订单明细,即为紧偶合的相关实例。
- 实体Entities应利用封装并应尽量减少公共设置器 public setters.
- 实体可以利用领域事件 Domain Events 将更改传达给系统的其他部分
- 可以为实体定义用于查询它们的规范 Specifications。即: Sql 查询条件,表关联,可重复使用
- 对于实例的变更处理,应通过存储库接口Repository interface(访问数据库的仓储模式)访问实体
- 只读即时查询可以使用单独 的查询服务Query Services,而不使用领域模型Domain Model
在这里查看示例:
https://github.com/ardalis/CleanArchitecture/tree/main/sample
二、Use Cases Project 用例项目,应用层
- 在清洁架构中,用例(或应用程序服务)项目 Use Cases (or Application Services)是包装域模型的相对较薄的层。
- 用例Use Cases通常按功能组织。 这些可能是简单的 CRUD 操作或更复杂的活动。
- 用例不应直接依赖于基础设施项目 infrastructure,这使得它们在大多数情况下易于进行单元测试。
- 用例通常按照 CQRS 分为命令和查询。
- 将用例作为单独的项目可以减少 UI 和基础设施项目中的逻辑量。
- 对于更简单的项目,可以省略 Use Cases 项目,并将其行为移至 UI 项目中,作为单独的服务或 MediatR 处理程序,或者简单地将逻辑放入 API 端点中。
三、Infrastructure Project 基础设施项目 ,实现层
- 在清洁架构中,基础设施问题与核心业务规则解耦,即业务逻辑与具体实现之间应该解耦
- 唯一应该包含与 EFCore、文件、电子邮件、Web 服务、Azure/AWS/GCP 等相关的代码的项目是基础设施。即:具体的实现操作功能
- 基础设施应依赖于存在抽象(接口)的领域层(以及可选的应用层)
- 基础设施类实现领域层(应用层)项目中的接口。
- 这些实现在项目启动时使用 DI 注入。 在本例中,使用项目中定义的“Microsoft.Extensions.DependencyInjection”和扩展方法。
using Ardalis.GuardClauses; using Ardalis.SharedKernel; using CleanProject.Core.Interfaces; using CleanProject.Core.Services; using CleanProject.Infrastructure.Data; using CleanProject.Infrastructure.Data.Queries; using CleanProject.Infrastructure.Email; using CleanProject.UseCases.Contributors.List; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace CleanProject.Infrastructure; public static class InfrastructureServiceExtensions { public static IServiceCollection AddInfrastructureServices( this IServiceCollection services, ConfigurationManager config, ILogger logger) { string? connectionString = config.GetConnectionString("DefaultConnection"); Guard.Against.Null(connectionString); services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString)); services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>)); services.AddScoped(typeof(IReadRepository<>), typeof(EfRepository<>)); services.AddScoped<IListContributorsQueryService, ListContributorsQueryService>(); services.AddScoped<IDeleteContributorService, DeleteContributorService>(); services.Configure<MailserverConfiguration>(config.GetSection("Mailserver")); logger.LogInformation("{Project} services registered", "Infrastructure"); return services; } }