tags:

views:

308

answers:

5

When using an IoC container, is it considered good design to inject other classes into them? i.e. a persistence class

+2  A: 

This is the Spreadsheet Conundrum: do you write repository.store(entity) or entity.storeIn(repository)?

Each has its merits. I generally tend to favor repository.store(entity) for the main reason that I keep the methods of my entities domain-focused. It makes sense to write pen.dispenseInkOnto(Surface) because that is what pens do. It makes a little less sense to write pen.storeIn(penRepository).

The downside is you need to provide access to the internals of the entity class to the persistence class. Aside from getters, which introduce the same problem as entity.storeIn(), I'd go with a friend class, package protected access, internal access, or a friend class pattern of some kind to restrict access to internal to only those who need it.

As far general injection of classes, in the pen.dispenseInkOnto(Surface) example, you could very well make Surface an interface and use injection. I see no problem with this as long as you inject other entities, value objects, or services.

moffdub
I'll note that repository.store(entity) doesn't tie you to a persistence implementation either. You can use the GoF Abstract Factory pattern to create a repository factory that will return an implementation that either stores to DB or to memory.
moffdub
A: 

Absolutely. That's how you don't tie the class to some specific persistence implementation. Sometimes I write mock DAO classes that "persist" to memory structures only, and I inject these when unit testing.

Germán
+2  A: 

I'd generally recommend against it.

It generally keeps your domain cleaner when your entities are given the things they need to do to perform their duties. When they have to look things up they are often taking shortcuts, shortcuts that can be avoided by doing more analysis into the domain and the relationships between members of the domain.

Application and Domain services are generally a better place to allow injection in my opinion. They can also be responsible for creating/persisting entities.

aaronjensen
+3  A: 

Generally I advise against it. Entities are just that and should represent some identifiable and important part of your core domain. They should have one responsibility and be very, very good at doing it. If the entity requires additional services in order to complete a task (say persist itself) you're starting to let things like infrastructure creep into your domain. Even the notion of an Invoice being able to calculate it's billing value isn't necessarily the responsibility of the Invoice class. It may require things like sales tax, shipping costs, customer discounts. Once you open those doors and try to start bringing those items into your Invoice entity, it becomes an everything class. Domain services are better suited for co-ordination of entities and providing services to them. Infrastructure services are better suited for things like persistance and external communications. Both of those are fine to inject other services into via IoC (and encouraged so they themselves don't become bloatware).

Bil
+4  A: 

I advise against it too, but would recommend reading the DDD forum as there are many posts about it on there. Its questionable whether you should even inject into domain services, in more complex domains I think not.

As Bil said services are great for cross-aggregate coordination and especially any co-ordination with anything outside the domain.

Colin Jack