vkhorikov / DddInAction

Source code for the DDD in Practice Pluralsight course
https://www.pluralsight.com/courses/domain-driven-design-in-practice
587 stars 155 forks source link

Repository is not repository #7

Open Zefek opened 2 years ago

Zefek commented 2 years ago

Hello,

I saw your code but I think repository is not a repository because you implement it as generic type. So it means each derived type will have Get/Save methods. When Save method is divided into Insert and Update and Remove method will be added there is class which implements CRUD operation above table. When you have class for CRUD operation it is more Table Gateway pattern than Repository pattern. There is some differences between TableGtw and Repository pattern. Important thing in DDD (domain model more exactly) is that domain model works with entities aggregates. It means I have entity Invoice and it have many Items. Domain model works with root entity which is Invoice. Important is that nobody can change Invoice Item directly but Item are encapsulated inside Invoice entity and each change can be done by Invoice entity only - not from outside Invoice entity. It means Invoice entity should be loaded with Items together. So Repository pattern can provide access to whole aggregate for Invoice entity. Instead of TableGtw pattern provides access to one table in database which means one entity - Invoice is loaded by InvoiceTableGtw and Items are loaded by InvoiceItemTableGtw. Exception could be value object which can be stored in same table as entity. Repository pattern can provide some logic to check if entity is consistent and valid. It means it can check if price on Invoice entity is equal sum of price on items. Repository is created only for root entities, not for entities inside aggregate. Repository is not responsible for saving data to data store, it has not Save method.

I think it is very important to think in aggregates and each entity/value object is encapsulate inside aggregate and can be accessed and changed only by root entity - not directly outside of aggregate. It is difference to Table Module business pattern or Transaction Script.

There is difference between domain model and domain driven design (DDD) which is confused often. DDD is whole methodology how to distil bounded contexts, how to establish communication between contexts and other systems, what is core/support/generic domain, ... Domain model is more implementation technique which can take more complex business by model. Model can by created by Model Driven Design methodology but when we use DDD we create model for each context instead of whole system in case of Model Drive Design. I saw some projects where people said we use DDD because we have entities, repositories and we have many apis. Ok and what are your bounded context? No, we don't have bounded context we have more apis and it is DDD. You don't have value objects. Each object has identity - primary key in database. Ok, but it is not business identity. Your entity has not any behavior it is POCO object - it is not domain model, it can be anemic domain model or another business pattern but not rich domain model. Each entity is 1:1 with database table and it is loaded by generic repository. Generic repository is TableGtw pattern. You don't have any domain service. We have services. Ok, but it is in application layer and these services hold use cases but domain service hold business case.

In DDD can be used any business pattern (domain model, transaction script or table module). DDD doesn't say which pattern or technology should be used. Each context can be implemented by different approach. DDD doesn't say nothing about code.

vkhorikov commented 2 years ago

The repository class has a where statement which allows introduction of repositories for aggregate roots only: https://github.com/vkhorikov/DddInAction/blob/master/DddInPractice.Logic/Common/Repository.cs#L7