Replacing service layer with MediatR - is it worth to do it? - c#

Do you think it might be reasonable to replace my service layer or service classes with MediatR? For example, my service classes look like this:
public interface IEntityService<TEntityDto> where TEntityDto : class, IDto
{
Task<TEntityDto> CreateAsync(TEntityDto entityDto);
Task<bool> DeleteAsync(int id);
Task<IEnumerable<TEntityDto>> GetAllAsync(SieveModel sieveModel);
Task<TEntityDto> GetByIdAsync(int id);
Task<TEntityDto> UpdateAsync(int id, TEntityDto entityDto);
}
I want to achieve some sort of modular design so other dynamically loaded modules
or plugins can write their own notification or command handlers for my main core application.
Currently, my application is not event-driven at all and there's no easy way for my dynamically loaded plugins to communicate.
I can either incorporate MediatR in my controllers removing service layer completely or use it with my service layer just publishing notifications so my plugins can handle them.
Currently, my logic is mostly CRUD but there's a lot of custom logic going on before creating, updating, deleting.
Possible replacement of my service would look like:
public class CommandHandler : IRequestHandler<CreateCommand, Response>, IRequestHandler<UpdateCommand, Response>, IRequestHandler<DeleteCommand, bool>
{
private readonly DbContext _dbContext;
public CommandHandler(DbContext dbContext)
{
_dbContext = dbContext;
}
public Task<Response> Handle(CreateCommand request, CancellationToken cancellationToken)
{
//...
}
public Task<Response> Handle(UpdateCommand request, CancellationToken cancellationToken)
{
//...
}
public Task<bool> Handle(DeleteCommand request, CancellationToken cancellationToken)
{
///...
}
}
Would it be something wrong to do?
Basically, I'm struggling what to choose for my logic flow:
Controller -> Service -> MediatR -> Notification handlers -> Repository
Controller -> MediatR -> Command handlers -> Repository
It seems like with MediatR I can't have a single model for Create, Update and Delete, so one way to re-use it I'd need to derive requests like:
public CreateRequest : MyDto, IRequest<MyDto> {}
public UpdateRequest : MyDto, IRequest<MyDto> {}
or embed it in my command like:
public CreateRequest : IRequest<MyDto>
{
MyDto MyDto { get; set; }
}
One advantage of MediatR is the ability to plug logic in and plug it out easily which seems like a nice fit for modular architecture but still, I'm a bit confused how to shape my architecture with it.

Update: I'm preserving the answer, but my position on this has changed somewhat as indicated in this blog post.
If you have a class, let's say an API controller, and it depends on
IRequestHandler<CreateCommand, Response>
What is the benefit of changing your class so that it depends on IMediator,
and instead of calling
return requestHandler.HandleRequest(request);
it calls
return mediator.Send(request);
The result is that instead of injecting the dependency we need, we inject a service locator which in turn resolves the dependency we need.
Quoting Mark Seeman's article,
In short, the problem with Service Locator is that it hides a class' dependencies, causing run-time errors instead of compile-time errors, as well as making the code more difficult to maintain because it becomes unclear when you would be introducing a breaking change.
It's not exactly the same as
var commandHandler = serviceLocator.Resolve<IRequestHandler<CreateCommand, Response>>();
return commandHandler.Handle(request);
because the mediator is limited to resolving command and query handlers, but it's close. It's still a single interface that provides access to lots of other ones.
It makes code harder to navigate
After we introduce IMediator, our class still indirectly depends on IRequestHandler<CreateCommand, Response>. The difference is that now we can't tell by looking at it. We can't navigate from the interface to its implementations. We might reason that we can still follow the dependencies if we know what to look for - that is, if we know the conventions of command handler interface names. But that's not nearly as helpful as a class actually declaring what it depends on.
Sure, we get the benefit of having interfaces wired up to concrete implementations without writing the code, but the savings are trivial and we'll likely lose whatever time we save because of the added (if minor) difficulty of navigating the code. And there are libraries which will register those dependencies for us anyway while still allowing us to inject abstraction we actually depend on.
It's a weird, skewed way of depending on abstractions
It's been suggested that using a mediator assists with implementing the decorator pattern. But again, we already gain that ability by depending on an abstraction. We can use one implementation of an interface or another that adds a decorator. The point of depending on abstractions is that we can change such implementation details without changing the abstraction.
To elaborate: The point of depending on ISomethingSpecific is that we can change or replace the implementation without modifying the classes that depend on it. But if we say, "I want to change the implementation of ISomethingSpecific (by adding a decorator), so to accomplish that I'm going to change the classes that depend on ISomethingSpecific, which were working just fine, and make them depend on some generic, all-purpose interface", then something has gone wrong. There are numerous other ways to add decorators without modifying parts of our code that don't need to change.
Yes, using IMediator promotes loose coupling. But we already accomplished that by using well-defined abstractions. Adding layer upon layer of indirection doesn't multiply that benefit. If you've got enough abstraction that it's easy to write unit tests, you've got enough.
Vague dependencies make it easier to violate the Single Responsibility Principle
Suppose you have a class for placing orders, and it depends on ICommandHandler<PlaceOrderCommand>. What happens if someone tries to sneak in something that doesn't belong there, like a command to update user data? They'll have to add a new dependency, ICommandHandler<ChangeUserAddressCommand>. What happens if they want to keep piling more stuff into that class, violating the SRP? They'll have to keep adding more dependencies. That doesn't prevent them from doing it, but at least it shines a light on what's happening.
On the other hand, what if you can add all sorts of random stuff into a class without adding more dependencies? The class depends on an abstraction that can do anything. It can place orders, update addresses, request sales history, whatever, and all without adding a single new dependency. That's the same problem you get if you inject an IoC container into a class where it doesn't belong. It's a single class or interface that can be used to request all sorts of dependencies. It's a service locator.
IMediator doesn't cause SRP violations, and its absence won't prevent them. But explicit, specific dependencies guide us away from such violations.
The Mediator Pattern
Curiously, using MediatR doesn't usually have anything to do with the mediator
pattern. The mediator pattern promotes loose coupling by having objects interact with a mediator rather than directly with each other. If we're already depending on an abstraction like an ICommandHandler then the tight coupling that the mediator pattern prevents doesn't exist in the first place.
The mediator pattern also encapsulates complex operations so that they appear simpler from the outside.
return mediator.Send(request);
is not simpler than
return requestHandler.HandleRequest(request);
The complexity of the two interactions is identical. Nothing is "mediated." Imagine that you're about to swipe your credit card at the grocery store, and then someone offers to simplify your complex interaction by leading you to another register where you do exactly the same thing.
What about CQRS?
A mediator is neutral when it comes to CQRS (unless we have two separate mediators, like ICommandMediator and IQueryMediator.) It seems counterproductive to separate our command handlers from our query handlers and then inject a single interface which in effect brings them back together and exposes all of our commands and queries in one place. At the very least it's hard to say that it helps us to keep them separate.
IMediator is used to invoke command and query handlers, but it has nothing to do with the extent to which they are segregated. If they were segregated before we added a mediator, they still are. If our query handler does something it shouldn't, the mediator will still happily invoke it.
I hope it doesn't sound like a mediator ran over my dog. But it's certainly not a silver bullet that sprinkles CQRS on our code or even necessarily improves our architecture.
We should ask, what are the benefits? What undesirable consequences could it have? Do I need that tool, or can I obtain the benefits I want without those consequences?
What I am asserting is that once we're already depending on abstractions, further steps to "hide" a class's dependencies usually add no value. They make it harder to read and understand, and erode our ability to detect and prevent other code smells.

Partly this was answered here: MediatR when and why I should use it? vs 2017 webapi
The biggest benefit of using MediaR(or MicroBus, or any other mediator implementation) is isolating and/or segregating your logic (one of the reasons its popular way to use CQRS) and a good foundation for implementing decorator pattern (so something like ASP.NET Core MVC filters). From MediatR 3.0 there's an inbuilt support for this (see Behaviours) (instead of using IoC decorators)
You can use the decorator pattern with services (classes like FooService) too. And you can use CQRS with services too (FooReadService, FooWriteService)
Other than that it's opinion-based, and use what you want to achieve your goal. The end result shouldn't make any difference except for code maintenance.
Additional reading:
Baking Round Shaped Apps with MediatR
(which compares custom mediator implementation with the one MediatR provides and porting process)
Is it good to handle multiple requests in a single handler?

Related

MediatR when and why I should use it? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
It might have been asked before but I cannot find even in the official site why I should use MediatR and what problems it solves?
Is it because I can pass a single object in my constructor rather than a multitude of Interfaces?
Is it a replacement or competitor of ServicesBus etc...
Basically what are the benefit and what problem does it solve
I want to buy into it but its not clear to me why I should use it.
many thanks
Is it because I can pass a single object in my constructor rather than
a multitude of Interfaces?
No.
Is it a replacement or competitor of ServicesBus etc...
No.
Basically what are the benefit and what problem does it solve
Among other things, one of the problem MediatR is trying to solve is DI Constructor Explosion in your MVC controllers
public DashboardController(
ICustomerRepository customerRepository,
IOrderService orderService,
ICustomerHistoryRepository historyRepository,
IOrderRepository orderRepository,
IProductRespoitory productRespoitory,
IRelatedProductsRepository relatedProductsRepository,
ISupportService supportService,
ILog logger
)
This is a highly debated topic and there is no one-size-fits-all solution, take a look at this question
How to avoid Dependency Injection constructor madness?
If you want to hide dependencies behind even more abstractions, then at this point you will want to take a look at all the options, like refactoring, separating concerns a little more, or other techniques.
In all honesty, the example problem and solution given on the MediatR website is a little suspect, however it does have its uses. In short, you need to choose whats right for you and your environment.
Overview of the Mediator Pattern
A mediator is an object that makes decisions on how and when objects interact with each other. It encapsulates the “how” and coordinates execution based on state, the way it’s invoked or the payload you provide to it.
In regards to the spirit of your question, you should really have a look at this site:
Simplifying Development and Separating Concerns with MediatR
MediatR is an open source implementation of the mediator pattern that
doesn’t try to do too much and performs no magic. It allows you to
compose messages, create and listen for events using synchronous or
asynchronous patterns. It helps to reduce coupling and isolate the
concerns of requesting the work to be done and creating the handler
that dispatches the work.
More about Mediator Pattern
Can you in your own opinion describe why would you use it
The mediator pattern helps decoupling your application via communication through a mediator (its a thing) .
Usually a program is made up of a large number of classes. However, as more classes are added to a program, the problem of communication between these classes may become more complex. This makes the program harder to read and maintain. Furthermore, it can become difficult to change the program, since any change may affect code in several other classes.
With the mediator pattern, communication between objects is encapsulated within a mediator object. Objects no longer communicate directly with each other (decoupling), but instead communicate through the mediator. This reduces the dependencies between communicating objects, thereby reducing coupling.
In modern software, the mediator pattern is usually found within many frameworks, however you can create your own, or use one of many that are available.
From here, i think you should probably just do more research, i mean usually you figure out you need these things before you research them, however in this case i think you really need to find some good examples to know whether you want the Mediator Pattern, and even more The MediatR library
Update
wired_in had some great practical comment on this
All MediatR does is service locate a handler for a request. That is
not the mediator pattern. The "mediator" in this instance, does not
describe how two objects communicate, it uses inversion of control
that is already being used in an application and just provides a
useless layer of abstraction that only serves to make an application
harder to reason about as a whole. You already achieve decoupling by
using standard constructor injection with IoC. I don't understand why
people buy into this. Let's create multiple composite roots just so we
don't have to put interfaces in our constructor.
and
The OP is completely justified in questioning the point of MediatR.
The top responses I hear to the question involve explaining the use of
the mediator pattern in general, or that it makes the calling code
cleaner. The former explanation assumes that the MediatR library
actually implements the mediator pattern, which is far from clear. The
latter is not a justifcation for adding another abstraction on top of
an already abstracted IoC container, which creates multiple composite
roots. Just inject the handler instead of service locating it
It is just a way to implement communication between your business logic components.
Imagine that you have:
FirstRequest // which handled by FirstRequestHandler(FirstRequest)
SecondRequest // which handled by SecondRequestHandler(SecondRequest)
ThirdRequest // which handled by ThirdRequestHandler(ThirdRequest)
... there are hundreds of them ...
And then comes ComplexRequest, when ComplexResponse have to be a combination of FirstResponse and ThirdResponse.
How should we solve this?
Well, ComplexRequestHandler would have to inject FirstHandler and ThirdHandler, get their results, and combine them.
But why should ComplexRequestHandler should have access to FirstRequestHandler interface ?
Why we should bother to inject First, Third ... OneHundredAndTwentythHandler into our ComplexHandler ?
What MediatR gives us in such use case, is a third party that tells us:
"Give me a request, and I"ll get you the right response, Trust me!"
So ComplexHandler doesn't know anything about First and Third Handlers.
It knows only about the required requests and responses (which usually are only just wrapping DTOs).
Note: You don't have to necessarily use the MediatR library for that. You can read about the Mediator Pattern and implement one yourself.

The Dependency Inversion Principle with .NET Framework classes

I'm trying to understand SOLID principles, in particular The Dependency Inversion Principle.
In this is SO answer it is explained very well.
I think I have understood that I can't create any instance of a class inside my class. Is it right?
But if I have to save to disk some content, can I create an instance of System.IO.File or do I have to inject it?
I don't understand where is the limit, if I can't instance my own classes or if I can't either instance .NET Framework classes (or whatever other framework).
UPDATE:
I think File is a bad example because is declared as static.
By the way, does this principle apply to static classes?
The S of SOLID stands for SRP (Single Responsibility Principle). You won't violate it by using System.IO.File inside a class directly, once you keep that class with one single responsibility.
It's a good idea trying to abstract the purpose behind using System.IO.File. Let's suppose you need it to generate a log. Then you would probably do something like:
public interface IMyLogger
{
void GenerateLog(IEnumerable<string> content);
}
public class FileLogger: IMyLogger
{
public void GenerateLog(IEnumerable<string> content)
{
System.IO.File.WriteAllLines("C:/Log", content);
}
}
Maybe it's not just a log, it's something more important, like generating a file so other system/app (even external) read it and do some job.
If you are trying to use a DDD approach, the interface could belong to your domain, and the implementation could belong in the application. Then you register your interface as a service and inject it.
The class which needs an IMyLogger actually doesn't need to know how is the log being generated, it just needs the job to be done.
You can apply the same idea when you need to send an email inside some business logic in your domain. Instead of making a connection to an Exchange inside your domain directly, create an interface INotifier and a MailNotifier implementing it to be injected.
Somewhere down the chain of dependencies you will need to use the concrete class directly. Even if you use a DI framework like Ninject, the framework itself will create an instance of the concrete type, so it will not be injected into the framework (which wouldn't make sense, of course).
You can only abstract something away to a certain level. It will vary from project to project - you have to ask yourself if you need another level of abstraction (be it for modularity, unit testing etc.). I think this is very important - you want to be pragmatic, not create layers upon layers of abstractions just for the sake of it.
By the way, does this principle apply to static classes?
Yes, it does. But with static classes you have to introduce a wrapper, which will delegate calls to the static class, because a static class cannot implement interfaces.
There is no point in applying a principle just for the sake of it. Think in a pragmatic way.
If you want to unit-test a method that uses hard coded file accesses, your unit tests will access these files. This is usually not desired as you must set up or clean up these files. To avoid this, you would inject a service which wraps these file accesses. This allows you to replace the real service with a fake one during the unit tests. This fake service can provide hard coded test data for read accesses and dump written data to memory for later analysis or simply do nothing. Btw.: NSubstitute can create fake services at runtime easily.
The injection of services allows you to achieve Unit Test Isolation. E.g. you can test some logic without depending on correct file handling or database accesses or the correct functioning of other services. Injecting a service is just one way to do it. You could also just specify a method parameter as IEnumerable<string> with the content of the file instead. Events can also be used for decoupling. Instead of writing to a log, you could raise a log event.
Most DI frameworks allow you to specify the lifetime of objects. One of these options is Singleton, which means that the DI container will always return the same instance of a requested service. This allows you to wrap static classes in a service that behaves statically.

Is it a code smell that a repository has change events?

I've not seen change events being used in repository pattern implementations, but I'd like to have my repository like this:
interface IEntityRepository
{
event EventHandler<EntityChangedEventArgs> EntityAdded;
event EventHandler<EntityChangedEventArgs> EntityRemoved;
IEnumerable<Entity> GetAll();
Entity GetById(int id);
}
This is largely because my entities can be added and removed from the outside only, and not by the client of IEntityRepository.
Am I thinking fundamentally wrong about the repository pattern by doing like this, or do I have a valid case?
I'd say yes, if you intend to use Fowler's actual Repository Pattern. That pattern is intended to be a mediator between business and data layers by exposing a collection-like interface. It was not intended to actually hold data. That said, if you merely want to create a collection that wraps an API and exposes events when things change, by all means do so. Sometimes you don't need to follow a predefined pattern.
If you want it to be a pattern, I'd say it looks more like an Object Pool or Observer pattern. Consider the case of IObservable using Reactive Extensions (Rx). It would allow you to react to the PInvoke layer, and force your responsibilities down the line. The code actually winds up being more effective than events. By using events, you have to maintain this repository, keep track of object lifetime, probably make this repository a singleton and give it some thread management. With Rx, you simply push an action on the observer's queue.
But in the end, use whatever feels most natural to you. Patterns are just suggestions, and don't always exist for every potential use case. This is one of those cases.
I have a similar issue where I need to publish events to an event store for CUD operations against a database (not concerned about Read operations). Rather than modify my repo I instead created a decorator and injected it (using SimpleInjector). That satisfies the Open/Closed principle and Single Responsibility, and actually it's provided a much cleaner way to handle that requirement.

What do programmers mean when they say, "Code against an interface, not an object."?

I've started the very long and arduous quest to learn and apply TDD to my workflow. I'm under the impression that TDD fits in very well with IoC principles.
After browsing some of TDD tagged questions here in SO, I read it's a good idea to program against interfaces, not objects.
Can you provide simple code examples of what this is, and how to apply it in real use cases? Simple examples is key for me (and other people wanting to learn) to grasp the concepts.
Consider:
class MyClass
{
//Implementation
public void Foo() {}
}
class SomethingYouWantToTest
{
public bool MyMethod(MyClass c)
{
//Code you want to test
c.Foo();
}
}
Because MyMethod accepts only a MyClass, if you want to replace MyClass with a mock object in order to unit test, you can't. Better is to use an interface:
interface IMyClass
{
void Foo();
}
class MyClass : IMyClass
{
//Implementation
public void Foo() {}
}
class SomethingYouWantToTest
{
public bool MyMethod(IMyClass c)
{
//Code you want to test
c.Foo();
}
}
Now you can test MyMethod, because it uses only an interface, not a particular concrete implementation. Then you can implement that interface to create any kind of mock or fake that you want for test purposes. There are even libraries like Rhino Mocks' Rhino.Mocks.MockRepository.StrictMock<T>(), which take any interface and build you a mock object on the fly.
It's all a matter of intimacy. If you code to an implementation (a realized object) you are in a pretty intimate relationship with that "other" code, as a consumer of it. It means you have to know how to construct it (ie, what dependencies it has, possibly as constructor params, possibly as setters), when to dispose of it, and you probably can't do much without it.
An interface in front of the realized object lets you do a few things -
For one you can/should leverage a factory to construct instances of the object. IOC containers do this very well for you, or you can make your own. With construction duties outside of your responsibility, your code can just assume it is getting what it needs. On the other side of the factory wall, you can either construct real instances, or mock instances of the class. In production you would use real of course, but for testing, you may want to create stubbed or dynamically mocked instances to test various system states without having to run the system.
You don't have to know where the object is. This is useful in distributed systems where the object you want to talk to may or may not be local to your process or even system. If you ever programmed Java RMI or old skool EJB you know the routine of "talking to the interface" that was hiding a proxy that did the remote networking and marshalling duties that your client didn't have to care about. WCF has a similar philosophy of "talk to the interface" and let the system determine how to communicate with the target object/service.
** UPDATE **
There was a request for an example of an IOC Container (Factory). There are many out there for pretty much all platforms, but at their core they work like this:
You initialize the container on your applications startup routine. Some frameworks do this via config files or code or both.
You "Register" the implementations that you want the container to create for you as a factory for the interfaces they implement (eg: register MyServiceImpl for the Service interface). During this registration process there is typically some behavioral policy you can provide such as if a new instance is created each time or a single(ton) instance is used
When the container creates objects for you, it injects any dependencies into those objects as part of the creation process (ie, if your object depends on another interface, an implementation of that interface is in turn provided and so on).
Pseudo-codishly it could look like this:
IocContainer container = new IocContainer();
//Register my impl for the Service Interface, with a Singleton policy
container.RegisterType(Service, ServiceImpl, LifecyclePolicy.SINGLETON);
//Use the container as a factory
Service myService = container.Resolve<Service>();
//Blissfully unaware of the implementation, call the service method.
myService.DoGoodWork();
When programming against an interface you will write code that uses an instance of an interface, not a concrete type. For instance you might use the following pattern, which incorporates constructor injection. Constructor injection and other parts of inversion of control aren't required to be able to program against interfaces, however since you're coming from the TDD and IoC perspective I've wired it up this way to give you some context you're hopefully familiar with.
public class PersonService
{
private readonly IPersonRepository repository;
public PersonService(IPersonRepository repository)
{
this.repository = repository;
}
public IList<Person> PeopleOverEighteen
{
get
{
return (from e in repository.Entities where e.Age > 18 select e).ToList();
}
}
}
The repository object is passed in and is an interface type. The benefit of passing in an interface is the ability to 'swap out' the concrete implementation without changing the usage.
For instance one would assume that at runtime the IoC container will inject a repository that is wired to hit the database. During testing time, you can pass in a mock or stub repository to exercise your PeopleOverEighteen method.
It means think generic. Not specific.
Suppose you have an application that notify the user sending him some message. If you work using an interface IMessage for example
interface IMessage
{
public void Send();
}
you can customize, per user, the way they receive the message. For example somebody want to be notified wih an Email and so your IoC will create an EmailMessage concrete class. Some other wants SMS, and you create an instance of SMSMessage.
In all these case the code for notifying the user will never be changed. Even if you add another concrete class.
The big advantage of programming against interfaces when performing unit testing is that it allows you to isolate a piece of code from any dependencies you want to test separately or simulate during the testing.
An example I've mentioned here before somewhere is the use of an interface to access configuration values. Rather than looking directly at ConfigurationManager you can provide one or more interfaces that let you access config values. Normally you would supply an implementation that reads from the config file but for testing you can use one that just returns test values or throws exceptions or whatever.
Consider also your data access layer. Having your business logic tightly coupled to a particular data access implementation makes it hard to test without having a whole database handy with the data you need. If your data access is hidden behind interfaces you can supply just the data you need for the test.
Using interfaces increases the "surface area" available for testing allowing for finer grained tests that really do test individual units of your code.
Test your code like someone who would use it after reading the documentation. Do not test anything based on knowledge you have because you have written or read the code. You want to make sure that your code behaves as expected.
In the best case you should be able to use your tests as examples, doctests in Python are a good example for this.
If you follow these guidelines changing the implementation shouldn't be an issue.
Also in my experience it is good practice to test each "layer" of your application. You will have atomic units, which in itself have no dependencies and you will have units which depend on other units until you eventually get to the application which in itself is a unit.
You should test each layer, do not rely on the fact that by testing unit A you also test unit B which unit A depends on (the rule applies to inheritance as well.) This, too, should be treated as an implementation detail, even though you might feel as if you are repeating yourself.
Keep in mind that once written tests are unlikely to change while the code they test will change almost definitely.
In practice there is also the problem of IO and the outside world, so you want to use interfaces so that you can create mocks if necessary.
In more dynamic languages this is not that much of an issue, here you can use duck typing, multiple inheritance and mixins to compose test cases. If you start disliking inheritance in general you are probably doing it right.
This screencast explains agile development and TDD in practice for c#.
By coding against an interface means that in your test, you can use a mock object instead of the real object. By using a good mock framework, you can do in your mock object whatever you like.

Options for IoC Auto Wiring in Domain Driven Design

In my latest ASP.NET MVC 2 application I have been trying to put into practice the concepts of Domain Driven Design (DDD), the Single Responsibility Principle (SRP), Inversion of Control (IoC), and Test Driven Development (TDD). As an architecture example I have been following Jeffery Palermo's "Onion Architecture" which is expanded on greatly in ASP.NET MVC 2 in Action.
While, I have begun to successfully apply most (some?) of these principles I am missing a key piece of the puzzle. I am having trouble determining the best mechanism for auto-wiring a service layer to my domain entities.
As an example: each domain entity that needs the ability to send an email should depend on an IEmailService interface. From my reading, best practice to reveal this dependency would be to use constructor injection. In my UI layer I perform a similar injection for repository interface implementations using the StructureMapControllerFactory from ASP.NET MVC Contrib.
Where I am confused is what is the best mechanism for auto-wiring the injection of the necessary services into domain entities? Should the domain entities even be injected this way? How would I go about using IEmailService if I don't inject it into the domain entities?
Additional Stack Overflow questions which are great DDD, SRP, IoC, TDD references:
IoC Containers and Domain Driven Design
How to avoid having very large objects with Domain Driven Design
Unless I'm misunderstanding your intent and instead I'm choosing to focus on semantics I'm going to dissect this statement "As an example: each domain entity that needs the ability to send an email should depend on an IEmailService interface."
I would have to argue this is upon itself is an extreme bastardization of DDD. Why should a domain entity ever need to depend on an email service? IMO it shouldn't. There is no justification for it.
However there are business operations in conjunction with a domain entity that would require the need to send emails. You should have your IEmailService dependency contained in this class here, not the domain entity. This class would most likely fall into one of a few nearly synonymous names: Model, Service or Controller dependent upon which architecture/layer you're in.
At this point your StructureMapControllerFactory would then correctly auto wire everything that would use the IEmailService.
While I might be minorly over generalizing it's pretty much standard practice to have domain entities be POCOs or be nearly POCOs (to avoid violation of the SRP) however frequently SRP is violated in domain entities for sake of serialization and validation. Choosing to violate SRP for those types of cross cutting concerns is more of a personal belief stance as opposed to a "right" or "wrong" decision.
As a final follow up if your question is on the portion of code that is truly operating in a stand alone service whether web or OS based and how to wire up the dependencies from that, a normal solution would be take over the service at a base level and apply IOC to it in the same similar fashion as the StructureMapControllerFactory does in MVC. How to achieve this would be entirely dependent upon the infrastructure you're working with.
Response:
Lets say you have IOrderConfirmService which has a method EmailOrderConfirmation(Order order). You would end up with something like this:
public class MyOrderConfirmService : IOrderConfirmService
{
private readonly IEmailService _mailer;
public MyOrderConfirmService(IEmailService mailer)
{
_mailer = mailer;
}
public void EmailOrderConfirmation(Order order)
{
var msg = ConvertOrderToMessage(order); //good extension method candidite
_mailer.Send(msg);
}
}
You would then have your OrderController class that would be something like
public class OrderController : Controller
{
private readonly IOrderConfirmService _service;
public OrderController(IOrderConfirmService service)
{
_service= service;
}
public ActionResult Confirm()
{
_service.EmailOrderConfirmation(some order);
return View();
}
}
StrucutreMap will inherently build up you're entire architecture chain when you use constructor injection correctly. This is the fundamental difference between tight coupling and inversion of control. So when the StructureMapFactory goes to build up your controller the first thing it will see is that it needs IOrderConfirmService. At this point it will check if it can plug IOrderConfirmService directly which it can't because it needs IEmailService. So it will check if it can plug IEmailService and for argumentsake lets say it can. So at this point it will build EmailService, which it will then build MyOrderConfirmService and plug in EmailService, and then finally build OrderController and plug in MyOrderConfirmService. This is where the term inversion of control comes from. StructureMap will build the EmailService first in the entire chain of dependencies and ending last with the Controller. In a tightly coupled setup this will be the opposite where the Controller will be built first and have to build the business service and then build the email service. Tightly coupled design is very brittle when compared to IOC.

Categories