Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AKIBA.swift: Layered ArchitectureにおけるRxSwiftを用いたErrorの伝搬

AKIBA.swift: Layered ArchitectureにおけるRxSwiftを用いたErrorの伝搬

Takeshi Ihara

April 17, 2017
Tweet

More Decks by Takeshi Ihara

Other Decks in Programming

Transcript

  1. RxSwift Rx is a generic abstraction of computation expressed through

    Observable<Element> interface. This is a Swift version of Rx.
  2. class ViewController: UIViewController { … override func viewDidLoad() { super.viewDidLoad()

    presenter.prepare() .subscribe( onNext: { domainModel in // Viewʹ൓ө }, onError: { error in // Τϥʔॲཧ } ) .addDisposableTo(disposeBag) } } subscribe - onError Ͳ͜Ͱى͖ͨΤϥʔ͔෼͔Βͳ͍ʜ
  3. ֤૚ͷΤϥʔΛఆٛ [Infra] enum InfrastructureError: Error { case connection case anthorization

    } extension InfrastructureError { static func create(error: Error) -> InfrastructureError { ... return infraError } }
  4. ֤૚ͷΤϥʔΛఆٛ [Domain] enum DomainError: Error { case logic case translation

    } extension DomainError { static func create(error: Error) -> DomainError { ... return domainError } }
  5. public static func error(_ error: Swift.Error) -> Observable<E> { return

    ErrorProducer(error: error) } Observable.error ObservableType.catchError public func catchError(_ handler: @escaping (Error) throws -> RxSwift.Observable<Self.E>) -> RxSwift.Observable<Self.E> 0CTFSWBCMFʹแΜͩΤϥʔΛੜ੒͢Δ 0CTFSWBCMFͷதͰൃੜͨ͠ΤϥʔΛ $BUDIͯ͠ճ෮ॲཧΛ͢Δ
  6. protocol Repository { func find() -> Observable<Entity> } struct RepositoryImpl:

    Repository { … func find() -> Observable<Entity> { return apiClient.send() .catchError { return Observable.error(InfrastructureError.create(error: $0)) } } } %PNBJO૚ʹެ։͢Δ*OUFSGBDF ͜͜Ͱ"1*͔Βฦ͖ͬͯͨ&SSPSΛ *OGSB&SSPSʹม׵͍ͯ͠Δ *OGSB
  7. struct Translator { static func translate(entity: Entity) throws -> DomainModel

    { ... throw DomainError.translation ... return domainModel } } protocol UseCase { func prepare() -> Observable<DomainModel> } struct UseCaseImpl: UseCase { … func prepare() -> Observable<DomainModel> { return repository.find() .map { try Translator.translate(entity: $0) } } } NBQͰUISPX͞ΕͨΒ 0CTFSWBCMFFSSPSʹͳΔ %PNBJO
  8. struct Presenter { … func prepare() -> Observable<DomainModel> { return

    useCase.prepare() .catchError { error in guard let infraError = error as? InfrastructureError else { return Observable.error(PresentationError.unknown) } switch infraError { case .connection: return Observable.error(PresentationError.connection) default: return Observable.error(PresentationError.unknown) } } } } 1SFTFOUBUJPO ಛఆͷ&SSPSܕͷͱ͖ʹ ಛผͳΤϥʔΛฦ͢