Making DDD and CQRS Microservices easy with dotnet templates
If you are working with Microservices, you might have noticed that you are repeating over and over the scaffolding for your new microservices. In order to make easier the creation of new microservices, you can build your own custom dotnet core template.
Apart from saving time, building a custom template will help to promote good practices, a proper architecture, right dependencies, etc. With this purpose, I have built my custom template, so it can help us to create easily new microservices based on CQRS and DDD, without having to build the same scaffolding each time we have to create a new service.
Microservice architecture
In microservices architecture, each service can be different, according to the problem it has to solve. However, it is likely that you have a reference architecture that will provide some consistency and it will promote good practices.
In our case, the main patterns that drive our microservice architecture are Domain Driven Design (DDD) and Command and Query Responsibility Segregation (CQRS). If you don't know these concepts, Martin Fowler has two good articles for DDD and CQRS.
In next diagram, we can see a summary of one our more standard microservices, where we deploy Command and Query as independent AWS lambda functions. On the one hand, Command API will publish events to EventStore. On the other hand, Query API will read from DynamoDB database. This pattern decouples reading and writing operations, offering high scalability and performance for reading operations, which are the most frequent.
Finally, we have a worker service subscribed to EventStore, so each time it receives a new event, it projects that event into DynamoDB. This service is running as docker container and it is orchestrated by AWS ECS.
If we have a look at the architecture decomposing it by layers, we can observe that it is using DDD as reference. So basically, the domain layer will be the core of the application, containing business logic and domain events. In addition, we have a data layer to convert these domain models to data models. And there is also an application layer to handle application logic and using data layer with Dependency Injection (DI). On the top, we have distributed services layer, where we have Web APIs or Service Workers. Finally, we have a platform layer to share cross cutting code with our microservices.
Building a custom dotnet core template
If we translate the architecture patterns we explained in previous section into a dotnet core solution. We will have multiple projects to separate concerns between different layers. In addition, we will have different projects for different applications and also for tests.
In order to build our reusable template, the first step is building a generic solution that we can use as reference to build new microservices. In particular, I've created this solution named MicroserviceTemplate, that contains all the needed scaffolding to implement patterns like DDD and CQRS out-of-the-box. As you can see, there are different folders in the first level to organize the code by DDD layers. So we have distributed services, application, domain and data. Furthermore, these folders have been numbered to organize them in the proper order if we use DDD architecture diagram as reference.
In addition, we have different folders to separate Command Web API, Query Web API and Projector worker service. Finally, application layer has also been divided into three projects that belong to command, query and projector respectively.
Test projects follow similar structure, but they have been hidden to simplify. However, you can find the full example on my GitHub repository: https://github.com/albertocorrales/dotnet-template-ddd-cqrs.
In this template, it is important to use the same namespace for all projects, since we will be able to replace it later when we use it as template. In my example, I have always used "MicroserviceTemplate" as namespace.
Once you have created your reference solution, you have to configure your template. To do it, you can use Sidewaffle Creator extension, or you can just use the ones I shared on GitHub and modify them. What you need to define your template are these files that you can find in .template.config folder https://github.com/albertocorrales/dotnet-template-ddd-cqrs/tree/master/template/.template.config. This configuration should be in the same folder that you have your solution.
Additionally, you could define multiple templates in one package. For example, Amazon uses this technique to distribute multiple lambda dotnet core templates within the package Amazon.Lambda.Templates.
Publishing and using a custom dotnet core template
Once you have defined your custom dotnet template, you can pack it as NuGet package and use it locally or you can publish it into a NuGet feed.
For both scenarios, the first step is defining your nuspec file, which will be used to generate your NuGet package. In this file, you configure parameters like the package name and version, the files to be added to the package, etc.
Publishing to a local package
In order to create your package locally, open a terminal where you have your nuspec file and execute this command:
This is going to generate a file MicroserviceTemplate.1.0.0.nupkg that contains your template as NuGet package.
In order to install your template use the command:
When this command finishes, you will see a new template in your list of templates named "MicroserviceTemplate".
In order to use this template to create a new microservice, in the folder you can to create your solution use this command:
Now you will see that your new solution has the same architecture you defined in your template, but all the namespaces and projects have been renamed to use "MyCoolMicroservice" as namespace:
Publishing to a private NuGet feed
In order to publish into a private NuGet feed, the best option is using CI/CD. In my case, I'm using Azure DevOps and I have a release defined as:
Since the package is in a private feed you need to authenticate. However, --interactive options is not supported yet by dotnet new --install command, so you will need to add your private NuGet feed. More info about this in this issue: https://github.com/dotnet/templating/issues/1747.
In order to access to your feed, you need to generate a Personal Access Token (PAT). Here there is more info about how to generate a new PAT.
Once you have your PAT, execute the following command:
nuget source Add -Name "<name>" -Source "<your nuget source>" -UserName <your username> -Password <your PAT>Now, to install your template from your private NuGet feed, use this command:
dotnet new --install MicroserviceTemplate::1.0.0 --nuget-source "<your nuget source>"
Once you have installed your template, you can use it with dotnet new command to create new solutions based on your template.
Conclusions
In this article, we have seen how custom dotnet core templates can help you to save time and promote good architectural practices when you have to create new microservices. We have used as example a microservice based on architectural patterns DDD and CQRS to define our template.
Finally, we have explained how we can use this template to generate a NuGet package to share the template and use it with dotnet new commands.
Remember that this is just one example to illustrate the concept, but you could add more useful stuff in your template, like build definitions, IaC code, etc. In addition, you could define multiple templates in one package to cover the most used patterns that you might need for your microservices.
You can find the source code related to this post on my GitHub repository: https://github.com/albertocorrales/dotnet-template-ddd-cqrs
Very Nice Article !!
ReplyDelete