2

DDD/"hexagonal architecture" insist on separating the domain, aka model, from infrastructure requirements. This looks clean and logical until you realize that storing your domain object in memory might hurt performance if the domain object happens to be too large, and even more so fetching such domain object from persistent storage/network.

The proposed "cure" which I have seen, is centered around defining the aggregates to be "small" and around "eventual consistency". Both seem to delegate the business rules to stateless ("domain") services and not the aggregates (domain entities) behaviour. So this appears to favour the creation of "anemic domain objects"; however "rich domain objects" seems to me the main purpose of DDD (together with the creation of the ubiquitous domain language).

What you, as a DDD practitioner, think of this concern? (I am not currently a DDD practitioner, but given the hype around "microservices", I might perhaps become one).

  • 2
    Part of the confusion might stem from a misunderstanding: in this context "model" does not primarily mean "data model" but "model of the problem domain", in particular "business logic". The model does not usually load a complete database into memory. – amon Jan 25 at 14:58
3

The proposed "cure" which I have seen, is centered around defining the aggregates to be "small" and around "eventual consistency". Both seem to delegate the business rules to stateless ("domain") services and not the aggregates (domain entities) behaviour.

Something got lost in the messaging here.

Many applications today separate storage from compute. The compute elements may be completely stateless (with regards to the model), or they may have in memory caches that they use to improve latency.

The domain model is a way of isolating, in compute, the business logic from everything else.

The basic outline is

  1. read state from the durable store
  2. create a domain model representation of that state
  3. apply changes to the domain model
  4. create a representation of the new state from the model
  5. write state to the durable store

This flow of control would normally live, not in a domain service (which has a different meaning in domain driven design), but in an application service.

What I find interesting is, if you look at the process as a whole:

  1. read state from the durable store
  2. ???
  3. write state to the durable store

The basic shape is that of an anemic domain model -- we pull data out of the database, fuss with it in some stateless "service", then put the data back in. At the boundaries, applications are not object oriented.

2

DDD/"hexagonal architecture" ...

DDD doesn't enforce any specific architecture, you are free to choose whatever works for your application. The confusion comes from the book itself, where the examples used the Layered architecture.

An Aggregate is defined as the (strong) consistency boundary.

The Aggregates should be as small as possible without compromising the consistency requirements which are driven by the business needs. If the business doesn't need strong consistency for some invariant why would you assume so?

A bigger Aggregate is slower which is bad for the business. This means that we need to ensure that the business really needs strong consistency and if it doesn't need it then we can move it to a Saga/Process manager which can also protect an invariant but in an eventual consistency manner by sending commands to the right Aggregate.

Some times the business rules force us to have a big Aggregate. That is, the entire Aggregate should be loaded-from/saved-to the Repository as a single atomic unit. On the other hand, the system should be also fast. So what do we do? We use the technology as a solution. An example is the Set validation where a simple solution is to use a database unique index to protect a cross-aggregate invariant. This is in general wrong because the technology changes a lot faster than the business. DDD teaches us to use our code as a solution because the code is more resistant to change because of trends but sometimes it's impossible.

As a conclusion, DDD guides us in right direction but we are the ones that need to make the decisions for each particular situation. There is no perfect model, all are wrong but some are useful; you just need to make the right compromise.

0

I broadly agree with your summary of DDD in practice. However, I think the change from classic OOP style logic + data objects to ADM comes not from DDD but is caused by the size of the system.

If your system can be contained in a single in memory desktop application then the OOP approach is an ideal way to express your business rules. You need to keep the objects in memory anyway and you are performing many operations on the same in memory instance.

If your system is distributed into several disparate parts then the OOP approach falls apart. Either you have to have multiple OOP style systems with different versions of the same conceptual object. Or you reduce your conceptual object to just its data and pass it around the various parts of your system.

If you are working with a microservice style architecture with message queues and the like you will have lots of small systems and the overall design lends itself to the second ADM approach. But you can apply DDD to both styles of programming.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.