Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I inject things into my entities?

Tags:

oop

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

like image 378
therealhoff Avatar asked Dec 23 '22 14:12

therealhoff


2 Answers

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).

like image 174
Bil Simser Avatar answered Mar 20 '23 11:03

Bil Simser


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.

like image 20
moffdub Avatar answered Mar 20 '23 12:03

moffdub