DEV Community

Cover image for Mediator and CQRS with MediatR
Nils Diekmann
Nils Diekmann

Posted on • Originally published at Medium

Mediator and CQRS with MediatR

ultimate beautiful code

Solution to save money — Generated by Image3


Challenge

Today I am talking about a coding dojo that my younger and older self are carrying out against each other. A developer is active in the coding dojo all the time. The active developer is free to decide what to develop. But he must explain his thoughts to the other developer.

The company they work for has developed a donation system. People can donate some money and see the total amount of all donations. The challenge for the Coding Dojo is now to develop this system further. The sample application is available on GitHub.

GitHub logo KinNeko-De / sample-codingdojo-donation

Read my articles to find out how my [younger](https://medium.com/@kinneko-de/344fe6e8e4f6) and [older](https://medium.com/@kinneko-de/0de8a4351da2) selves solved this coding dojo.

Donation app

Motivation

This is a sample exercise for a coding dojo in C#.

The application consists of a user interface part and a server part with a database. Everything is in one application to avoid unnecessary complexity. API calls are reduced to method calls.

Read my articles to find out how my younger and older selves solved this coding dojo.

Challenge

Develop the application further. You are completely free in your decisions

Architecture in a real world example

In a real world the UI would run on the client. The UI would access the server over an API.

C4 mode

Sources

The headliner image was generated using Gemini's image generation capabilities.

Gemini is a large language model developed by Google AI. It can generate realistic and diverse images based on text prompts. Learn more about Gemini.




My younger self will take on the role of the active developer in this article. Read my other article to find out what my older self would do instead.

Coding Dojo

Younger Self [excited]: Oh my God, today we had a training session with an external consultant. He talked about what we should use in our project. He told us to use patterns to improve the code. There were a lot of patterns, I can’t remember them all, but there was one very special pattern called Mediator.

Older Self [relaxed]: Can you explain me what the mediator pattern does and when to use it?

Youger Self [irritated]: There’s a mediator between different parts of the code that greatly improves readability.

Older Self: If you don’t know what the mediator pattern is, how are you going to implement it?

Younger Self: Of course, I am not going to implement it myself. There's a framework called MediatR. It has almost the same name, so I cannot be wrong if I use it. This framework will do everything for me.

Older Self [sceptical]: Are you absolutely sure?

Younger Self [self-confident]: Yes, of course. There is a comment from a guy who uses it everywhere because he totally likes it and is totally satisfied by the framework. So I am going to use it everywhere now.

Older Self: Okay, so where do we start?

Younger Self: The service adds a number to a value in a database. I have heard that this is a command. Then the service queries the result. If I separate the command from the query, I can also implement CQRS.

Older Self: Sounds ambitious, but let us first introduce the mediator pattern.

Younger Self: I first need to add a nuget package for MediatR and register it in my Program.cs. That is all I have to do to get all my code injected by dependency Injection.

builder.Services.AddMediatR(
  cfg => cfg.RegisterServicesFromAssemblyContaining<Program>());
Enter fullscreen mode Exit fullscreen mode

I create a command that does the update in the database. It needs the same properties as I had before as parameters. I put the command in its own class.

public class AddDonationCommand : IRequest
{
  public required int Donation { get; init; }
}
Enter fullscreen mode Exit fullscreen mode

Then I create a handler for the command. It will get the database injected as the service before. Each handler has a Handle method. There I do my database query.

// ReSharper disable once UnusedMember.Global
// MediatR will automatically find and use this class somehow, do not remove it!
public class AddDonationCommandHandler : IRequestHandler<AddDonationCommand>
{
  private Database Database { get; }

  public AddDonationCommandHandler(Database database)
  {
    Database = database;
  }

  public async Task Handle(AddDonationCommand request, CancellationToken cancellationToken)
  {
    await Database.AddDonation(request.Donation);
  }
}
Enter fullscreen mode Exit fullscreen mode

Then I do the same with the query. In the service, I just call the mediator and send the command and the query to it.

public async Task<int> UpdateDonation(int donation)
{
  var command = new AddDonationCommand() { Donation = donation };
  await Sender.Send(command);

  var query = new GetTotalDonationsQuery();
  return await Sender.Send(query);
}

Enter fullscreen mode Exit fullscreen mode

GitHub logo KinNeko-De / sample-codingdojo-donation-mediatr

Read my articles to find out how my [younger](https://medium.com/@kinneko-de/344fe6e8e4f6) and [older](https://medium.com/@kinneko-de/0de8a4351da2) selves solved this coding dojo.

Donation app

Motivation

This is a sample exercise for a coding dojo in C#. It was copied from the donation template

This is the coding dojo solution of my younger selve.

Read my article to find out how my older selve solved this coding dojo.

Challenge

Develop the application further. You are completely free in your decisions






Older Self: The code now looks much more complex to me.

Younger Self: It’s more simpler because I had don’t have to worry about how the objects are created. The framework does it for me. Now I can just focus on my command and not have to look at the rest.

Older Self: Where do you see CQRS in this specific example?

Younger Self: I separated my query from my command by putting a mediator between them. So its now segregated right?

Older Self: There is an R in CQRS. It stands for responsibility. The responsibility in your code is not segregated. It is still one method, even with all the layers of abstraction in between.

Younger Self [thoughtful]: Hmmmmm [pause] I have the perfect solution for that. We do two teams, one is responsible for the query and one is responsible for the command. Then we do a modular monolith. We can also extract the query to an separate microservice that I call synchronously from the microservice that does the addition.

Older Self [surrenders]: I am at a loss for words. Product owner, we are done.

Product owner: What is the benefit to our company of doing your approach?

Younger Self: Hmm Hmm Hmm

Conclusion

When I was still young, I tried to use as many patterns as possible. Later I realized that I was just adding a lot more complexity to my code. Nowadays, I only use patterns to solve problems that already exist.

I also realized that beautiful code and my personal satisfaction do not pay the bills. So I focus more on business value and the bigger picture than on just code.

If you totally disagree with experience and totally like the approach of my younger self, then stop here. Otherwise, I am happy to share my older self’s aproach with you.

And don’t forget to send me a reaction at this article.

Top comments (0)