β What's the point of MediatR?
I haven't done a lot of web/API dev, so this might just be because I've never been in a situation where I've actually needed it, but what is the point of MediatR? I don't really understand it too well, so if someone could give me a rundown, that would be incredible.
81 Replies
Clarification: Do you truly mean the mediator pattern, or do you mean libraries like
MediatR
etc?Isn't MediatR an implementation or the mediator pattern?
See, that would make sense! But no, its not π
Despite the name, MediatR does not implement the Mediator Pattern at all: itβs a Command Dispatcher.
ah
yeah okay I had it backwards then, my actual question would be why do people use MediatR?
Well, there are a few benefits and downsides
First, having a single handler for a single command hierarchy makes it more focused than an entire service class, while still letting it be mocked out for tests
Easy to find what you are looking for and it's not going to be a thousand line service class, so that's good. Also resolves it's own dependencies, so you don't need to do that in the endpoint or whatever caller you are using
Third, not common in asp but sometimes you might have a command type hierarchy and not know the concrete implementation. An example is a paser for a command line app, where you just parse and fire away
Downsides? Well it's just a glorified method invocation
It does add complexity where it might not be needed
Oh and most dispatchers use a pipeline, so you can register middleware
This lets you handle transactions
Another point, a lot of people use MediatR to implement CQRS and not necessarily the Mediator pattern in itself
sorry, what's a "command hierarchy"?
Commands related to eachother, either by nature of what they do (two ways to add something) or by actual inheritance (all commands are ICommands)
Why is that a benefit of MediatR?
Not reinventing the wheel
... what?
And a command is just some kind of "action"?
Like... send an email or update a db or whatever
So because it can be used to implement CQRS, that counts as a plus ? Wtf
Yep
It's a glorified method invocation:)
right
It does allow your method calls to be serialized thou. Useful for things like undo
I meant that you will see the MediatR library in the wild a lot of times because people wanted to implement CQRS (which benefits from using the mediator pattern) and the internet is filled with "implementing CQRS with MediatR" tutorials
I agree with that
But how is that "the point" of MediatR?
Also, MediatR is not an implementation of the mediator pattern
This is important
why is it even named that if it doesn't implement the mediator pattern?
No clue
But it doesn't. It was just a command dispatcher and then they added a message Hub to it
It isn't, it was more of a heads up that the library does much more than simply helping implementing CQRS. I had the same question once and my doubt arose from looking at open source projects that used it for CQRS
I really like that in their GitHub page it says "Simple mediator implementation in .NET"
I'm traveling right now, but I'll try to find an excellent article that shows the difference
But yeah, CQRS is a big factor of why it's popular for sure.
There is a Greg Young talk about CQRS and simplicity that is very good
What MediatR does, is replace classes that end in
...Service
or ...Manager
with a class that has only one method.
whether it's
or whether it's
The result is that you're thinking in small functionalities that handle a command or request, instead of making large classes that do a bunch of inbetween things
I want to put this way of thinking into my codebases, without using mediator. I want to see more very very small interfaces
and
and
Are roughly similarBut you still need these small
Command
classes and Handler
classesluckily we don't need to watch how many kilobytes of code we write. You usally have a few GBs free on your disk :)
whether it's an interface + implementation, or a command + handler, you'll write nearly just as much
Ah that's what this meant, instead of calling a method on a service, you use
Send<T>(new T(...));
it feels like the service locator antipattern, which makes spaghetti code, but it isn't really
you're not specifying a dependency, you just say "I want this command done. I don't care who does it, but I want this result from this input"
yes!
Also, I found the article: https://arialdomartini.github.io/mediatr
You probably don't need MediatR
Personal resume
"The Mediator Pattern" is the section that breaks down how this isn't a mediator
Oh, and the primary drawback (at least if you ask me) is that intellisense can't tell you that you have references to the handler
damn that is a very good article
ie, if you want to jump to the
AddCommandHandler.Handle
method, you need to know that its called suchit reflects the thoughts that I didn't know how to word
Mhm, I felt the same way.
usually you put the command and the handler in the same file
Yeah I know.. unfortunately at work we have stylecop that enforces no more than one class per file
and I hate it
π
that's... unproductive
Also if I wanted to write a MediatR handler for like creating a user or whatever, would I inject the EF db context and other related things directly in the handler?
we use a home-rolled command dispatcher thou, not mediatr. but its similar enough
yep
the idea is that the command would contain all the data needed, and the handler all the code needed.
ah, so it's like minimal APIs vs. controllers, where minimal APIs can request the minimum amount of things they actually need
having tiny handlers, all separated from other handlers would also allow you to make refactoring easier. If you switch to a different DB, you don't have to switch out one big layer to another, but you can approach it per handler
you can also make controllers with just one endpoint :)
@rodrigovaz https://discord.com/channels/143867839282020352/1155864560859873411/1155883188032380978
thats the article I mentioned
So Thinker, do you feel the question has been answered? π
Probably, at least I think I got a better understanding of what the point is, to the point I could see why I would use it myself.
Actually nevermind, I have another question, why split a request handler and endpoint in the first place? Like if I have an endpoint which one job is to create something, why should I separate that into a request handler which creates the thing and an endpoint which literally just calls the handler with the request object?
you don't want to be tightly coupled to ASP.net
what if you decide to be event bus-based, then you want your business logic to be accessible through a message consumer instead of that consumer needing ASP.net dependencies
but, you could always refactor that later imo
unless you start returning action results in your code
imo a business logic csproj should never know it's being called by ASP.net
Well, I made this just to test it, but it feels dumb because like these could just be one method
Agree with all the above points.
What if you later must add items not via an endpoint, but via a message queue? or via a CLI app? or a desktop app?
if its all in the endpoint, you can't easily.
I have switched a bunch of endpoints to azure service bus consumers lately
and some of them were a pain
let the controller/endpoint handle the HTTP specifics and nothing else (except calling the correct command)
Yeah, I've had to implement CLI tools that do a lot of business logic from our big ASP application recently
So I should have a separate project which contains all the request handlers?
it was trivial, since we use a dispatcher
we have
MyApplication.API
, MyApplication.Business
, MyApplication.Data
imho, yes. that would be your
business logic
projectetc etc
same here
Data.Database
though, cause external dependencies get an e.g. MyApplication.Data.Discord
etcI have an API, EF/data, and "common" project (mainly containing models), it already feels somewhat like I'm splitting these up for no reason other than out of principle
be careful with "common" projects D:
my codebase has waaay too many
and models/DTOs end up not being common
but they are used across projects
Yeah I just have no idea where else I would put the models which aren't EF entities
some like
MyApplication.Domain
for their domain modelsCommon would be stuff like a Result type, or other similar things
love those
we have Domain for domain models, and
.Contracts
for our public facing DTOsI like that
that could easily be inside API as well, if you know you dont need it (for a client for example)
I'm drafting an API layout so that we improve on these things (e.g. internal models are given to the outside, and shared through csprojs with microservices) and I want to cut that all out
So like
- API
- Requests/request handlers
- Models/domain/whatever
- EF/data
you could put requests in your domain too
I guess
yup, seems like a good start to me
Thinker have you seen Accord's code?
@Accord?
GitHub
GitHub - patrickklaeren/Accord: A C# Discord bot with moderation, X...
A C# Discord bot with moderation, XP/guild participation and utilities - GitHub - patrickklaeren/Accord: A C# Discord bot with moderation, XP/guild participation and utilities
you'll like this
this is primarily for larger or more serious codebases btw. its not worth for a small app or a POC
4 projects???
only 4???
π
man MODiX looks like a beast in comparison
at work I have 113 csprojs lol
worst thing is, this is ~15 ""microservice"" APIs and they share so many csprojs
what's a microservice again
its like a unicorn
rare
a magical thing that doesnt exist π