Reputation: 253
In the book 'Clean Architecture' (Robert C. Martin) p. 191, he states that "Entity is pure business logic and nothing else". I am unsure of how literal I should interpret this statement with respect to the entites knowledge of a persistence mechanism.
I am assuming the entity objects are stateful - that they manipulate the business data that they represent. If so, the persistence-layer must be informed of changes to that data, so it can persist those changes. Therefore; are the entities allowed to hold a reference to a persistence-interface (or a unit-of-work-interface, if a more elaborate design)?
I am inclined to think that an entity-object holding such a reference (and calling it from within the entity) would be something else than 'pure business rules'. But I have a feeling it does not count as long as the entities hold reference to an interface?
And if the entities should NOT hold reference to persistence-mechanisms, are there any other good patterns for persisting changes to business data?
Upvotes: 9
Views: 5328
Reputation: 864
An entity (DTO) should not know about the persistence mechanism. Because the idea of the clean architecture is to make your whole business logic independent of UI and frameworks. And by giving knowledge of persistence mechanism inside your DTO, your entities will become framework dependent.
Interaction should be this way:
UI <-> VM/Presenter <->* Use-Case (Interactor) <->* Adapters over frameworks (Plugins)
Entities are supposed to be used between the Usecases and Plugins. So if the business logic which resides in a concrete use case implementation manipulates the entity, it can directly call a method of plugin to persist the changes as it holds reference to that plugin.
Upvotes: 0
Reputation: 1369
he states that "Entity is pure business logic and nothing else". I am unsure of how literal I should interpret this statement with respect to the entites knowledge of a persistence mechanism.
Very literal.
Business objects should not know anything about how they are being persisted.
The architecture of your application should be:
Upvotes: 2
Reputation: 726
There are 2 major line of thoughts regarding this matter. Both of them represented by a different design pattern. Both of these options also consider you're dealing with stateful entities which model aspects of your business scenario, in that sense, they're aware of the "data" that will be persisted however, they are not necessarily aware of the persistence mechanism itself.
Now, regarding the persistence mechanism, the first way of doing it is probably the most familiar to old-J2EE or Rails practitioners where the entity is fully aware that it will be loaded/saved into an underlying persistence and its interface will convey such methods as "get", "insert", "update". That's been called the "Active Record" (Martin Fowler, Patterns of Enterprise Application Architecture) pattern. That is, the entity while modelling an aspect of your business, it will represent also a straight record in the database and be able to save/load itself.
The other approach, which will be more inline with the "Clean Architecture" you mentioned, has been called by some authors the "Data Mapper" (also Martin Fowler, Patterns of Enterprise Application Architecture) pattern. In that matter the entity remains ignorant of the persistence mechanism (it will be "pure business logic, and nothing else") and you delegate to an external player (class / whatever) the responsibility of "mapping" the "data" that the entity currently holds into and out-of the persistence mechanism/layer.
In other words, when taking such an approach, you will delegate to a translator the responsibility of understanding the persistence mechanism and translating from database-to-entity and from entity-to-database. That way, your entities are never even aware that they are persisted somewhere else, much less of the inner workings of such persistence process.
The interface of persistence Data Mapper will be something along these lines:
interface IMyDataMapper {
void Save(IMyEntity entity);
IMyEntity Get(whatever criteria you use to find the entity);
}
So, from that interface, its responsibility is clear:
Upvotes: 4
Reputation: 29629
This is primarily opinion based - you may find people voting to close this question.
However...
As I interpret the quote (and the book itself, though it's a while since I read it), the purpose is not to define a directly implementable technical architecture, but to give you a way of evaluating your decisions.
At one end of the spectrum, you may have a component which mixes display, application, business and persistence logic all in one. We can all agree this is not "clean" by any standard, let alone Uncle Bob's.
At the other end of the spectrum is a pure, clean design in which business entities have no reference to persistence. You can achieve this through sending messages/events, for instance; the business entity decides that a business process has completed, and sends a message to say as much, and then the persistence engine decides when and how to write this to storage.
In my experience, in practical terms, we find ourselves somewhere on the spectrum between those two ends, and should seek to move towards "clean", rather than achieving "cleanliness" in one go.
Upvotes: 1
Reputation: 3953
I think even if you are not doing Clean Architecture, your entities should know nothing about the persistence mechanisms since these can be variable and arbitrarily complicated.
The solution to the issue you raise would be to have the layer that is changing the entities also make sure that these changes are persisted.
Upvotes: 0