일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- PrototypePattern
- ㅋㅁ
- 추상팩토리패턴
- ㅓ
- 옵저버 패턴
- Functional Programming
- android designsystem
- compose
- factory method
- 함수형프로그래밍
- material3
- designPattern
- 싱글톤
- El
- Observer Pattern
- 안드로이드 디자인시스템
- Kotlin
- Abstract Factory
- Design Pattern
- 추상 팩토리
- r
- Singleton
- 디자인패턴
- 디자인패턴 #
- 코틀린
- 프로토타입 패턴
- F
- 팩토리 메소드
- 빌터패턴
- builderPattern
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
DomainLayer(usecase) 사용하기 본문
원칙
- 관심사의 분리(컴퓨터 공학 디자인 원칙, 계층화된 디자인)
구별된 부분으로 분리시키는 디자인 원칙으로, 각 부문은 개개의 관심사를 해결
- 단일 책임의 원칙(객체지향 프로그래밍의 원칙)
클래스 변경하려는 단 하나 이유만을 가져야 한다고 결론
- Data Model에서 UI 도출
데이터 모델(UI 요소 및 기타 구성요소와 독립적)에서 UI를 도출해야 한다는 것
구조화 계층
UI Layer (표현 계층)
화면에 애플리케이션 데이터를 표시하는 것.
사용자 상호작용(예: 버튼 누르기) 또는 외부 입력(예: 네트워크 응답)으로 인해 데이터가 변할 때마다 변경사항을 반영하도록 UI가 업데이트된다
UI elements
화면에 데이터를 렌더링하는 UI 요소. 이러한 요소는 View(xml) 또는 Jetpack Compose 함수를 사용하여 Activity/Fragment에 빌드
State Holders
데이터를 보유하고 이를 UI에 노출하며 로직을 처리하는 상태 홀더(ViewModel)
UI controller(Activity, Fragment) 와 ViewModel (N : N)
* viewModel의 생명주기를 잘 설정해야 한다.
Data Layer(데이터 계층)
데이터 레이어에는 비즈니스 로직이 포함
비즈니스 로직은 앱에 가치를 부여하는 요소 - (앱의 데이터 생성, 저장, 변경 방식을 결정하는 규칙으로 구성)
*Repository Pattern - 데이터 소스(로컬 DB, Network API, )와 관계 없이 동일한 인터페이스로 데이터 제공 및 접근
- 앱에서 처리하는 다양한 유형의 데이터마다 저장소 클래스를 만들어야 한다.
- 각 저장소는 0-N개의 데이터 소스를 포함 할수 있다.
ViewModel - Repository (N : N)
* Repository는 Singleton 객체, 하나의 데이터 소스 를 관리한다.
Android MVVM 기본적인 구조
Domain Layer(도메인 계층)
domain - 데이터를 다루는 영역, 범위
domain는 UI 레이어와 data layer 사이에 존재 선택적이다.
복잡한 비즈니스 로직, 또는 여러 ViewModel에서 재사용되는 간단한 비즈니스 로직의 캡슐화를 담당
복잡성을 처리하거나 재사용성을 선호하는 등 필요한 경우에만 도메인 레이어를 사용
- 코드 중복을 방지
- domain layer 를 사용하는 클래스의 가독성을 개선
- 앱의 테스트 가능성을 높입니다.
- 책임을 분할하여 대형 클래스를 방지
UseCase
현재 시제의 동사 + 명사/대상(선택사항) + UseCase
class GetLatestNewsWithAuthorsUseCase(
private val newsRepository: NewsRepository,
private val authorsRepository: AuthorsRepository
) { /* ... */ }
class GetLatestNewsWithAuthorsUseCase(
private val newsRepository: NewsRepository,
private val authorsRepository: AuthorsRepository,
private val formatDateUseCase: FormatDateUseCase
) { /* ... */ }
class FormatDateUseCase(userRepository: UserRepository) {
private val formatter = SimpleDateFormat(
userRepository.getPreferredDateFormat(),
userRepository.getPreferredLocale()
)
operator fun invoke(date: Date): String {
return formatter.format(date)
}
}
Life Cycle
UseCase 고유한 수명 주기를 갖지는 않습니다. UseCase 를 사용하는 클래스로 범위가 지정됩니다.
즉, UI 레이어의 클래스에서, 서비스에서 또는 Application 클래스 자체에서 사용 사례를 호출할 수 있습니다.
UseCase는 변경 가능한 데이터를 포함해서는 안 되므로 개발자가 UseCase 클래스의 새 인스턴스를 종속 항목으로 전달할 때마다 그 인스턴스를 생성해야된다.
Threading
도메인 레이어의 UseCase는 기본 안전성을 갖추어야 합니다. 즉, MainThread 에서 안전하게 호출되어야 합니다.
UseCase 클래스는 장기 실행 차단 작업을 실행하는 경우 관련 로직을 적절한 스레드로 옮깁니다.
하지만, 그 작업 전에 개발자는 계층 구조에서 Thread 차단 작업이 더 잘 배치되는 다른 레이어가 있는지 확인하여 배치한다.
복잡한 계산은 재사용이나 캐싱을 유도하기 위해 데이터 레이어에서 이루어집니다.
예를 들어 결과를 캐시하여 앱의 여러 화면에서 재사용해야 하는 경우 대용량 목록을 대상으로 한 리소스 집약적인 작업은 도메인 레이어보다 데이터 레이어에 더 잘 배치됩니다
class MyUseCase(
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
suspend operator fun invoke(...) = withContext(defaultDispatcher) {
// Long-running blocking operations happen on a background thread.
}
}
Repository 결합.
뉴스와 작성자 데이터 작업을 각각 처리하는 NewsRepository 클래스와 AuthorsRepository.
NewsRepository에서 제공하는 Article 클래스에는 Authors 이름만 알수있다.
개발자는 화면에 자세한 작성자 정보를 표시하고자 할 수 있습니다. 작성자 정보는 AuthorsRepository에서 얻어야 한다.