이번 포스팅은 Clean architecture의 가장 안쪽 레이어인 Domain 레이어를 구현할 것이다.
즉, 이전 포스팅에서 생성한 domain 모듈을 구현한다.
먼저 entity를 구현해보도록 하겠다.
포켓몬 도감은 포켓몬들을 리스트업하고 상세한 내용을 볼 수 있는 기능을 갖는다.
따라서 포켓몬 리스트를 구성할 Entity와 포켓몬 상세를 표현할 Entity가 필요하다.
아래와 같은 Entity 코드를 작성한다.
data class PokemonEntity(
val id: Int,
val name: String,
val imageUrl: String
)
data class PokemonDetailEntity(
val id: Int,
val name: String,
val imageUrl: String,
val weight: Int,
val height: Int,
val stats: List<PokemonStatEntity>,
val types: List<PokemonTypeEntity>
)
data class PokemonStatEntity(
val name: String,
val stat: Int
) {
val progress: Float
get() = stat.div(300f)
}
enum class PokemonTypeEntity(
val type: String
) {
NORMAL("normal"),
FIRE("fire"),
WATER("water"),
ELECTRIC("electric"),
GRASS("grass"),
ICE("ice"),
FIGHTING("fighting"),
POISON("poison"),
GROUND("ground"),
FLYING("flying"),
PSYCHIC("psychic"),
BUG("bug"),
ROCK("rock"),
GHOST("ghost"),
DRAGON("dragon"),
DARK("dark"),
STEEL("steel"),
FAIRY("fairy")
}
이제 이 Entity를 획득할 수 있는 Repository interface를 구현한다.
interface PokemonRepository {
fun getPokemonPagingSource(
limit: Int
) : Flow<PagingData<PokemonEntity>>
suspend fun getPokemonDetail(name: String) : PokemonDetailEntity
}
이 interface를 data 레이어에서 구현하여 사용하게 된다.
이제 이 Repository를 통해 포켓몬 목록과 포켓몬 상세를 얻는 UseCase를 작성한다.
class GetPokemonListUseCase @Inject constructor(
private val pokemonRepository: PokemonRepository
) {
operator fun invoke(
limit: Int,
) = pokemonRepository.getPokemonPagingSource(limit)
}
class GetPokemonUseCase @Inject constructor(
private val pokemonRepository: PokemonRepository
) {
suspend operator fun invoke(
name: String
): PokemonDetailEntity = withContext(Dispatchers.IO) {
pokemonRepository.getPokemonDetail(name)
}
}
여기까지 작성하면 domain 레이어의 구현은 끝이 난다.
코드가 길거나 어려운 부분은 없었다.
이 프로젝트에서 의존성 주입을 위해 Hilt를 사용하므로, DI 모듈을 아래와 같이 작성한다.
@Module
@InstallIn(SingletonComponent::class)
object UseCaseModule {
@Provides
@Singleton
fun provideGetPokemonListUseCase(
pokemonRepository: PokemonRepository
): GetPokemonListUseCase = GetPokemonListUseCase(pokemonRepository)
@Provides
@Singleton
fun provideGetPokemonUseCase(
pokemonRepository: PokemonRepository
): GetPokemonUseCase = GetPokemonUseCase(pokemonRepository)
}
Hilt를 통해 정말 쉽게 의존성 주입을 할 수 있다.
다음은 이 domain 레이어를 활용하여 data 레이어를 구현할 것이다.
data 레이어는 Repository interface를 구현하여 presentation에서 entity를 얻을 수 있도록 한다.
domain 레이어의 전체 코드는 아래 깃허브에서 확인할 수 있다.
https://github.com/DuItDDu/Android_CleanArchitecture_Pokedex/tree/master/domain
반응형