3

Consider:

The Use Case layer defines an interface

public interface IGeocoder
{
    Coordinate GetCoordinate(Address address);
}

Coordinate and Address are value objects defined in the domain layer (i.e. entities layer in Uncle Bob jargon). Obviously the use case (interactor) constructs the Address and passes it to the IGeocoder, expecting a Coordinate to be returned.

Would this break any Clean Architecture rules? Should I be instead passing DTOs through the interface, so that the actual implementation of the service is not responsible for generating the domain entities? Or is this fine?

Note that I don't see any difference between this and a repository (entity gateway), whose interface would also be defined in the Use Case layer but implemented in the surrounding Interface Adapters layer:

public interface IRestaurantRepository
{
   // ...
}
Jordan Walker
  • 550
  • 1
  • 5
  • 17

2 Answers2

2

Who is owning the implementation of the infrastructure service? Is it the same team? Then it should be fine to handle it similar to repositories; return domain entities directly. Is it owned by different team? Then creating a boundary and passing dedicated DTOs might be beneficial as it creates less coupling.

plainionist
  • 2,950
  • 1
  • 15
  • 27
  • I like this answer as it's about coupling rather than layers. Repositories are coupled to domain entities because that's their responsibility (in my view). The idea of a geocoding service probably shouldn't be coupled to domain objects, since it would be harder to re-use elsewhere. In this case it's just a personal side project so it's probably fine for it to return domain entities, but it does make it less re-usable in other contexts. – Jordan Walker Aug 14 '20 at 15:23
1

This all depends on what your "entity" is, and what the "DTO" is. If the "entity" and the "DTO" are basically the same, then you aren't violating anything by passing in the entity.

However, if your entity had a function like address.getISOAddress() and your getCoordinates function was expected to call that function, to get the correct address/coordinates, then that would violate the architecture, and instead you should pass in a ISOAddress into your getCoordinates usecase.

The important thing to remember is that you are dealing with interfaces, and contracts or abstractions. If that interface is dealing with an abstract class, a concrete implementation of an exact instance should not and does not matter. What matters is that you have a clear interface at the right level of abstraction, and that your system is flexible so that the implementation details can change and your system still works without major modifications.

Bob
  • 1,605
  • 2
  • 18
  • 33
  • What about repositories? They are also interface adapters, and they directly handle domain entities. – Jordan Walker Aug 13 '20 at 15:25
  • 1
    Repositories only directly handle the domain entities when they are dumb, otherwise they handle entity models. – Bob Aug 14 '20 at 12:20
  • That’s not how I usually see them implemented. Usually they are couple directly to the entities. Imagine you have an app where some repositories couple to domain entities and some don’t... that would get confusing no? There’s no consistency. – Jordan Walker Aug 14 '20 at 17:35
  • Even if you have the same fields, the domain layer should not know the infrastructure (with DTOs) layer. – slim Aug 16 '20 at 09:08
  • @jordan-walker answer updated. The interface is the consistency, not the implementation details. – Bob Aug 17 '20 at 10:30