Using offline first or the one you can see in official document and clean architecture with mapping DTO(data transfer object used for getting REST data) to Entity database model?
One design i saw in Buffer app in github is something like, simplified it a little bit,
interface PostDataSource {
suspend fun getPostEntities(): List<PostEntity>
}
interface LocalPostDataSource : PostDataSource {
suspend fun savePosts(posts: List<PostEntity>)
suspend fun deletePosts()
}
interface RemotePostDataSource : PostDataSource
the thing is both Remote and Local data source return database entities where mapping logic take place inside remote data source implementation.
class RemotePostDataSourceImpl(
private val postApi: PostApi,
private val mapper: DTOtoEntityMapper
) : RemotePostDataSource {
override suspend fun getPostEntities(): List<PostEntity> {
return mapper.map(postApi.getPosts())
}
}
And in other one i generally see is
interface PostDataSource
interface LocalPostDataSource : PostDataSource {
suspend fun getPostEntities(): List<PostEntity>
suspend fun savePosts(posts: List<PostEntity>)
suspend fun deletePosts()
}
interface RemotePostDataSource : PostDataSource {
suspend fun getPostDTOs(): List<PostDTO>
}
remote data source
class RemotePostDataSourceImpl(
private val postApi: PostApi
) : RemotePostDataSource {
override suspend fun getPostDTOs(): List<PostDTO> {
return postApi.getPosts()
}
}
And mapping logic is inside repository
class PostRepositoryImpl(
private val localPostDataSource: LocalPostDataSource,
private val remotePostDataSource: RemotePostDataSource,
private val mapper: DTOtoEntityMapper
) : PostRepository {
override suspend fun getPostsOfflineFirstFlow(): Flow<List<PostEntity>> =
flow {
emit(localPostDataSource.getPostEntities())
}
.flatMapConcat { postEntities ->
if (postEntities.isNullOrEmpty()) {
mapper.map(remotePostDataSource.getPostDTOs())?.apply {
localPostDataSource.deletePosts()
localPostDataSource.savePosts(this)
}
flowOf(localPostDataSource.getPostEntities())
} else {
flowOf(postEntities)
}
}.catch { emit(listOf()) }
}
Don't mind the rest of the code other than mapping for this question, it's invoked in repository.
And my second question is, isn't putting business logic inside repository or remote data source instead of usecase/interactor(class with purpose of implementing business logic) for offline-first considered anti-pattern?
Aucun commentaire:
Enregistrer un commentaire