0

I'm struggling to understand how to refactor my site to cleaner code by letting my Domain Entities have their behavior.

I hope i have managed to describe my problem in this diagram:

enter image description here

A is my current design of Web application project while B is my target design.

I'm trying to insert all logic from my current BL to my Entities so that a code line like:

var customer = new CustomerLogic().GetCustomer(id);

Would become:

var customer = new Customer(id);

Or,

var customer = Customer.Get(id);

It's even more obvious when i see a polymorphic situation.

The problem is that while in my current design (A) Entities are just being used so all projects have a reference to it, with the future design (B) Entities will have to have a reference to a lower layer.

But Since i also want my DAL to deliver my Entities back to the calling client i get to have a circular reference.

My current design makes my code more procedural than Object Oriented and i want to change that.

So, how can i solve this circular reference while maintaining a DDD?

YanivHer
  • 71
  • 12

1 Answers1

0

You resolve the circular dependency by inverting the dependency from Entities (which in DDD are Aggregates, where each Aggregate contains one Aggregate root and zero or more nested Entities). In other words, the Domain layer should not have any dependency to other layers, like Persistence, Application or Presentation.

A complete use case would be like this:

customerId = request.get('customer_id')
customer  = repository.load(customerId)
customer.doSomethingImportant() //business logic that doesn't need anything from other layers
repository.save(customer)

If somehow, your Aggregate needs some information from outside to do its job, then you pass that info as an argument, like this: customer.doSomethingImportant(some, info, fromOutside).

The important aspect that you should note here is that the Aggregate's methods do not mutate anything else except its own state. For example, it does not send emails, it does not write to files, not even to the Database. That mutated state is then taken by the Repository and persisted in the Database. In this way you invert the dependency to the DAL/Database.

In Event sourcing, this mutated state takes the form of Domain Events. In flat/classic architectures, the Repository (often an ORM) computes the diff and perform changes to the Database.

Constantin Galbenu
  • 14,628
  • 3
  • 23
  • 41
  • Can you clarify in which Layer should your use-case be? I'm guessing that there needs to be some Layer which by your use-case have a reference to the Repository layer and the Entities. So it looks like a Businss Logic layer. Am i correct? Would you call that layer something else? Thanks! – YanivHer Apr 27 '18 at 19:10
  • @YanivHer my use case traverses Presentation (it knows about `request`) and Application. The business layer would contain the body of the `doSomethingImportant` method (you can't it see here). – Constantin Galbenu Apr 27 '18 at 19:40
  • From my reading of the DDD book, the Domain layer depends on the Infrastructure layer (with UI and Application layers above it, which also depend on the Infrastructure layer). Also, every Repository belongs within the Domain layer. Dependency inversion is something you can do with any architecture, but there is no need for it in DDD layered architecture. – Rogério Jul 16 '19 at 22:00
  • @Rogério That book is excellent but not because of the Layered architecture; that architecture is just an example (a bad one in my opinion), an implementation detail and one should not think that Layered architecture === DDD. As a side not: I never used it. – Constantin Galbenu Jul 17 '19 at 06:22
  • In DDD, software components in the Domain Model (for example, a Domain Service, or a Repository) do depend (ie, have a compile-time dependency) on software components from the "Infrastructure" (which is another part of the application codebase, whether you call it a "layer" or not). This is very common in real-world projects (for example, a Domain Service class might use an Email sending class, or a database access class, or a Date utility class, all of which are infrastructure components). – Rogério Jul 17 '19 at 17:26
  • @Rogério yes, but "software components in the Domain Model" !== "Domain layer, where you find only Aggregates, Value Objects, Nested entities" – Constantin Galbenu Jul 17 '19 at 17:44
  • @ConstantinGalbenu When we have a "Domain layer" in a DDD codebase, then it obviously contains the whole Domain Model. Therefore, Domain Services, Factories, and Repositories all go inside the Domain layer. It makes no sense to put part of the Domain Model outside the Domain layer. – Rogério Jul 17 '19 at 19:51