Hello, In a clean architecture(image taken from <...
# android-architecture
a
Hello, In a clean architecture(image taken from here), we have multiple features (e.g.,
:feature:home
and
:feature:reviews
) that need a use case combining data from two domain modules (
:domain:books
and
:domain:reviews
). For example,
Feature A
and
Feature B
both require data that comes from a composition of
BooksUseCase
(from
:domain:books
) and
ReviewsUseCase
(from
:domain:reviews
). A few approaches come to mind: 1. Create a new module (e.g.,
:domain:books-reviews
)
to house the combined use case logic. However, this introduces horizontal dependency, as the new domain module depends on both
:domain:books
and
:domain:reviews
, potentially violating clean architecture principles of vertical dependency. 2. Place the combined logic in a common domain module (
:domain:common
). But in a large app, this could lead to bloating and tightly coupling unrelated shared logic in a single module. 3. Move the composition logic to the feature layers and directly invoke the relevant use cases from the domain modules. However, this risks duplicating logic across multiple features if the combination logic is reused. What is the best way to handle this scenario while maintaining modularity, scalability, and adherence to clean architecture principles? Is it acceptable to have a cross-domain dependency in such cases, or should the logic live elsewhere (e.g., feature layer or backend)? Any recommendations or best practices for managing such cross-domain use cases in large apps?
a
You need to follow the api/impl way of structuring your modules for this.
j
Even if follow api/impl can still get issue like api models in A depend on api models in B and C depend on B. Where need put shared api models somewhere. To be honest I think its easy over modularize things at a point no where to go. I guess can duplicate api models to incapsulate. Can have circular api modules in all layers. I think core thing here is keep a balance.
1
a
Agree with Joel here, for now, I am thinking for now to go with option 3 of keeping a bit of duplication for that combined use case and wait if my code will start to speak about a domain which would be based on the common use case.
a
I follow api/impl in codebase with 30+ features and it works like a charm, you just have to smart and keep the api modules as lean as possible (make them a pure JVM module if possible), It is your DIs job to bind the actual implementation, If you ever have a case where 2 features are using each other a lot then maybe they need to be a single feature ?
j
Yeah this becomes more important when have hundreds of modules or thousands. Yes its common 😁 the api vs implementation thing works well in small scale with few feature dependencies in hexagonal architecture.
a
How do you folks handle feature to feature navigation? Does the navigation goes into the domain layer as well?
j
For navigation its entirely decoupled from feature modules I realized work best. Ideally create entire nav graph at app level only. In some apps can work having core navigation module with all possible routes that each feature module can consume from. This avoids circular dependecies and other annoying things.
a
I see, so since app would have dependency for all features, so that way we won't need to have feature to feature dependency for navigation. that makes sense.
a
I create a different module for navigation named "contract" for each feature and define the destination classes there. When a feature needs to navigate the other feature it just need to add that module as a dependency.