Domain Layer
정의
UI Layer와 Data Layer 사이에 있는 선택적 Layer로,
복잡한 비즈니스 로직 또는 여러 ViewModel에서 재사용되는 간단한 비즈니스 로직의 캡슐화를 담당한다.
Domain Layer의 장점
- 코드 중복 방지
- 가독성 향상
- 테스트 용이성
- 책임 분할을 통한 대형 클래스 분리
Domain Layer의 네이밍 규칙
현재 시제의 동사 + 명사/대상(선택사항) + UseCase
예를 들면 "LogOutUserUseCase", "GetLatestNewsithAuthorUsecase", "MakeLoginRequestUsecase"가 있다.
종속 항목
1. UseCase 클래스는 UI Layer의 ViewModel과 Data Layer의 Repository 사이에 위치한다.
즉, Repository 클래스에 종속되며, Repository와 마찬가지로 콜백(Java) 또는 코루틴(Kotlin)을 사용하여 UI Layer와 통신한다.
다음은 뉴스 Reository의 데이터와 작성자 Repository의 데이터를 가져와서 이를 결합하는 Usecase 예시이다.
/**
* This use case fetches the latest news and the associated author.
*/
class GetLatestNewsWithAuthorsUseCase(
private val newsRepository: NewsRepository,
private val authorsRepository: AuthorsRepository,
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
suspend operator fun invoke(): List<ArticleWithAuthor> =
withContext(defaultDispatcher) {
val news = newsRepository.fetchLatestNews()
val result: MutableList<ArticleWithAuthor> = mutableListOf()
// This is not parallelized, the use case is linearly slow.
for (article in news) {
// The repository exposes suspend functions
val author = authorsRepository.getAuthor(article.authorId)
result.add(ArticleWithAuthor(article, author))
}
result
}
}
NewsRepository에서 노출되는 Article 클래스는 작성자 이름만 포함된다. 하지만 개발자는 화면에 자세한 작성자 정보를 표시하고자 할 수 있으며 이를 표시하기 위해 AuthRepository를 사용한다.
2. Usecase는 재사용 가능한 로직을 포함하기 때문에 다른 Usecase에 의해 사용될 수도 있다. 따라서 Domain Layer에 여러 수준의 UseCase가 있을 수 있다.
다음은 UI Layer의 여러 클래스가 시간대를 사용하여 화면에 적절한 메시지를 표시하는 경우 FormatDateUseCase를 사용하는 경우이다
class GetLatestNewsWithAuthorsUseCase(
private val newsRepository: NewsRepository,
private val authorsRepository: AuthorsRepository,
private val formatDateUseCase: FormatDateUseCase
) { /* ... */ }
ViewModel에서 UseCase 호출 예시
class MyViewModel(formatDateUseCase: FormatDateUseCase) : ViewModel() {
init {
val today = Calendar.getInstance()
val todaysDate = formatDateUseCase(today)
/* ... */
}
}
class FormatDateUseCase(userRepository: UserRepository) {
private val formatter = SimpleDateFormat(
userRepository.getPreferredDateFormat(),
userRepository.getPreferredLocale()
)
operator fun invoke(date: Date): String {
return formatter.format(date)
}
}
Kotlin에서 operator 연산자와 함께 invoke()함수를 정의하여 UseCase 클래스 인스턴스를 함수처럼 호출 가능하게 만들 수 있다.
'Android > Architecture' 카테고리의 다른 글
안드로이드 Clean Architecture - 예제 (Rxjava) (0) | 2023.05.27 |
---|---|
안드로이드 Clean Architecture - 개념 (0) | 2023.05.27 |
[Android] 앱 아키텍처 가이드 (3) - Data Layer (0) | 2023.05.01 |
[Android] 앱 아키텍처 가이드 (2) - UI Layer (0) | 2023.04.29 |
[Android] 앱 아키텍처 가이드 (1) - 개요 (0) | 2023.04.12 |