Search code examples
androidkotlinentityandroid-roomclean-architecture

Is Room Entity and Clean architecture Domain layer's Entity is different?


My question is as the title states.

Room has the annotation @Entity, and within Room, this is considered an Entity.
But in Clean architecture, when using a Domain layer, an Entity is also used.
For example, entities used by Use Cases within the domain layer.
However, I think that what Room considers an Entity is a DTO or POJO as of Clean architecture.

With that being said, when creating an app, what should I name my model in the presentation layer, domain layer, and in the data layer?


Solution

  • Domain Layer:
    Domain layer is the centre point of the clean architecture which doesn't only contains data models but also usecases and domain layer is something that should be language specifics, which means there should be no third party involve you've to keep it to language. The domain layer is something that you are going to manage throughout the whole app even in unit tests(most of the time).

    Framework Layer:
    When you say Entity or DTO which we use with Room or Retrofit and these frameworks that we use with third party libs., these should belong to framework layer of the architecture. That means these entities and dtos are not directly targeting the usecases or domain models but how can we use them or connect them with domain model? this is where mappers comes into play you've to use mapper mechanism to map the data from one layer to another and not to violate CA rules.

    Example:
    Entity:

    @Entity(tableName = "user_auth")
    data class UserAuthEntity(
        @PrimaryKey(autoGenerate = false)
        @ColumnInfo(name = "pk")
        val uid: String,
    
        @ColumnInfo(name = "user_name")
        val username: String,
    
        @ColumnInfo(name = "email")
        val email: String,
    
        @ColumnInfo(name = "password")
        val password: String,
    )
    

    Domain Model:

    data class UserAuth(
        val uid: String,
        val username: String,
        val email: String,
        val password: String,
    )
    

    we are going to use kotlin extension functions to map them:

    fun UserAuth.fromDomain(): UserAuthEntity{
        return UserAuthEntity(
            uid, username, email, password
        )
    }
    
    fun UserAuthEntity.toDomain(): UserAuth{
        return UserAuth(uid, username, email, password)
    }
    
    

    How to use it:

    
    suspend fun getUser(): UserAuth {
        // this userAuth is from dao which Entity
        val userAuth = dao.getUserEntity()
        
         // map them userAuth domain through mapper extension functions
        return userAuth.toDomain()
    }
    
    

    fromDomain means we getting data from domain and mapping to Entity and toDomain we are getting data from entity and mapping to domain.
    As a side note, as it is mentioned above we are going to use mapper to map data between the layers. Since clean architecture based on layer that doesn't mean we always going to use mappers everywhere to separate the layers and communication between the layers, since this question was about data models we normally use mapper to map the data which is in it by not breaking the layers.
    Please search about DIP(dependency inversion principle), how we can communicate between different layers through interfaces.