CleanMicroserviceTemplate 1.0.0
See the version list below for details.
dotnet new install CleanMicroserviceTemplate::1.0.0
Clean microservice template
This is a project template to create microservices in .NET 6 based on the Clean architecture approach (also known as Onion architecture, or Hexagonal architecture, or Ports and adapters).
The goal is to provide a boilerplate for creating API's that enforces some good practices so it is easy to spin off new microservices but keeping a good level of quality on the solution.
The solution is heavily inspired by the templated created by Jason Taylor.
Features
- ADR
ADR stands for Architectural Decision Records.
Please refer to ADR.md to know more about it.
You can quickly take a look by exploring the index
- DDD
The template is prepared to do Domain Driven Design by providing a 'Domain' layer ready to host you entities, value objects, and so on, in an structured way.
- CQRS
The template is also ready to separate your Queries and Commands in the application layer using MediatR.
Link to the ADR decission
- Mapster
Uses mapster as the default mapper but you can always write your own or use another one.
Link to the ADR decission
- Validation
The domain validation is done using FluentValidation (Link to the ADR decission) and following the Notification pattern (Link to the ADR decission) suggested by Martin Fowler.
- Honeycomb testing
The template comes with unit tests implemented as well as Integration tests using xUnit, moq, Fluent Assertions (Link to the ADR decission), and then everything is checked with mutation tests using Striker.net with the 'MultipleProjectRunner' plugin.
- Observability
We're using Open Telemetry to add metrics and tracing instrumentation from the beginning!
The template is ready to output the tracing information on the console as well as to use a grafana cloud agent as a OTLP collector but you can easily change it to use Jagger or Zipkin adding a new container on the docker compose.
Metrics are exposed on the/metrics
endpoint using the Prometheus exporter and there is a custom metric created to monitor how many products are being added.
- Others
Scope logging, strong typed ID's to avoid primitive obsession, docker compose ready, just go ahead and take a look.
Solution structure
Main folders:
- Domain ⇒ The domain layer contains your plain objects for entities and value objects as well as validators or any other core business logic you might have.
- Application ⇒ The application layer contains all queries and commands so you can see the operations this microservice is doing in a quick sight.
This layer is organized with a first level of folders containing each "entity" and then another level with a folder for the queries, and a folder for the commands, and then the next level is another folder for the specific Query or Command where you can find everything related to this operation.
That's the same convention as in the Jason Clean Architecture template, but in this case I've preferred to keep one file per class approach instead of having the Query and the handler in the same file. - Api ⇒ The API is generated using the new minimal api approach as the microservice shouldn't be that big.
- Infrastructure ⇒ Only the database layer is implemented using an in memory repository.
Test projects
Tests are separeted from the code in a diferent root folder and you can see them on the solution also under the 'tests' solution folder.
We provide the following tests projects:
- Application IntegrationTests
The test project is testing the application layer with its real dependencies. - Application UnitTests
The test project is testing the application layer with mocked dependencies. - Domain UnitTests
The test project is testing the domain layer. - Infrastructure UnitTests
The test project is testing the infrastructure layer.
Runing the project
Build Solution
- Build ⇒ Build Solution
Run Tests
- Test ⇒ Windows ⇒ Test Explorer ⇒ Run All
Run Tests with Command Prompt/Windows PowerShell
- Open Folder in File Explorer
- Open Command Prompt/Windows PowerShell
- Run
dotnet vstest *Tests*.dll
Run Mutation Tests with Stryker.net
- Open terminal and run
dotnet tool restore
to install Stryker.net for the project. - Navigate to root folder and run the powershell
.\RunAllSteps.ps1
Run the solution using docker compose
The solution has a Dockerfile
and it is ready to be used with docker compose.
If you work with only WSL (Windows Subsystem for Linux) version 2 with docker installed.
Then you just need to go to the path of the solution and run the following command:
docker compose up
The API should be available on localhost:8080
If you are using 'Docker Desktop' then you need to enable the build on the docker-compose
project by editing the properties on the solution and going to 'Configuration properties > Configuration' and checking the project.
How to contribute
Everyone should be able to create a 'Pull Request' with a suggested change.
Feel free to reach out if you need to discuss anything beforehand.
😃
Some to-do's we think could be added:
- Add identity handling
Even though it could be unnecessary for some microservices it's a very common problem that is nice to have it solved, and the one who don't need it can easily remove it. (or it could even be parametrizable)
- Ubiquitous language.
Based on this article, they idea could be to have a dictionary of terms and actions defined and then use those keys to check the entities, properties and methods on the domain layer on a unit test so we make sure we have a definition and our code follows what is understandable in the bounded context. Continuing on this idea the terms with descriptions could be also available via endpoint so it can be queried or published or whatever.
- Apply ubiquitous language in domain.
Continuing on the previous point, in the domain, for example, the object
Product
has a generic method update, could be splited in three methods:productUpdateTitleAndDescription
,productUpdateSku
,productUpdatePrice
.
-
net6.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.