티스토리 뷰
클린아키텍처 11장 DIP - 의존성 역전원칙 을 읽다가
Abstract Factory 에 대해 여러 고민이 들어서 기록!
[1] 책 내용
객체를 생성하려면 해당 객체를 구체적으로 정의한 코드에 대해 소스 코드 의존성이 발생하게 된다.
이런 의존성을 처리하기 위해 추상 팩토리를 사용한다.
예를들어
Application은 ConcreateImpl 에 대한 소스 코드 의존성을 만들지 않기 위해
ServiceFactory 인터페이스의 makeSvc 메소드를 호출하고
ServiceFactoryImp 구현체가 ConcreateImpl 의 인스턴스를 생성한 후 Service 타입으로 반환한다.
곡선은 아키텍쳐 경계를 뜻하는데, 구체적인 것들로부터 추상적인 것들을 분리한다.
[2] 경험 + 구글링
보통 Factory 패턴을 쓸 때 Factory 인터페이스 까지 정의해서 쓰는 것을 본 적이 별로 없는 것 같다.
레이웬더리치 글에 나오는 예제도 그렇고 리팩토링 2판에 나오는 예제도 Factory 인터페이스는 안만들었던 것으로 기억.
그동안 내가 본 Abstract Factory는 쓰는 곳은 립스이다.
Factory랑 비슷하게 객체 생성을 하는 RIBs의 Builder는
- Buildable (인터페이스)
- Builder (구현)
로 되어있기 때문이다.
립스밖에 없나..?? 하고 검색을 해보니
아주 명시적으로 Abstract Factory 라고 네이밍을 해서 쓰는 예제도 있고
https://refactoring.guru/design-patterns/abstract-factory/swift/example
사실 상 Factory와 Router가 섞여있는 개념인 Coordinator를
명확히 Factory, Router로 나눠서 쓰는 예제도 인상깊었다.
final class ApplicationCoordinator: BaseCoordinator {
private let coordinatorFactory: CoordinatorFactory
private let router: Router
init(router: Router, coordinatorFactory: CoordinatorFactory) {
self.router = router
self.coordinatorFactory = coordinatorFactory
}
...
}
protocol Router: Presentable {
func present(_ module: Presentable?)
func present(_ module: Presentable?, animated: Bool)
func push(_ module: Presentable?)
func push(_ module: Presentable?, hideBottomBar: Bool)
func push(_ module: Presentable?, animated: Bool)
func push(_ module: Presentable?, animated: Bool, completion: (() -> Void)?)
func push(_ module: Presentable?, animated: Bool, hideBottomBar: Bool, completion: (() -> Void)?)
func popModule()
func popModule(animated: Bool)
func dismissModule()
func dismissModule(animated: Bool, completion: (() -> Void)?)
func setRootModule(_ module: Presentable?)
func setRootModule(_ module: Presentable?, hideBar: Bool)
func popToRootModule(animated: Bool)
}
final class RouterImp: NSObject, Router {
...
}
protocol CoordinatorFactory {
func makeTabbarCoordinator() -> (configurator: Coordinator, toPresent: Presentable?)
func makeAuthCoordinatorBox(router: Router) -> Coordinator & AuthCoordinatorOutput
func makeOnboardingCoordinator(router: Router) -> Coordinator & OnboardingCoordinatorOutput
func makeItemCoordinator(navController: UINavigationController?) -> Coordinator
func makeItemCoordinator() -> Coordinator
func makeSettingsCoordinator() -> Coordinator
func makeSettingsCoordinator(navController: UINavigationController?) -> Coordinator
func makeItemCreationCoordinatorBox() ->
(configurator: Coordinator & ItemCreateCoordinatorOutput,
toPresent: Presentable?)
func makeItemCreationCoordinatorBox(navController: UINavigationController?) ->
(configurator: Coordinator & ItemCreateCoordinatorOutput,
toPresent: Presentable?)
}
final class CoordinatorFactoryImp: CoordinatorFactory {
func makeTabbarCoordinator() -> (configurator: Coordinator, toPresent: Presentable?) {
let controller = TabbarController.controllerFromStoryboard(.main)
let coordinator = TabbarCoordinator(tabbarView: controller, coordinatorFactory: CoordinatorFactoryImp())
return (coordinator, controller)
}
..
}
[3] Abstract Factory 꼭 써야할까?
오브젝트 책에서 설계는 트레이드 오프 라고 했다.
Abstract Factory 를 사용함으로써 책에서 나오는 예쁜 곡선 (구체적인 것들로 부터 추상적인 것들을 분리하는 곡선) 을 얻을 수 있겠지만
한편으로는 리팩토링 책과 다른 예제들에서 Abstract Factory를 굳이 안만드는 이유도 있을 것이라는 생각이 든다.
(짧은 경험이지만 립스에서 Builable과 Builder를 열심히 수정하며 많은 컴파일 에러를 고쳤던 기억이 난다ㅎㅎ,,)
[ 참고 ]
이글에서는 객체생성을 한다는 이유로 factory, builder 를 동일한 개념으로 봤지만
엄밀히 말하면,, factory는 builder가 아니라는 주장도 있습니다!
https://betterprogramming.pub/software-design-patterns-factories-are-not-builders-dc4c1297de8f
'책도 읽고' 카테고리의 다른 글
[클린아키텍처] 서비스를 안티패턴이라고 하는 이유 (1) | 2022.07.03 |
---|---|
[클린 아키텍처] 의존성 순환 (cyclic dependency) 의 문제와 해결방안 (5) | 2022.04.07 |
리팩터링 (7) - 타입코드를 서브클래스로 / 서브클래스를 위임으로 (0) | 2021.08.20 |
리팩터링 (6) - 객체 통째로 넘기기 / 매개변수 / 예외 (0) | 2021.07.30 |
리팩터링 (5) - 조건부 로직을 다형성으로 / 특이 케이스 / Assertion (0) | 2021.07.12 |
- Total
- Today
- Yesterday
- Python Type Hint
- Flutter getter setter
- Django Heroku Scheduler
- ipad multitasking
- Watch App for iOS App vs Watch App
- 장고 Custom Management Command
- PencilKit
- SerializerMethodField
- Sketch 누끼
- github actions
- flutter 앱 출시
- Django Firebase Cloud Messaging
- drf custom error
- Flutter Spacer
- cocoapod
- flutter build mode
- DRF APIException
- flutter deep link
- ribs
- Flutter Clipboard
- 구글 Geocoding API
- Dart Factory
- Django FCM
- METAL
- Flutter 로딩
- 플러터 싱글톤
- 플러터 얼럿
- Flutter Text Gradient
- 장고 URL querystring
- flutter dynamic 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 |