SOPT 과제를 수행하면서 아래 코드를 사용했는데 해당 코드의 역할에 대해서 질문을 받았다.
그 이유에 대해서 정리하고 남겨볼려고한다.
ModuleFactory 사용 이유
UML

UML작성 기준: https://www.nextree.co.kr/p6753/
ModuleFactory 코드
import UIKit
protocol ModuleFactoryProtocol {
func makeLoginViewController() -> UIViewController
func makeWelcomeViewController() -> UIViewController
}
final class ModuleFactory: ModuleFactoryProtocol {
static let shared = ModuleFactory()
private init() {}
func makeLoginViewController() -> UIViewController {
let useCase = LoginUseCase()
let viewModel: LoginViewModel = DefaultLoginViewModel(useCase: useCase)
let viewController = LoginViewController(viewModel: viewModel)
return viewController
}
func makeWelcomeViewController() -> UIViewController {
let viewController = WelcomeViewController()
return viewController
}
}
ViewController를 만들 때 ViewModel과 같이 생성에 필요한 객체들이 있죠.
클린아키텍쳐등을 적용한다면, ViewModel에는 UseCase를 생성시에 필요로 합니다. 또, UseCase를 생성하는데에는 또 Repository를 필요로 합니다.
이렇게 의존성이 늘어가게 되면 우리가 평상시에 ViewController를 생성하듯이 ViewController를 생성할려면 어떻게 해야할까요?
LoginViewController(viewModel: DefaultLoginViewModel(useCase: LoginUseCase()))
이런식으로 생성자안에 꼬리를 물고 의존성이 쭉 늘어지게 되겠죠. 지금은 UseCase까지 있지만, 후에 Repository나 의존성이 늘어나게 되면 더욱 더 복잡해집니다. (의존성이 매우 높은 상태)
그리고 우린 이런 코드를 매번 ViewController를 만들 때마다 적어줘야합니다. 중복된 코드가 계속 늘어나게 되는 거죠. 그리고 만약 변경사항이 생긴다면 모든 ViewController를 생성하는 코드를 찾아서 하나하나 변경해주어야 합니다.
이렇게 객체간의 의존성이 높다면 코드의 재사용을 어렵게 만듭니다. 또한, 테스트시에 객체를 독립적으로 다룰 수 없어 테스트를 수행하기에도 어려움이 존재합니다.
우리는 ModuleFactory처럼 ViewController를 만드는 Factory를 만들어 쓰면 이런 상황을 해결할 수 있습니다.
let loginVC = ModuleFactory.shared.makeLoginViewController()
위에서 생성자들을 일일히 만들어서 넣는 과정은 모두 숨긴 채(캡슐화), 객체(ViewController)를 생성할 수 있습니다. 클라이언트, 즉 호출하는 입장에서는 그냥 객체를 달라고 하고, 안에서 해당 객체를 어떻게 만드는지에 대해서는 알지도 못하고 궁금해하지도 않는거죠.
프로토콜을 쓰면 해당 프로토콜을 채택한 Factory가 정해진 타입의 객체를 반환하게끔 강제됩니다. 그렇기에 생성하는 객체가 포로토콜에서 지정한 객체의 타입과 일치하다면 클라이언트 입장에서 아무런 수정없이 쓸 수 있습니다.
Ref
https://medium.com/@amiddleeasterner/make-it-for-me-factory-pattern-and-swift-ae8668a11741
https://medium.com/@mayooresan/swift-factory-pattern-6f0d7556d862
'Dev > 고민과 삽질의 기록들🤔' 카테고리의 다른 글
[삽질] 클래스의 확장성 개선(protocol 의존성 주입: any) (0) | 2023.06.01 |
---|---|
[삽질] Infinite Carousel 구현해보기 + auto scrolling(Timer) (0) | 2023.05.08 |
[삽질] 상단 Custom TabBar 구현 (3) | 2023.05.01 |
[삽질] BottomSheet 구현 중 시행착오 + 해결과정 (PanGesture, CGAffineTransform) (1) | 2023.04.16 |
[iOS] 메모리 뜯어보기 (힙할당 줄이기 및 누수 해결하기) (0) | 2023.03.11 |
댓글