DI(Dependency Injection)이란?
- 의존성을 객체 외부에서 주입해주는 형식
- SOLID원칙중 DIP(의존성 역전 원칙)으로 특정 모듈에 의존하지 않고 의존성이 역전됨을 의미
- 상위모듈은 의존성 주입을 통해 하위 모듈에 의존하지 않고 구조 설계 가능
Dependency Injection이 적용되지 않은 경우
class Foo {
private var bar: Bar
init() {
self.bar = Bar()
}
}
Dependency Injection이 적용된 경우
class Foo {
private var bar: Bar
init(bar: Bar) {
self.bar = bar
}
}
DI가 필요한 이유
- Interface를 통해 구체타입에 의존하지 않고(결합도↓) 상황에 따라 변경가능하고 단위 테스트시 간결함을 유지
- 의존성 파라미터를 생성자에서 작성하지 않고 주입받음으로써 유연한 프로그래밍 가능
DIContainer 예시(+with Coordinator)
DIContainer에서 Coordinator 주입
DIContainer에서 (ViewController, viewModel, usecase..) dependencies self로 정의
class DIContainer {
func createMainCoordinator(navigationController: UINavigationController) -> MainCoordinator {
return MainCoordinator(navigationController: navigationController, dependencies: self)
}
}
extension DIContainer: MainCoordinatorDependencies {
func createHomeViewController(actions: HomeViewModelActions) -> UIViewController {
let viewModel = HomeViewModel(actions: actions)
return HomeViewController(viewModel: viewModel)
}
func createDetailViewController() -> UIViewController {
return DetailViewController()
}
}
DIContainer에서 Coordinator를 만들어서 주입
let diContainer = DIContainer()
let navigationController = UINavigationController()
let mainCoordinator = diContainer.createMainCoordinator(navigationController: navigationController)
- 화면이동 Process
Coordinator에서 화면이동 핸들러 정의(showDetailViewController)
protocol MainCoordinatorDependencies {
func createHomeViewController(actions: HomeViewModelActions) -> UIViewController
func createDetailViewController() -> UIViewController
}
final class MainCoordinator {
private var navigationController: UINavigationController?
private let dependencies: MainCoordinatorDependencies
init(navigationController: UINavigationController, dependencies: MainCoordinatorDependencies) {
self.navigationController = navigationController
self.dependencies = dependencies
}
func start() {
let actions = HomeViewModelActions(showDetail: showDetailViewController)
let homeViewController = self.dependencies.createHomeViewController(actions: actions)
self.navigationController?.pushViewController(homeViewController, animated: true)
}
private func showDetailViewController() {
let detailViewController = dependencies.createDetailViewController()
self.navigationController?.pushViewController(detailViewController, animated: true)
}
}
viewModel에 Actions주입
struct HomeViewModelActions {
let showDetail: () -> Void
}
protocol HomeViewModelInput {
func didTappedNextButton()
}
protocol HomeViewModelOutput { }
protocol HomeViewModelIO: HomeViewModelInput, HomeViewModelOutput { }
final class HomeViewModel: HomeViewModelIO {
private let actions: HomeViewModelActions
init(actions: HomeViewModelActions) {
self.actions = actions
}
}
extension HomeViewModel {
func didTappedNextButton() {
actions.showDetail()
}
}
참고
https://ali-akhtar.medium.com/ios-dependency-injection-using-swinject-9c4ceff99e41
'Design Pattern' 카테고리의 다른 글
Delegate Pattern (0) | 2021.12.14 |
---|---|
Clean Architecture (0) | 2021.12.10 |
MVC Pattern (0) | 2021.12.10 |