Search code examples
architecturedomain-driven-designn-layer

Converting from N-Layer to DDD


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?


Solution

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