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.