8

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?

unique_ptr
  • 233
  • 3
  • 9

5 Answers5

4

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:

  • It receives an entity (which is unaware of this operation) and reads its data to store it somewhere else.
  • It receives criteria to finding stored data somewhere else, finds it and populates an entity object with this data to return it to you.
Pedro Goes
  • 726
  • 3
  • 10
  • 1
    Thanks! But, how would the data-mapper know if the entity is changed or not? The reason for my initial question is that I am considering implementing the caller-registration pattern (from POEAA, which you mention). This require that the entities be given access to a unit-of-work-reference. – unique_ptr Jun 20 '18 at 14:15
  • Is the common approach to simply compare the entity-object with the database? – unique_ptr Jun 20 '18 at 14:16
  • The Data Mapper pattern can be without it actively knowing if the entity changed or not. If you want, you can design entities with clear Command and Query method definitions (not to be confused with full-scale CQRS models) and let the decision to whether save or not the entity rely on the application layer of your architecture. That way, the application layer understands whether Command methods (that is, state-altering methods) were called on which of your entities so it can decide which entities need to be saved (not needing to understand which were the actual changes the models suffered). – Pedro Goes Jun 20 '18 at 20:04
  • If your concern is performance and you which to avoid to overwrite data that never changed (instead of full-saving an entity whenever ordered to), what you can implement is some sort of "context" where you register the data as it was loaded and compare it when the application layer orders the data mapper to persist. So, the application layer order the data mapper to save the entity, the mapper compares the new entity to the one stored in the "context" and decides which parts of the data needs to be updated specifically. – Pedro Goes Jun 20 '18 at 20:06
  • I think you have a good point here. My current entity design (actually aggregate design ref. Domain Driven Design) are seperated along the query (ask for information) and command (perform state altering action) lines - assuming my understanding of command/query-methods is correct. So now, if an interactor calls an entity-command-method, the interactor itself should know that the entity changed state. – unique_ptr Jun 20 '18 at 20:23
  • Yes! My concern was always performance. If the entities (or aggregates, really) where small in terms of memory-size, it would be no problem: one could simply overwrite the data regardless of change. – unique_ptr Jun 20 '18 at 20:26
  • Well, I think you're set on a good path. You should always strive to design small aggregates so performance shouldn't be a problem. If you need to improve, creating a registry of loaded entities for comparison should be a good path! Also, your understanding of commands and queries is correct! Glad to be of help! – Pedro Goes Jun 20 '18 at 21:19
2

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:

  • Business Layer - Includes entities, business rules, domain events, repository interfaces etc.
  • Data Layer - References the business layer and implements the repository interfaces.
  • Service Layer - References the business layer, coordinates the logic of the application and persists data using the repository interface from the business layer.
Cool Breeze
  • 1,289
  • 11
  • 34
1

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.

Neville Kuyt
  • 29,247
  • 1
  • 37
  • 52
  • Hi Neviille Kuyt, Can you please answer my question. I'm very upset on this.https://stackoverflow.com/questions/50998636/single-responsibility-principle-in-clean-architecture-aggregating-usecases-in-o – Dipendra Sharma Jun 23 '18 at 07:48
0

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.

Alper
  • 3,424
  • 4
  • 39
  • 45
0

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.

Anand
  • 864
  • 10
  • 31