Android clean architecture and related entities

Viewed 847

This is mostly a design question. I have 2 entities Payment and User, having a one-to-one relationship. The API call returns a list of Payments each Payment contains a User. The payments are displayed in a Recycler View, every row contains information from both the Payment and User entities. And to fetch them from the DB (using Room) I need to perform a join query that returns a combination of both entities:

@Query("SELECT payment.*, user.* FROM payment INNER JOIN user ON payment.user_id = user.userId")
fun findPaymentsAndUsers(): List<PaymentAndUser>

data class PaymentAndUser(
    @Embedded val payment: Payment,
    @Embedded val user: User)

My question is how can I create my repositories without breaking any of the Clean Architecture principles?

  • Of course I cannot create 2 independent repositories and pass the data between them through the calling UseCase because they are already being returned together either in the API call or in the Room DAO query.
  • The single responsibility principle states that every repository should only handle its own entity, so I cannot create a PaymentRepository and handle everything from there.
  • I also cannot group both entities into an Aggregate and create a repository than handles them both, because they are two independent Entities that can exist regardless of each other.

Every single Android Clean Architecture sample I found has one or two entities that are totally independent with no join queries or any sort of grouping, which is totally unrealistic in real life applications.

Is there any way this can be implemented correctly?

1 Answers

As to my understanding SRP does NOT say that each repository should only handle its own entity - instead each repository should only have "a single reason to be changed".

The pattern that should solve your problem is the "unit of work" pattern: just create a "unit of work" repository which exactly handles this query.

In fact in his book "clean architecture" uncle blob states that repository interfaces should be designed in a way being convenient to its user. It should have one method "per query" the use case would raise against the repository.

Related