Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- uiscrollview
- Refactoring
- combine
- collectionview
- ribs
- HIG
- MVVM
- SWIFT
- Xcode
- 클린 코드
- swiftUI
- 리펙토링
- Observable
- 리팩토링
- ios
- uitableview
- RxCocoa
- swift documentation
- map
- clean architecture
- 애니메이션
- Human interface guide
- UITextView
- Clean Code
- rxswift
- 스위프트
- UICollectionView
- tableView
- Protocol
- 리펙터링
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] clean architecture - DI (필요한 곳에서 protocol에 선언하는 방법) 본문
Architecture (swift)/MVVM (맛보기)
[iOS - swift] clean architecture - DI (필요한 곳에서 protocol에 선언하는 방법)
jake-kim 2021. 7. 13. 01:011. DI패턴 (필요한 곳에서 protocol에 선언하는 방법)
DI 패턴
- ADIContainer와 AViewModel이 있고 DIContainer에서 AViewModel를 만들 때, AViewModel에 필요한 값을 정의하는 방법
- DIP와 테스트에 용이하기 위하여 protocol을 통해 설계는 2. 테스트 구조를 고려한 DI패턴 참고
- 1. DI패턴 (필요한 곳에서 protocol에 선언하는 방법)의 목적
- DIContainer자체가 구현체가 되는 패턴 파악
- DIContainer가 구현체가 되는 '패턴'에 대해서 보며, 이 방법은 의미없다는것을 알고 Usecase위치는 ViewModel에 있어야한다는 것을 깨닫는 목적
- 테스트시에 DIContainer 구현체를 변경하는 일은 적으므로 ViewModel에서 Usecase를 init값에 받는것이 이상적
일차원적인 DI 방법
- A -> B화면전환 시, B의 Dependencies에 protocol이 아닌 class를 바로 참조하는 것
- 구성
- BViewController
- BViewModel
- BDIContainer
// BViewController.swift
class BViewController: UIViewController {
private var viewModel: BViewModel!
static func create(with viewModel: BViewModel) -> BViewController {
let view = BViewController()
view.viewModel = viewModel
return view
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
}
}
- ViewModel에 Dependencies가 있고 BDIContainer에서 해당 코드를 바로 참조하는 형태
// BViewModel.swift
protocol BInput {
}
protocol BOutput {
}
protocol BViewModel: BInput, BOutput {}
class DefaultBViewModel: BViewModel {
let dependencies: Dependencies
struct Dependencies {
let countNumber: Int
let someUseCase: SomeUseCase
}
init(dependencies: Dependencies) {
self.dependencies = dependencies
}
}
- BDIContainer: BViewModel의 Dependencies를 참조
// BDIContainer.swift
class BDIContainer {
func makeBViewController(countNumber: Int) -> BViewController {
let vc = BViewController.create(with: makeBViewModel(countNumber: countNumber))
return vc
}
func makeBViewModel(countNumber: Int) -> BViewModel {
return DefaultBViewModel(dependencies: .init(countNumber: countNumber,
someUseCase: SomeUseCase()))
}
}
* source code: 일차원적인 DI방법
필요한 곳에서 protocol에 선언하고 주입하는 쪽에서 구현하여 사용 방법
- BViewModel에 Protocol로 Dependencies 정의
// BViewModel.swift
protocol BInput {
}
protocol BOutput {
}
protocol BViewModel: BInput, BOutput {}
protocol BDependencies { // 추가
func getSomeUseCase() -> SomeUseCase
}
class DefaultBViewModel: BViewModel {
let dependencies: BDependencies // 추가
let countNumber: Int
struct Dependencies {
let someUseCase: SomeUseCase
}
init(countNumber: Int, dependencies: BDependencies) {
self.countNumber = countNumber
self.dependencies = dependencies
}
func executeSomeUsecase() { // usecase는 주입받은 usecase이용
let usecase = dependencies.getSomeUseCase()
print("execute usecase")
}
}
- BDIContainer에서 protocol을 구현하여 self로 주입
- 구현체가 BDIContainer가 되는 개념
// BDIContainer.swift
class BDIContainer {
func makeBViewController(countNumber: Int) -> BViewController {
let vc = BViewController.create(with: makeBViewModel(countNumber: countNumber))
return vc
}
func makeBViewModel(countNumber: Int) -> BViewModel {
return DefaultBViewModel(countNumber: countNumber, dependencies: self) // 추가: self로 주입
}
}
extension BDIContainer: BDependencies { // 추가
func getSomeUseCase() -> SomeUseCase {
return SomeUseCase()
}
}
* source code: 필요한 곳에서 protocol에 선언하고 주입하는 쪽에서 구현하여 사용 방법
테스트 관점에서 의미있는 코드인지 판단
- Test 시에 BDIContainer를 사용 > UseCase를 갈아 치울 수 없고 이미 extension으로 정의되어 있으므로 usecase를 갈아치우며 테스트하는 로직에 어려움이 존재
- UseCase는 ViewModel의 init에서 받는 구조가 되어야, 테스트 로직 시 usecase만 mock으로 만들고 viewMoel에 주입하여 테스트 하는 코드가 이상적
'Architecture (swift) > MVVM (맛보기)' 카테고리의 다른 글
[iOS - swift] clean architecture - DI (DI패턴, unit test, business logic test) (0) | 2021.07.15 |
---|---|
[iOS - swift] clean architecture를 적용한 MVVM 코드 맛보기 (0) | 2021.06.19 |
[iOS - swift] clean architecture를 적용한 MVVM 개념 맛보기 (1) | 2021.06.18 |
Comments