Let's say we have an app that is going to apply clean architecture principles. we have repositories, data sources(local & remote), multiple value objects for each layer and mapper classes for mapping those objects.
There is also a wrapper class called Resource (similar to what is discussed in this post).
for example:
interface PriceRepository {
suspend fun getPrices(): Resource<PriceData>
}
interface PriceRemoteDataSource {
suspend fun getPrices(): Resource<RemotePriceData>
}
interface PriceLocalDataSource {
suspend fun getPrices(): Resource<PriceDataEntity>
}
interface Mapper<I, O> {
fun mapTo(input: I): O
}
class PriceRepositoryImpl: PriceRepository {
override suspend fun getPrices() {
val localPrices: Resource<PriceDataEntity> = localDataSource.getPrices()
val remotePrices: Resource<RemotePriceData> = remoteDataSource.getPrices()
// Some logic ...
// Map results to Resource<PriceData> and return them? how?
}
}
Now my questions are:
How and where the mapping between different entities should happen? if it happens inside the repository, how should it be implemented (since we are wrapping objects inside Resource)?
I am exposing Resource from data sources in order to catch any exceptions inside them and only send the final result in a common format, is this a good practice? if not, where is the better place to handle errors?