What is the recommended way of exposing types from internal package structure? #495
Replies: 2 comments 1 reply
-
I usually recommend following the “interfaces belong to clients” approach when it comes to the interaction with internal components:
This makes the internal package a sole implementation package that can refer to types in the API package and reuse them. The alternative would be to let the internal package declare an interface for the DTO to implement. Unfortunately, that would leak that internal interface out to client modules, and it's easy to create a reference to that internal interface from there. This problem could then easily be resolved by switching to referring to the full DTO type, but it feels weird having to do so. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the answer and the interesting read. That would solve the circular dependency. In the linked answer is stated:
What would make a client defining the interface change this pattern? I can see that if there are multiple client defined interfaces that are, from the implementer's view, highly related, they can all be implemented by a single class. But since we want want a class to be responsible for 1 thing, doesn't this tend towards this single implementer for an interface situation? I see most services in common codebases don't need multiple implementations. |
Beta Was this translation helpful? Give feedback.
-
Hello everyone,
When I make a service available for other modules, that public service often calls something internal for that module and returns some object that is of a public type.
In a simple module, this could be 3 classes in the root package of the module:
DTO [public]
Repository [package private, returns DTO]
Service [public, calls repo and returns DTO]
In an advanced module, when 'something internal' is not just a Repository, but something that lives in an internal package, I cannot do the same. It would introduce a circular dependency root package -> internal package -> root package.
The way I currently handle it
DTO [in package 'exposed' that has @NamedInterface("exposed")]
InternalService [in package 'internal', returns DTO]
Service [public in root package, calls internalService and returns DTO]
I wonder if this is the recommended way of doing it, or someone might have a better idea.
Beta Was this translation helpful? Give feedback.
All reactions