Muthu
Muthu

Reputation: 2685

Data Access Layer and DDD

I am trying to learn the idea of Domain Driven Design and trying to figure out where should we put the Database persistence code.

Going through the book "Implementing Domain Driven Design by Vaughn Vernon", I understand that the Repository or the Database operations (along with connections etc.,) have to be kept in the Model project (Domain Model Context) itself. Is my understanding correct?

I am referring to his sample of IdentityAccessContext, AgilePMContext etc., where there are interfaces to the repository. I had always grown with an idea of having a separate Data Layer and adding one here leads me to circular dependency. Because the Interfaces, Entities are declared in Model which is required for the Data layer and the Data layer needs to be referred from model for persistence.

Is this correct or am I missing something?

Upvotes: 2

Views: 4547

Answers (2)

guillaume31
guillaume31

Reputation: 14064

Going through the book "Implementing Domain Driven Design by Vaughn Vernon", I understand that the Repository or the Database operations (along with connections etc.,) have to be kept in the Model project (Domain Model Context) itself. Is my understanding correct?

Repository abstractions (interfaces) should be in the Domain layer, but their concrete implementations are in an Infrastructure layer.

See his code samples for the book : https://github.com/VaughnVernon/IDDD_Samples/tree/master/iddd_agilepm/src/main/java/com/saasovation/agilepm, for instance TeamRepository interface in domain/model and LevelDBTeamMemberRepository in port/adapter/persistence.

There's no circular reference because persistence is strongly coupled to Domain but Domain is only loosely coupled to persistence if it ever needs it (thanks to Inversion of Control, most of the time achieved by Dependency Injection).

Upvotes: 4

Matías Fidemraizer
Matías Fidemraizer

Reputation: 64933

I wouldn't say there's a data access layer per se.

Actually, repositories translate domain into data and viceversa using a data mapper.

Models, services or transaction scripts must use repositories to both get and persist objects. There's no circular reference here:

  • Service layer injects repository/repositories to implement domain operations. That is, a service will know what to do if it requires objects and it's not focused on how they're translated into data.
  • Repositories use a data mapper to persist and get data (1).
  • Data mapper usually is an OR/M like Entity Framework, NHibernate, Dapper...

Furthermore, a good DDD will enforce inversion of control and this will mean that:

  • Upper layers know about lower layers.
  • Lower layers don't own any reference to upper layers.

In summary, DDD doesn't have a DAL like you think, but it tries to abstract and encapsulate each concern in order to let upper layers be decoupled from the underlying data approach.

About the circular reference thing...

OP said:

Because the Interfaces, Entities are declared in Model which is required for the Data layer and the Data layer needs to be referred from model for persistence.

Double check your statement. If models represent higher layer of abstraction than data, why data should reference models?

It would be the model who requires the data. And the data should be accessed using interfaces to let the models be agnostic about the data access strategy. This is called inversion of control, as I said previously on this answer.

Maybe you think that data layer requires a reference to entities, because you're still thinking the old way, but if you practice a good separation of concerns and you work with a data mapper (or you implement it yourself), the data mapper just maps objects to raw data and viceversa, and it doesn't require a reference to concrete classes like domain objects (you should ask yourself how Entity Framework can persist your entities to your favourite database engine without even knowing about these entities (2)).

Anyway, as I said before on this answer too, you shouldn't think about a DAL but a bunch of repositories and a data mapper, or just repositories (see exception (1)).

Usually dependent lower layers are instantiated and given to upper layers using dependency injection pattern (a possible implementation of inversion of control).


(1) Exception to this rule: if we're no talking about a relational storage, maybe there's no data mapper at all, and repository implements its interface by accessing the data with lower level of abstraction/encapsulation. For example, if the repository implements its operations to store data in XML, then it would use an XDocument or XmlDocument internally and there's no actual data mapper at all.

(2) Actually OR/M frameworks like Entity Framework can know how's your model by configuration. While it doesn't require a reference to your concrete domain to compile, it requires you to provide class maps using Code First or other approaches)

Upvotes: 4

Related Questions