1

I want the adpaters to pass a common interface to the cart service. I've read that interfaces should be in the Domain layer and DTOs to be defined in the Services layer, which seems to conflict with me. You don't want the Domain layer to have a reference to the Service layer where the DTO is defined.

What am I missing? Or is it ok to have the interface live with the DTO in the service layer, like I have in the diagram?

enter image description here

crichavin
  • 4,672
  • 10
  • 50
  • 95
  • If DTO used in multiple layers, as usually is. Then introduce one project which contains all DTO types and make all other projects/layers to reference it. – Fabio Feb 09 '19 at 00:41
  • 1
    Interfaces can be everywhere the question is only their purpose. If an interface has a DTO as part of its contract it should be declared in the same layer with the DTO, but still domain layer may have its own interfaces to abstract away from implemenrations, unit testing, etc. – Dmytro Mukalov Feb 09 '19 at 07:14
  • Thank you @DmytroMukalov. If you want to make this an answer, I will accept it. – crichavin Feb 09 '19 at 14:07

1 Answers1

1

So if you use layered architecture pattern (I presume you do), one fundamental property of this pattern should be taken into consideration. This property implies specific order of "use" dependencies between the modules (classes) in different layers, in particular modules from a layer should "use" (be dependent) on modules or abstractions from the next underlying layer or layers. I mentioned layers because there can be some relaxed constraints which allow to use not only classes from the nearest underlying layer but all layers which are below the given one. As for for the upward dependencies the constraints are very strict and explicit - it's not allowed otherwise it's not a layered architecture but something else since it eliminates the quality attributes the layered architecture is supposed to bring. As a logical consequence - using DTO from the service layer inside the domain layer implies upward dependencies which violates layered architecture constraints.

As for interfaces, another fundamental property of layered architecture is that the layers should be isolated from each other by means of abstractions. The abstractions here may imply some public contracts (API, interfaces, etc.) which define higher layers intentions and lower layers expectations but nothing more which makes layered architecture so attractive from the modifiability and portability perspective. That's why we are talking about interfaces in all layers which are just an abstraction mechanism.

Now as a conclusion: if your DTOs are in the service layer they should be part of the contracts of the same layer (or layers above in some cases) but not below in order to exclude upward dependencies between the layers. The interfaces are still valid (and even desirable) for the domain layer as well as for any other layer for the abstraction purposes.

Dmytro Mukalov
  • 1,949
  • 1
  • 9
  • 14
  • If the service layer returns entities i guess we have another problem regarding transactions. If the entity returned by the serivce has some lazy collection ,we should open the transaction in the Controller to acces the data right? Is ok to open the transaction from the controller? – Al Xx Jun 14 '22 at 13:07
  • @AlXx If a service layer works with DTOs how come you've got to the point that it returns entities? – Dmytro Mukalov Jun 15 '22 at 10:35
  • Of course. I am talking about discussions where some people argue that services should return DTO and others argue services should return entities. About the second option ,how do you handle transactions ? Is ok to have transactions in the controller layer? – Al Xx Jun 16 '22 at 12:50
  • @AlXx, Handling transactions in controllers can be ok if you have no other layers, so the answer is it depends. From the other hand I'm not sure that I fully understand how returned entities affect transactions. A transaction is supposed to accompany a data mutation while at the moment when a data gets returned, trcansaction should be completed if it took a place, so I definitely fail to find a relationship between returned type of data and transactions. – Dmytro Mukalov Jun 17 '22 at 15:53
  • Usually , when you work with ORM you have entities related to another entities. In some cases ,you have EntityA having a collection of Entitie B ( Person-> Addresses) .Usually the Adddress collection is in "Lazy Mode" , it will fetch the data in case you do something like "personEntity.getAddresses()" . If you return the entity and you have the transaction in the service layer you have a problem. If you want to create a DTO from that entity in the Controller layer (Using some kind of mapper) ,you cant. The transaction is ended .You will have an Error in case you do "personEntity.getAddresses() – Al Xx Jun 18 '22 at 15:28
  • @AlXx what type of a transaction are you talking about when an entity is getting returned? There shouldn't be any active transaction at the moment when mutations are done associated with the flow which returns entity otherwise such a design is a crap. – Dmytro Mukalov Jun 18 '22 at 18:31
  • I am agree with you . But if you look ,there are a lot of post talking about if a Service should return a DTO or an Entity . But i think they dont realize about this "transaction" thing. By the way ,theorically speaking , which would be the cons fo openning the transaction in the controler? – Al Xx Jun 20 '22 at 21:03
  • @AlXx again, just to reiterate, what type of information a service returns (entity or DTO) has nothing to do with transactions because a transaction boundaries are supposed to enclose only data modifications while returning an information has no transaction semantic. – Dmytro Mukalov Jun 21 '22 at 13:32