How *not* to inject services in entities
By Jérémie Chassaing on Wednesday, March 4, 2009, 16:01 - Domain Driven Design - Permalink
I’ve seen lot of people asking where and how to
inject services in entities. The services in question are often repositories by
the way…
The response is simple :
- DO NOT inject services in entities !
- Ok I see, you’re against dependency injection
- NO, I'm not against dependency injection, I use it a lot.
- You can still use a static service locator…
- I avoid service locator when I can, especially when the service locator must be static…
– So you’ll get an anemic object model !
- I don’t think so.
Injecting services in entities is wrong
You’ll find me a bit presumptuous, but I say it again : Injecting services in entities is wrong.
Nesting objects is not a problem from an OO point of view, but we’re talking about a special kind of objects, entities.
Entities are all about their state management, and this state management can require several objects.
- Code infrastructure objects like lists or dictionary to handle collection of data,
- Object oriented constructs to leverage code maintenance techniques like strategies.
Entities don’t have to be classes with public setters and getters… you should even avoid this to keep you entities in a consistent state.
But there is no reason for an entity to keep a reference on a service, since it’s not part of its state.
There are usually three situations in which people thinks they need it :
- Lazy loads
- Relations
- Behavior methods
Let’s review each point…
Lazy loads
Sometimes, an entity property is heavy to load and is not required by all code paths. In this case, loading it upfront can lead to performance problems.
The usual way to work it out is to hold a reference to a data access object or a repository and to load and cache the requested data on demand.
Using a data access layer object in the entity is clearly a break of persistence ignorance, but using a repository is not a better option.
The repository is a way to abstract persistence in the model, but it’s still a persistence concern even if modeled in terms of domain terms.
I’ve already posted about ways to solve this problem in Lazy load and persistence ignorance and part 2.
Relations
I was twitting yesterday with Kyle Baley about the need to have an Event repository in the Users entity. He wanted to get the User Team for the current event. I think you don’t need more context to understand the problem.
The User did not know about the current event so it needed the Event repository to find it and find the corresponding team.
But why does the User entity expose a CurrentTeam property if it doesn’t know about Events ? There’s something missing here.
The whole picture becomes clearer if you add a Participant entity that embodies the participation of a user to an Event, and no repository is needed anymore since you don’t need a CurrentTeam property on User.
Make relations clear instead of hiding it in repositories.
Behavior methods
If I have mail message entity and I want a Send method on it ?
Tiding your entity to the service that will use it is not conceptually satisfying. The server that will send the message is a medium and is not part of the entity itself.
It’s seems better to call server.Send(message).
The problem is that you can end breaking the tell don’t ask principle because the Send method will ask the message for each property value. And you can be tempted to put computations that should be in the message entity inside the Send method.
Let’s call Double Dispatch to the rescue !
- Design a server interface presenting a Send method that take the parameters it need (title, recipients, message body…)
- Add a SendThrough method to your entity that takes the server interface as parameter
- Implement SendTrhough so that it computes values to pass to the Send method
- That’s it.
Here is a small sample implementation :
public interface IMailService
{
void Send(string sender, string recipient, string subject, string body);
}
public class Message
{
//...
public void SendThrough(IMailService mailService)
{
string subject = isReply ? "Re : " + title : title;
mailService.Send(sender, recipient, subject, GetMessageBody(content));
}
}
The entity is not tied to the service before needed. So no need for injection.
Is injection useless ?
There is no problem to inject services with other services, and it’s even easier since services have no state, they only need their dependencies in constructor, and to my opinion it’s the cleanest injection mode.
Usually domain services will need infrastructure services dependencies, and in this case a dependency injection framework can make things easier.
Following the preceding advice, you’ll never need to use your dependency injection framework as a service locator, and you’ll never have to perform buildups on your entities, and you’ll feel much better.
What’s your way to deal with it ?
For now I’ve always find a way to get rid of services inside entities, but I really would like to hear cases where you’re stuck with it to see if another way is possible, or cases where you think there is really a good reason to go this way.
Comments
Good post. I'm not so sure about your email example though - I agree with the concept (double dispatching), but aren't you really placing behaviour where it doesn't belong here? Should a Message really know how to send itself? In cases like this it can sometimes feel as if the 'tell, dont ask' and separation of concern principles pull in opposite directions. However, I'm not so sure that 'tell, don't ask' should be taken this far - I think maybe it makes more sense at a higher level.
@frederik> Yes, this is perhaps not the best choice. But it was easier since everyone knows the context.
I've recently started learning about DDD and although many of the concepts
make sense to me, DI + DDD has been giving me trouble so far.
Although I agree 100% that we shouldn't be injecting anything into entities
and that we shouldn't resolve entities using a container (it doesn't even make sense), my "problem" is that now "clients" of the domain model that are indeed resolved through
a container, now have to take a whole bunch of dependencies in their constructor,
that are totally unrelated to them, just so they can pass them further down the path
to the model explicitly.
@Noobie> I agree that Dependency Injection creates a problem on container configuration. Especially a problem of configuration leak. It doesn't seem judicious to let the application know every implementation choices from any inner component... I have no absolute response for this so far, but I did several tries.
It will make a good next post topic !!
If I have, say a user entity with a password reset method, I feel it's better to use service injections into my entity at construction time (through an event-listener) than to use an application-service (i.e. in the layer above) 1) read the whole state of the user, 2) generate a new password, 3) fill the mail, 4) post it; when I could have
(:User).ResetPassword(send-email::true) with
[Dependency]
public virtual IMailer Mailer { get; set; }
thereby having the user entity know what it needs, of course abstracted over the functionality of sending something, but none-the-less I now reduce the number of steps taken to reset the password and pass the _domain concept_ which would be "a user can reset its password if it's forgotten it" in the ubiquitous language, to the _domain model_.
(I've written the code above IRL, hence the example)
Also, you could use AOP to put concerns atop of the method calls into your domain object, say one concern sending the mail, depending on the settings in your IoC for that concern (and then implement is, say, through another wrapper event listener in NHibernate/whatever which intersects that method and keeps track of the list of generated assemblies).
***
Also, you concept "lazy load"s is a strict subset of your "relations" concept, imho. While I agree on letting the persistence layer deal with lazy loading and your interesting IDataAccess-impl are improvements on your nono-example, does it makes sense _always_ to have a domain service do a say calculation which needs information directly tied to a specific entity?
E.g. I have AHistory and A where A has a CalculateCost() which fetches the histories and sums them through a repository. Since we almost never fetch the histories it kind of seems to make sense to me, and it works well. Of course, we could go fancy and have a lazy.Value with a delegate being invoked as a part of doing the calculation, but again, that seems like inverting the control a bit too much and bringing the concept of the total cost out of the domain where it belongs... The option being pushing knowledge of the AHistory repository higher up and performing the calculation there which seems coarser.
@Henrik> I'm still not comfortable with the idea that a User entity has a IMailer field.. I makes no sense to me.
I would prefere a ResetPassword(IPasswordResetHanlder handler) that would do internaly in the entity what's needed and would call a method on the handler to tell (tell not ask !) the information needed for sending a message through email or whatever other communication channel.
This way, no injection is needed, the User doesn't know about emails, it just gives necessary information to the handler.
Hi Jeremie, great post.
I am still fighting the PI paradigm. My qualm with this idea is it feels to me like it violates common encapsulation principles.
For example, a Folder class aggregates Document entities. It seems most appropriate that if I want to add a Document to a Folder instance I would write Folder.AddDocument(myDocument), where the Folder would then add the Document to its collection as well as create a DocumentRepository and with it add the Document to the data store. Isn't this implied in the Aggregate concept, where Folder would be the aggregate-root for the Aggregate containing Document? As the aggregate-root, should it not be responsible for hiding from the "client" all the logic related to its entities?
As the "client" of Folder, I want the AddDocument method to handle all the related logic and not write something like:
IDocumentRepository repository = RepositoryFactory.GetRepository<Document>();
repository.Add(myDocument);
Folder.Documents.Add(myDocument);
Which seems tedious and unintuitive.
OR
IDocumentRepository repository = RepositoryFactory.GetRepository<Document>();
Folder.AddDocumentWith(repository);
Which puts the responsibility of obtaining the right factory in the hands of the "client", as well as requiring it to know more about the inner workings of the Folder aggregate.
What do you think?
@Joniba>The difficult point here is that your entities map to technical terms...
It's sometimes possible to have a domain that contains technical terms but their implementation in the domain will be different from their usual implementation *because the domain should be clear of any technical problem* ! But verify that Folder and File actually belong to the Ubiquitous language.
In your case, the Folder is the aggregate root, so you get the folder from the repository, add the document to the folder. The repository will be responsible for the whole aggregate persistence including folder and document. You don't have to create a repository for documents.
Hope it helps
I'm thinking of cases of strategy and state patterns. Is is bad to inject an ITaxCalculator into an Order entity when a number of tax calculators and vary based on Order.OrderType? How would you go about reworking such an arrangement to comply with these principles?
@Jacely> Yes I would pass ITaxCalculator to the Order, but there are several things that make the strategy pattern acceptable despite what I'm advocating here :
- Services have side effects.
- A strategy is not a service since it has no side effects, it should only contain side effect free functions.
- A strategy will typically not be injected by an Dependency Injection framework but chosen by a factory depending on the OrderType.
- A strategy *is* tied to the state of the object since it's simply calculation tied to OrderType.
State pattern has similar properties, so you can perfectly use it too.
Feel free to use any pattern from GoF !
I agree with Henrik.
What 's the difference betwen fire an event or send the email directly inside the object?....
@bugeo> The difference is in the action/reaction...
'When the password is reset, a email should be sent...'
We could decide to send the email directly inside the ResetPassword method.
But the you have to do something more when the password is reset... let's say, prepare a timeout so that if the user didn't come back in 20 min, use another communication mean to try to notify him.
And then you want to warn the support team. And then...
Every time you need to add something you'll have to go back to the User entity, add a dependency, and modify the ResetPassword method to add this extra concern..
This is clearly not what you should do. Of course, if you do it, it'll work. But this is a code smell to have to change several time a method for external concerns.
With an event, you can register handlers from the outside to *react* to the PasswordWasReset event.
No need to change the ResetPassword anymore, and you can add as many handlers as needed.
This is what *Inversion Of Control* is about.
I was in the "Behavior methods" category and you advice made for a realy simple and understandable solution.
Thanks.
Hi!
I've got here looking for a way to inject a service inside an entity, which is something that I also would not like to do but I see no more options. The thing is I have an Id generator service and I want to use it to assign the IDs to the entities upon creation, without having to assign them by hand. Is this possible without having to inject the service? Can I somehow intercept the entity creation and call the service there to set the id?
Any help would be greatly welcome! I am not able to find a simple solution for this :-(
cheers and thank you!
@izan> I really think you should not inject a service in your entities for this purpose.
The service is only needed when creating a new entity. But dependencies should have a meaning for the lifetime of the object.
It seems that you need a factory here. The factory would be in charge of getting an id, and instantiating the new entity with this id.
I'd like to avoid the creation of a factory, and have the ID (not the Hibernate database ID, but a business ID) initialised upon creation. entity annotations only get as far as @PrePersist and so on, so I can't use them for that. I was thinking on implementing an annotation for this purpose, if I can't put the service in the constructor and have the ID initialised in there. I've got the service working in the constructor of the child entities, but didn't get it to work in the constructor of the abstract entity because I get javax.naming.NameNotFoundException: <my_project_name_here> not bound. Any ideas why it is bound on the childs and not on the parent?
@Izan> Where does this business ID come from ?
What it the reason to avoid the factory ?
Why put external creation logic into the object ?
Constructor should not call code from outside - too dangerous. Only organize and set fields from provided values.
ID is created based on certain business information, like node identifier, number of sequence and so on. It's like a TCP header, if you get what I mean: you apply a mask and get some business information from this ID.
The reason to avoid the factory is not to get into the hassle of creating one. I know it's not rocket science, but we are quite time-tight and would like to keep creation as simple as possible.
Yeah, putting this code in the constructor is not very nice, I agree :-( I'll probably move it to an interceptor and put it there, or set a constructor with the ID as parameter, but I'd rather make it as "painless" and automatic as possible.
What do you think about the interceptor thing?
@Izan> I'd go foth the constructor parameter.
I'm not a fan of the interceptor. I don't like to hide things.
With a factory you just replace new Thing(id, otherparms) by factory.CreateThing(otherparams) ... I think it won't be painfull to implement.
Yeah, I'm going for the constructor parameter too. Using he service locator inside the entity didn't make me feel very comfortable either, and use a factory also. It's not painful, it was just in case there was another options :-)
Thank you very much for your comments and your time!
Hi, I know I'm a little late to the discussion, but found you through the big G.
What if I want an interface where methods on the model should change the state and persist it?
I mean think about the following scenario:
var item = new Item()
item.Checkout(someUser)
public void Checkout(IUser user)
{
}
Now this is not some code I have, it's just an example. But would you rely on the UnitOfWork implementation instead? I mean if I was using something like nhibernate I would just need to set the CheckedOutTo = user and then leave out the repository call. But we still need to tell the nhibernate UnitOfWork to update the object at some point.
Also I feel that the following implementation where the client needs the repository (or a service) to checkout the item is a bit smelly.
itemRepository.Checkout(someItem, myUserObject);
someItem.Title = "hey";
itemRepository.Checkin();
@rasmus> why would you save the entity state inside the Checkout method ? This should be done at the same level that where the entity is retrieved from repository:
var item = repository.GetItem(id);
item.Checkout(..)
repository.Save(item);
Thanks for the blog post, I've been thinking about this issue for a while. The problem I have is that this seems to conflict with the DDD principle of 'all business logic should go in the domain layer'. People always use trivial examples for 'business logic' like mandatory fields or a range check. I'm interested in complex business logic like 'The Status field of Volunteer can only be set to Approved if the Job they are linked to is starting in the future and has a status of Confirmed'. How do you implement a rule like that inside the entity without using repositories. Or, more generally: What should an Entity do when it needs to look at values in arbitrary other entities?
It seems to me that the approach you advocate will lead to anemic domain models because any reasonably complex business logic ends up going in a tasks or service layer that _can_ access the repositories.
@codeulike> I would try to give my personal opinion about your question. My answer to your question depends on the relation between first entity - say A - who wants to access values from other entities - say B. If A is the aggregate root and B is part of A, then you can access properties of B directly inside A. If A and B are part of different aggregates, things get complicated and there is room for debate. I would personally put that business logic inside a repository in this case, so that you can easily change it without altering A and also without creating a dependency between two entities being part of different aggregates.
Concrete, in your example, I would think that Volunteer and Job are in the same aggregate and there is an association between the two so you can access the values of Job without querying a repository.
Thanks gmisca, thats an answer that makes sense to me, as in you leave room for debate when there are different aggregates. I've got a long-running question up on StackOverflow about this issue:
http://stackoverflow.com/questions/...
It seems like you've got some good ideas in this area, maybe post an answer there?