干净的体系结构
使用ASP.NET Core的清洁体系结构的起点。干净的体系结构只是一系列名称中的最新架构,用于相同的松散耦合,依赖性与内向体系结构。您还会发现它名为Hexagonal,端口和适配器或洋葱架构。
在NimblePros的“清洁架构”课程中了解有关干净体系结构的更多信息和此模板。使用代码ardalis节省20%。
史蒂夫·史密斯(Steve Smith)和朱莉·莱尔曼(Julie Lerman)在DDD基础课程中使用了该架构。
?请与Steve的公司NimblePros联系,以进行清洁架构或DDD培训和/或为您的团队实施帮助。
上课程!
了解如何从NimblePros培训师Sarah“ Sadukie” Dutkiewicz和Steve“ Ardalis” Smith实施清洁建筑。
目录
- 干净的体系结构
- 故障排除铬错误
- 目录
- 给星星!
- 版本
- 了解更多
- 入门
- 使用dotnet CLI模板
- 控制器和剃须刀页面呢?
- 添加ardalis.apiendpoints
- 添加控制器
- 添加剃刀页
- 使用GitHub存储库
- 运行迁移
- 目标
- 历史记录和无耻的插头部分
- 设计决策和依赖项
- 在哪里验证
- 核心项目
- 用例项目
- 基础设施项目
- 网络项目
- ShareSherkernel项目
- 测试项目
- 使用的模式
- 域事件
- 相关项目
给星星!
如果您愿意或正在使用此项目学习或启动解决方案,请给它一颗星。谢谢!
或者,如果您真的很慷慨,我们现在支持GitHub赞助 – 请参阅上面的按钮。
赞助商
我请宣布,亚马逊AWS的FOSS基金已选择为该项目颁发12个月的赞助。谢谢您,感谢我所有其他过去和现在的赞助商!
故障排除铬错误
默认情况下,该网站使用HTTPS,并希望您拥有自签名的开发人员证书以供本地主机使用。如果您遇到了Chrome的错误,请参阅此答案以获取缓解说明。
版本
主分支现在使用.NET 9 。这与Nuget软件包版本10.x相对应。可以使用以前的版本 – 请参阅我们的发行版。
了解更多
- 实时流记录在干净的体系结构上工作
- Dotnetrocks播客与Steve“ Ardalis” Smith讨论
- 弗里茨(Fritz)和朋友与史蒂夫(Steve)的“ Ardalis” Smith的讨论
入门
要使用此模板,有一些选择:
- 使用
dotnet new(推荐)安装 - 下载此存储库(并根据需要修改)
使用dotnet CLI模板
首先,从Nuget(https://www.***nuget.org/packages/ardalis.cleanarchitecture.template/)安装模板:
dotnet new install Ardalis. CleanArchitecture .Template
您可以通过与-?选项:
dotnet new clean - arch - ? ASP.NET Clean Architecture Solution (C # ) Author: Steve Smith @ardalis , Erik Dahl Usage: dotnet new clean - arch [ options ] [ template options ] Options: - n , -- name < name > The name for the output being created. If no name is specified , the name of the output directory is used. - o , -- output < output > Location to place the generated output. -- dry - run Displays a summary of what would happen if the given command line were run if it would result in a template creation. -- force Forces content to be generated even if it would change existing files. -- no - update-check Disables checking for the template package updates when instantiating a template. -- project < project > The project that should be used for context evaluation. - lang , -- language < C # > Specifies the template language to instantiate. -- type < project > Specifies the template type to instantiate. Template options: -as , -- aspire Include .NET Aspire. Type: bool Default : false
在成功安装之后,您应该在dotnet new list中的模板列表中看到模板。查找带有“ Clean-Arch”简称的“ ASP.NET干净体系结构解决方案”。
导航到您希望创建解决方案文件夹的父目录。
运行此命令以在子文件夹名称中创建解决方案结构Your.ProjectName :
dotnet new clean-arch -o Your.ProjectName
将创建Your.ProjectName目录和解决方案文件,其中将是您所有的新解决方案内容,适当地命名为空间,并准备运行/测试!
例子:
感谢@dahlsailrunner的帮助!
已知问题:
- 不要在名称中包含连字符。参见#201。
- 不要将“ ardalis”用作您的命名空间(与依赖关系发生冲突)。
控制器和剃须刀页面呢?
截至版本9,此解决方案模板仅包括使用buddendpoints库对API端点的支持。如果您想使用我的Apiendpoints库,剃刀页和/或控制器,则可以使用其中的最后一个模板,版本7.1。或者,安装后它们很容易添加到此模板中。
添加ardalis.apiendpoints
要使用ardalis.apiendpoint代替(或除了)buddendpoints,只需添加参考并使用文档中的基类。
dotnet add package Ardalis.ApiEndpoints
添加控制器
您需要将对控制器的支持添加到program.cs文件中。您需要:
builder . Services . AddControllers ( ) ; // ControllersWithView if you need Views // and app . MapControllers ( ) ;
一旦到位,您就应该能够创建一个控制器文件夹,并((可选))一个视图文件夹,并且一切都应按预期工作。就我个人而言,我发现Razor页面比控制器和视图要好得多,因此,如果您还没有完全研究剃须刀页面,则在选择视图之前,您可能想现在就这样做。
添加剃刀页
您需要在program.cs文件中添加对Razor页面的支持。您需要:
builder . Services . AddRazorPages ( ) ; // and app . MapRazorPages ( ) ;
然后,您只需在项目的根部添加一个页面夹即可从那里添加。
使用GitHub存储库
要根据此存储库开始,您需要在本地获得副本。您有三个选择:叉子,克隆或下载。大多数情况下,您可能只想下载。
您应该下载存储库,取消封锁zip文件,然后将其提取到新文件夹中,如果您只想使用该项目,或者希望将其用作应用程序的起点。
只有在您打算提交拉动请求时,才应该分配此存储库。或者,如果您想将存储库快照的副本保留在您自己的GitHub帐户中。
如果您是贡献者之一,并且可以访问它,则应克隆此存储库。否则,您可能想要其他选项之一。
运行迁移
您不需要这样做才能使用此模板,但是如果您希望在基础架构项目中正确设置迁移,则在运行迁移命令时需要指定该项目名称。
在Visual Studio中,打开软件包管理器控制台,然后运行Add-Migration InitialMigrationName -StartupProject Your.ProjectName.Web -Context AppDbContext -Project Your.ProjectName.Infrastructure 。
在带有CLI的终端中,命令相似。从Web项目目录中运行此内容:
dotnet ef migrations add MIGRATIONNAME - c AppDbContext - p .. / Your.ProjectName.Infrastructure / Your.ProjectName.Infrastructure.csproj - s Your.ProjectName.Web.csproj - o Data / Migrations
要使用sqlserver,请更改options.UseSqlite(connectionString)); to options.UseSqlServer(connectionString));在Your.ProjectName.Infrastructure.StartupSetup文件中。还要记住将SqliteConnection替换为Your.ProjectName.Web.Program文件中的DefaultConnection ,该文件指向您的数据库服务器。
要更新数据库,请使用Web Project文件夹中使用此命令(用项目的名称替换Clean.Architecture ):
dotnet ef database update - c AppDbContext - p .. / Clean .Architecture.Infrastructure / Clean .Architecture.Infrastructure.csproj - s Clean .Architecture.Web.csproj
目标
该存储库的目的是提供一个基本的解决方案结构,该结构可用于构建域驱动设计(DDD)基于.NET Core的基于域驱动的设计(DDD)。在此处了解有关这些主题的更多信息:
- C#开发人员的坚实原则
- 域驱动的设计基础
- 重构为固体C#代码
如果您习惯于单个项目或遵循传统UI->业务层 – >数据访问层“ n -Tier”体系结构的一组项目构建应用程序,我建议您查看这两个课程(理想情况下是在DDD基础之前):
- 在C#,第1部分中创建n层应用程序
- 在C#,第2部分中创建n层应用程序
史蒂夫·史密斯(Steve Smith)还维护了Microsoft的参考应用程序Eshoponweb及其相关的免费电子书。在这里查看它们:
- github上的Eshoponweb(现在由NimblePros支持)
- 使用ASP.NET Core和Microsoft Azure(电子书)架构现代Web应用程序
请注意,该项目和存储库的目标不是提供示例或参考应用程序。它只是成为一个模板,但是有足够的零件向您展示您在设置实际解决方案时所属的位置。而不是无用的“ class1.cs”,有一些真实的类。一旦您了解它们为什么在那里,以及您应该将它们放置在哪里,请删除它们。如果您要寻找的话, /sample文件夹中有一个示例应用程序。
历史记录和无耻的插头部分
我已经使用此启动器套件来使用域驱动的设计概念和模式来教授ASP.NET核心的基础知识(从ASP.NET Core仍在预发行中时开始)。通常,在Devintersection之类的活动(或私人现场讲习班)之前,我为希望通过最新的开发技术和技术加快其团队的公司来教一个或两天的动手研讨会。如果您需要有关即将举行的研讨会的信息,请随时与我联系。
设计决策和依赖项
该解决方案模板的目的是为新项目提供相当简单的入门套件。它不包括特定企业应用程序可能受益的所有可能的框架,工具或功能。它对数据访问等技术选择的选择植根于使用Microsoft技术堆栈的大多数商业软件开发人员最常见的技术。它(当前)不包括对记录,监视或分析等诸如诸如的大量支持,尽管这些都可以轻松添加。以下是它包含的技术依赖性以及为什么选择它们的列表。其中大多数可以轻松地换成您选择的技术,因为该体系结构的性质是支持模块化和封装。
在哪里验证
用户输入的验证是所有软件应用程序的要求。问题是,以简洁而优雅的方式实施它有意义?该解决方案模板包括4个单独的项目,每个项目都可能负责执行验证以及执行业务不变性(给定验证已经发生的验证,通常是为例外)。
- 何时验证和何时进行异常
域模型本身通常应依靠面向对象的设计,以确保其始终处于一致的状态。它利用封装并限制了公共状态突变访问来实现这一目标,并假定已通过其传递给它的任何参数已经得到验证,因此在大多数情况下,零值或其他不当值会产生异常,而不是验证结果。
用例 /应用程序项目包括系统支持的所有命令和查询。它经常负责验证自己的命令和查询对象。这是使用MediaTR行为或其他一些管道使用的责任模式链最容易完成的。
Web项目包括所有API端点,其中包括其自己的请求和响应类型,按照reper模式。 Butdendpoints库包括对请求类型的FulentValidation进行验证的内置支持。这也是执行输入验证的自然场所。
在API端点内进行验证,然后在用例级别上再次发生验证可能被认为是冗余的。在两个地方添加基本相同的验证,一个用于API请求,另一个是发送给用例处理程序的消息的权衡。在防御性编码之后,在两个地方添加验证通常是有意义的,因为开销很小,心灵的平静和更大的应用鲁棒性通常值得。
核心项目
核心项目是干净建筑设计的中心,所有其他项目依赖性都应指向它。因此,它的外部依赖性很少。核心项目应包括域模型,包括以下内容:
- 实体
- 聚合
- 值对象
- 域事件
- 域活动处理程序
- 域服务
- 规格
- 接口
- DTO(有时)
您可以了解有关这些模式以及如何在此处应用它们的更多信息:
- DDD基本面
- DDD概念
用例项目
一个可选的项目,我将其包括在内,因为许多人都要求它,并且删除比以后更容易删除。这通常也称为应用程序或应用程序服务层。使用CQRS遵循命令和查询(我考虑使用Commands和Queries文件夹,但觉得它添加的文件夹很少 – 每个实际命令或查询的文件夹就足够了,而没有额外的嵌套就足够了)。命令突变域模型,因此应始终将存储库抽象用于其数据访问(存储库是一个获取和持续域模型类型的方式)。查询是阅读的,因此不需要使用存储库模式,而是可以使用最方便的任何查询服务或方法。
由于用例设置为依赖核心,并且不依赖基础架构,因此仍然需要为其数据访问定义抽象。它可以使用规格之类的东西,有时可以帮助封装查询逻辑以及结果类型映射。但是它不必使用存储库/规范 – 如果这是获取数据的最有效方法,它只能发出SQL查询或调用存储过程。
Although this is an optional project to include (without it, your API endpoints would just work directly with the domain model or query services), it does provide a nice UI-ignorant place to add automated tests, and lends itself toward applying policies for cross-cutting concerns using a Chain of Responsibility pattern around the message handlers (for things like validation, caching, auth, logging, timing, etc.).该模板包含一个用于记录的示例,该示例位于共享Kernel Nuget软件包中。
基础设施项目
您应用程序对外部资源的大多数依赖性应在基础架构项目中定义的类中实现。这些类应实现核心定义的接口。如果您有一个非常大的项目具有许多依赖关系,那么拥有多个基础架构项目(例如Infrastructure.data)可能是有意义的,但是对于大多数项目,一个带有文件夹的基础架构项目都可以正常工作。该模板包含数据访问和域事件实现,但是您还将在此项目中添加电子邮件提供商,文件访问,Web API客户端等诸如诸如电子邮件提供商,文件访问,Web API客户端等,因此他们不会将耦合添加到您的核心或UI项目中。
网络项目
应用程序的输入点是ASP.NET Core Web项目(或Aspirehost项目,该项目又加载了Web项目)。这实际上是一个控制台应用程序,在Program.cs中具有public static void Main方法。它利用butdendpoint和reper模式组织其API端点。
SharedKernel软件包
共享内核用于共享有限上下文之间的共同元素。这是一个DDD术语,但是许多组织利用“常见”项目或软件包用于在几个应用程序之间共享的事物。
如果您需要在多个有限上下文之间共享代码(请参阅DDD基本原理),我建议您创建一个单独的共享kernel项目和解决方案。我进一步建议将其作为Nuget软件包(最有可能在您的组织中私下)发布,并由需要它的项目称为Nuget依赖。
以前,该项目包括一个共享业务的项目。但是,由于上述原因,我将其制作了一个单独的软件包Ardalis.sharedkernel,当您使用此模板时,您应该用自己的替换。
如果您想查看共享kernel软件包的另一个示例,那么我在更新的Pluralsight DDD课程中使用的一个示例在Nuget上。
测试项目
可以根据测试(单位,功能,集成,性能等)的类型组织测试项目,也可以通过他们正在测试的项目(核心,基础架构,Web)或两者进行组织。对于这个简单的入门套件,测试项目是根据测试的类型组织的,该测试具有单位,功能和集成测试项目。功能测试是一种特殊的集成测试,可以对Web项目的API进行皮下测试,而无需实际托管真实的网站或越过网络。我创建了一堆测试助手,以使这类测试更短,更易于维护。
使用的模式
该解决方案模板内置了代码,以支持一些常见模式,尤其是域驱动的设计模式。这是其中一些工作方式的简要概述。
域事件
域事件是将操作与实施的触发触发的绝佳模式。这是从域内实体中特别有用的,因为事件的处理程序可以具有依赖关系,而实体本身通常不具有依赖关系。在示例中,您可以使用ToDoItem.MarkComplete()方法看到此操作。以下序列图说明了通过Web API端点标记项目完成时如何使用事件及其处理程序。
相关项目
- Apiendpoints
- 守护体
- httpclienttestextensions
- 结果
- ShareSkernel
- SmartEnum
- 规格
- butdendpoints
关于干净建筑的演示和视频
- 干净体系结构模板中的新功能9.1
- 复制模式和干净的体系结构
- 使用ASP.NET Core 8的清洁体系结构8
- 开始使用干净的体系结构和.NET 8(网络研讨会)
