Skip to content

Commit cb9b845

Browse files
authored
Update README.md (#876)
1 parent a5d4295 commit cb9b845

File tree

1 file changed

+46
-19
lines changed

1 file changed

+46
-19
lines changed

README.md

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,14 @@ By default the site uses HTTPS and expects you to have a self-signed developer c
5555
- [Related Projects](#related-projects)
5656

5757
## Give a Star! :star:
58+
5859
If you like or are using this project to learn or start your solution, please give it a star. Thanks!
5960

6061
Or if you're feeling really generous, we now support GitHub sponsorships - see the button above.
6162

6263
## Versions
6364

64-
The main branch is now using .NET 8. If you need a previous version use one of these tagged commits:
65-
66-
- [7.0](https://github.com/ardalis/CleanArchitecture/releases/tag/v8)
67-
- [6.0](https://github.com/ardalis/CleanArchitecture/releases/tag/dotnet-6)
68-
- [5.0](https://github.com/ardalis/CleanArchitecture/releases/tag/dotnet-core-5)
69-
- [3.1](https://github.com/ardalis/CleanArchitecture/tree/dotnet-core-3.1)
70-
- [2.2](https://github.com/ardalis/CleanArchitecture/tree/dotnet-core-2.2)
71-
- [2.0](https://github.com/ardalis/CleanArchitecture/tree/dotnet-core-2.0)
65+
The main branch is now using **.NET 9**. This corresponds with NuGet package version 10.x. Previous versions are available - see our [Releases](https://github.com/ardalis/CleanArchitecture/releases).
7266

7367
## Learn More
7468

@@ -91,6 +85,34 @@ First, install the template from [NuGet (https://www.nuget.org/packages/Ardalis.
9185
dotnet new install Ardalis.CleanArchitecture.Template
9286
```
9387

88+
You can see available options by running the command with the `-?` option:
89+
90+
```powershell
91+
dotnet new clean-arch -?
92+
ASP.NET Clean Architecture Solution (C#)
93+
Author: Steve Smith @ardalis, Erik Dahl
94+
95+
Usage:
96+
dotnet new clean-arch [options] [template options]
97+
98+
Options:
99+
-n, --name <name> The name for the output being created. If no name is specified, the name of the output
100+
directory is used.
101+
-o, --output <output> Location to place the generated output.
102+
--dry-run Displays a summary of what would happen if the given command line were run if it would result
103+
in a template creation.
104+
--force Forces content to be generated even if it would change existing files.
105+
--no-update-check Disables checking for the template package updates when instantiating a template.
106+
--project <project> The project that should be used for context evaluation.
107+
-lang, --language <C#> Specifies the template language to instantiate.
108+
--type <project> Specifies the template type to instantiate.
109+
110+
Template options:
111+
-as, --aspire Include .NET Aspire.
112+
Type: bool
113+
Default: false
114+
```
115+
94116
You should see the template in the list of templates from `dotnet new list` after this installs successfully. Look for "ASP.NET Clean Architecture Solution" with Short Name of "clean-arch".
95117

96118
Navigate to the parent directory in which you'd like the solution's folder to be created.
@@ -198,30 +220,32 @@ If you're used to building applications as single-project or as a set of project
198220

199221
Steve Smith also maintains Microsoft's reference application, eShopOnWeb, and its associated free eBook. Check them out here:
200222

201-
- [eShopOnWeb on GitHub](https://github.com/dotnet-architecture/eShopOnWeb)
223+
- [eShopOnWeb on GitHub](https://github.com/nimblepros/eShopOnWeb) (now supported by [NimblePros](https://nimblepros.com)
202224
- [Architecting Modern Web Applications with ASP.NET Core and Microsoft Azure](https://aka.ms/webappebook) (eBook)
203225

204-
Note that the goal of this project and repository is **not** to provide a sample or reference application. It's meant to just be a template, but with enough pieces in place to show you where things belong as you set up your actual solution. Instead of useless "Class1.cs" there are a few real classes in place. Delete them as soon as you understand why they're there and where you should put your own, similar files.
226+
Note that the goal of this project and repository is **not** to provide a sample or reference application. It's meant to just be a template, but with enough pieces in place to show you where things belong as you set up your actual solution. Instead of useless "Class1.cs" there are a few real classes in place. Delete them as soon as you understand why they're there and where you should put your own, similar files. There *is* a sample application in the `/sample` folder, if you're looking for that.
205227

206228
## History and Shameless Plug Section
207229

208-
I've used this starter kit to teach the basics of ASP.NET Core using Domain-Driven Design concepts and patterns for some time now (starting when ASP.NET Core was still in pre-release). Typically I teach a one- or two-day hands-on workshop ahead of events like DevIntersection, or private on-site workshops for companies looking to bring their teams up to speed with the latest development technologies and techniques. Feel free to [contact me](https://ardalis.com/contact-us) if you'd like information about upcoming workshops.
230+
I've used this starter kit to teach the basics of ASP.NET Core using Domain-Driven Design concepts and patterns for some time now (starting when ASP.NET Core was still in pre-release). Typically I teach a one- or two-day hands-on workshop ahead of events like DevIntersection, or private on-site workshops for companies looking to bring their teams up to speed with the latest development technologies and techniques. Feel free to [contact me](https://nimblepros.com/) if you'd like information about upcoming workshops.
209231

210232
# Design Decisions and Dependencies
211233

212-
The goal of this sample is to provide a fairly bare-bones starter kit for new projects. It does not include every possible framework, tool, or feature that a particular enterprise application might benefit from. Its choices of technology for things like data access are rooted in what is the most common, accessible technology for most business software developers using Microsoft's technology stack. It doesn't (currently) include extensive support for things like logging, monitoring, or analytics, though these can all be added easily. Below is a list of the technology dependencies it includes, and why they were chosen. Most of these can easily be swapped out for your technology of choice, since the nature of this architecture is to support modularity and encapsulation.
234+
The goal of this solution template is to provide a fairly bare-bones starter kit for new projects. It does not include every possible framework, tool, or feature that a particular enterprise application might benefit from. Its choices of technology for things like data access are rooted in what is the most common, accessible technology for most business software developers using Microsoft's technology stack. It doesn't (currently) include extensive support for things like logging, monitoring, or analytics, though these can all be added easily. Below is a list of the technology dependencies it includes, and why they were chosen. Most of these can easily be swapped out for your technology of choice, since the nature of this architecture is to support modularity and encapsulation.
213235

214236
## Where To Validate
215237

216238
Validation of user input is a requirement of all software applications. The question is, where does it make sense to implement it in a concise and elegant manner? This solution template includes 4 separate projects, each of which might be responsible for performing validation as well as enforcing business invariants (which, given validation should already have occurred, are usually modeled as exceptions).
217239

240+
- [When to Validate and When to Throw Exceptions](https://www.youtube.com/watch?v=dpPcnAT7n7M)
241+
218242
The domain model itself should generally rely on object-oriented design to ensure it is always in a consistent state. It leverages encapsulation and limits public state mutation access to achieve this, and it assumes that any arguments passed to it have already been validated, so null or other improper values yield exceptions, not validation results, in most cases.
219243

220-
The use cases / application project includes the set of all commands and queries the system supports. It's frequently responsible for validating its own command and query objects.
244+
The use cases / application project includes the set of all commands and queries the system supports. It's frequently responsible for validating its own command and query objects. This is most easily done using a [chain of responsibility pattern](https://deviq.com/design-patterns/chain-of-responsibility-pattern) via MediatR behaviors or some other pipeline.
221245

222246
The Web project includes all API endpoints, which include their own request and response types, following the [REPR pattern](https://deviq.com/design-patterns/repr-design-pattern). The FastEndpoints library includes built-in support for validation using FluentValidation on the request types. This is a natural place to perform input validation as well.
223247

224-
Having validation occur both within the API endpoints and then again at the use case level is redundant, so in this template the choice has been made to validate at the edge of the application, in the API endpoints. This means some future consumer of the Use Cases project will also need to be responsible for its own validation as well, but in the vast majority of cases there won't be any other consumers of the use cases outside of the API endpoints.
248+
Having validation occur both within the API endpoints and then again at the use case level may be considered redundant. There are tradeoffs to adding essentially the same validation in two places, one for API requests and another for messages sent to Use Case handlers. Following defensive coding, it often makes sense to add validation in both places, as the overhead is minimal and the peace of mind of mind and greater application robustness is often worth it.
225249

226250
## The Core Project
227251

@@ -237,21 +261,24 @@ The Core project is the center of the Clean Architecture design, and all other p
237261
- Interfaces
238262
- DTOs (sometimes)
239263

264+
You can learn more about these patterns and how to apply them here:
265+
266+
- [DDD Fundamentals](https://www.pluralsight.com/courses/fundamentals-domain-driven-design)
267+
- [DDD Concepts](https://deviq.com/domain-driven-design/ddd-overview)
268+
240269
## The Use Cases Project
241270

242271
An optional project, I've included it because many folks were demanding it and it's easier to remove than to add later. This is also often referred to as the *Application* or *Application Services* layer. The Use Cases project is organized following CQRS into Commands and Queries. Commands mutate the domain model and thus should always use Repository abstractions for their data access. Queries are readonly, and thus do not need to use the repository pattern, but instead can use whatever query service or approach is most convenient. However, since the Use Cases project is set up to depend on Core and not directly on Infrastructure, there will still need to be abstractions defined for its data access. And it *can* use things like specifications, which can sometimes help encapsulate query logic as well as result type mapping. But it doesn't *have* to use repository/specification - it can just issue a SQL query or call a stored procedure if that's the most efficient way to get the data.
243272

244-
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.
273+
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.).
245274

246275
## The Infrastructure Project
247276

248-
Most of your application's dependencies on external resources should be implemented in classes defined in the Infrastructure project. These classes should implement interfaces defined in Core. If you have a very large project with many dependencies, it may make sense to have multiple Infrastructure projects (e.g. Infrastructure.Data), but for most projects one Infrastructure project with folders works fine. The sample includes data access and domain event implementations, but you would also add things like email providers, file access, web api clients, etc. to this project so they're not adding coupling to your Core or UI projects.
249-
250-
The Infrastructure project depends on `Microsoft.EntityFrameworkCore.SqlServer` and `Autofac`. The former is used because it's built into the default ASP.NET Core templates and is the least common denominator of data access. If desired, it can easily be replaced with a lighter-weight ORM like Dapper. Autofac (formerly StructureMap) is used to allow wireup of dependencies to take place closest to where the implementations reside. In this case, an InfrastructureRegistry class can be used in the Infrastructure class to allow wireup of dependencies there, without the entry point of the application even having to have a reference to the project or its types. [Learn more about this technique](https://ardalis.com/avoid-referencing-infrastructure-in-visual-studio-solutions). The current implementation doesn't include this behavior - it's something I typically cover and have students add themselves in my workshops.
277+
Most of your application's dependencies on external resources should be implemented in classes defined in the Infrastructure project. These classes should implement interfaces defined in Core. If you have a very large project with many dependencies, it may make sense to have multiple Infrastructure projects (e.g. Infrastructure.Data), but for most projects one Infrastructure project with folders works fine. The template includes data access and domain event implementations, but you would also add things like email providers, file access, web api clients, etc. to this project so they're not adding coupling to your Core or UI projects.
251278

252279
## The Web Project
253280

254-
The entry point of the application is the ASP.NET Core web project. This is actually a console application, with a `public static void Main` method in `Program.cs`. It currently uses the default MVC organization (Controllers and Views folders) as well as most of the default ASP.NET Core project template code. This includes its configuration system, which uses the default `appsettings.json` file plus environment variables, and is configured in `Startup.cs`. The project delegates to the `Infrastructure` project to wire up its services using Autofac.
281+
The entry point of the application is the ASP.NET Core web project (or possibly the AspireHost project, which in turn loads the Web project). This is actually a console application, with a `public static void Main` method in `Program.cs`. It leverages FastEndpoints and the REPR pattern to organize its API endpoints.
255282

256283
## The SharedKernel Project
257284

0 commit comments

Comments
 (0)