0

I want to create an app following the DDD approach using Spring. Supose that I have a business model class Foo and an interface FooRepository.

DDD tells that the implementation of FooRepository should include in Infrastructure layer.

I would want to use CrudRepository but if I define in the domain layer:

public interface FooRepository extends CrudRepository<Foo, Long>{
    // Some methods
}

I break with the core concept that the domain layer (FooRepository interface) must not know the infrastructure layer (CrudRepository).

I'm reading about this Domain Driven Design a few months ago but I haven't found a framework that supports it purely.

How I can do it the right way?

Jaumzera
  • 2,305
  • 1
  • 30
  • 44
Cristhian Boujon
  • 4,060
  • 13
  • 51
  • 90
  • Sooner or later you'll couple things. Wrap `crudRepository` in your own repository, so if you want change it you will do this in a shot! – BAD_SEED Jul 07 '15 at 14:21
  • Please take a look at: https://github.com/BottegaIT/ddd-leaven-v2 and https://code.google.com/archive/p/ddd-cqrs-base-project/ or just do microservices with JHipster: http://jhipster.github.io/microservices-architecture/ – kinjelom May 02 '16 at 12:53

1 Answers1

1

In the layered architecture you usually have 3 layers: application, domain and infrastructure.

Infrastructure

Here I put the implementation of the repository. In your case this is the implementation of CrudRepository which I would implement directly in concrete classes, without the use of an intermediate interface. We make no whatsoever assumption as to how the single object in the warehouse behave, we only put them there and retrieve them efficiently. This way we have no knowledge of the domain. We only offer the domain an interface to interact with: the set of public methods of WarehouseRepository.

public class WarehouseRepository implements CrudRepository<Foo, Long> {
    ...
}

Domain

Here various part of the model interact with the WarehouseRepository when you are inside a UnitOfWork/Transaction. In the method adjustQuantityPlus we se only domain logic which is not interesting to the application and need not to be known at infrastructure level.

public class SaleOrder {
    public adjustQuantityPlus(LineItemID lineItemID,
                              WarehouseRepository warehouseRepository) {
        this.lineItems.get(lineItemID).addOne(); //<-- add one to the order
        Product product = 
            warehouseRepository.findByLineItem(lineItem);
        product.minusOneFromStock(); //<-- decrease one from stock
    }
}

Application

Here we start and stop transactions (UOWork) which manipulates many domain objects. Every business method correspond to a business use case.

public class CustomerEventsManager {
    @Inject WarehouseRepository warehouseRepository;
    @Inject SaleOrderRepository saleOrderRepository;
    @Transactional
    public wantsOneMoreOf(ProductID productID, SaleOrderID saleOrderID) {
        SaleOrder saleOrder = 
            saleOrderRepository.findByID(saleOrderID)
        saleOrder.adjustQuantityPlus(productToLineItem(productID),
                                     warehouseRepository); //<-- add product
        webPage.showPromoDiscount(); //<-- show promotional advertisement
    }
}

The above code is a transaction, if the system couldn’t add the product to the order I don’t want to give the discount to the customer. The adjustQuantityPlus in turn is an inner “transaction” with domain logic, hidden to the application layer.

gurghet
  • 7,591
  • 4
  • 36
  • 63
  • You have a circular dependency between layers. In your example the infrastructure layer knows the domain layer (Because you use `Foo`) and domain layer knows the infrastructure layer (Because `BarDomainObject` use `FooRepository`) so That is not good approach. In order to avoid circular dependencies you need to define an interface repository in domain layer so if you need use a repository in it you have to use the interface with some implementation in infrastructure layer. – Cristhian Boujon Jul 14 '15 at 17:08
  • Not exactly, the infrastructure layer knows how the entities are structured, the domain layer knows how entities work, the application layer knows how entities interact. The domain layer *has* to know about the infrastructure layer in this architecture. – gurghet Jul 14 '15 at 17:20
  • [Here](http://dddsample.sourceforge.net/architecture.html) is a summary of the concepts. See the picture – Cristhian Boujon Jul 14 '15 at 17:42
  • Yep, it works even in your diagram. Anyways if you are interested in talking about it we can open a chatroom. i'll try to elaborate my answer anyways. – gurghet Jul 14 '15 at 21:15
  • I'm newbie in DDD but I have an advanced OO knowledge and software development. Maybe I'm wrong but I dont understand why you use a repository inside `SaleOrder` entity. If inside `saleOrder.adjustQuantityPlus()` you need get a product from a lineItem so it should know which product contains doing `lineItem.getProduct()` or maybe delegate `adjustQuantityPlus()` to a `SaleOrderService`. Entities should contains the business rules, attributes and relationships with another entities, no repositories. If you need call a repository from domain layer, you should doing in a domain service class – Cristhian Boujon Jul 15 '15 at 00:12
  • Because it's easier to test. If you read the last part of your page it talks about it. With my code you can do something like `adjustQuantityPlus(lineItem1, fakeWarehouseRepository)` – gurghet Jul 15 '15 at 05:20
  • You can do exactly the same if you have a `SaleOrderService` so what is the difference? the difference is that entities keeps pure business issues without knowledge about infrastructure. Domain services acts as coordinator between different repositories. Maybe you already knows but I'm read [this](http://www.infoq.com/resource/minibooks/domain-driven-design-quickly/en/pdf/DomainDrivenDesignQuicklyOnline.pdf) interesting article about DDD that it helped me to understand all concepts and responsability of the layers and classes. – Cristhian Boujon Jul 15 '15 at 12:18
  • Also, you can see the same discussion [here](http://stackoverflow.com/questions/827670/is-it-ok-for-entities-to-access-repositories) and [here](http://stackoverflow.com/questions/5694241/ddd-the-rule-that-entities-cant-access-repositories-directly) – Cristhian Boujon Jul 15 '15 at 12:18
  • You can do exactly the same if you have a `SaleOrderService` so what is the difference? the difference is that entities keeps pure business issues without knowledge about infrastructure. Domain services – Cristhian Boujon Jul 15 '15 at 22:54