티스토리 뷰

반응형

클린아키텍처 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

 

Design Patterns: Abstract Factory in Swift

Usage examples: The Abstract Factory pattern is pretty common in Swift code. Many frameworks and libraries use it to provide a way to extend and customize their standard components. Identification: The pattern is easy to recognize by methods, which return

refactoring.guru

 

사실 상 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

 

Software Design Patterns: Factories Are Not Builders

The difference between Factory and Builder design patterns

betterprogramming.pub

 

반응형
댓글