Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
AKIBA.swift: Layered ArchitectureにおけるRxSwiftを用い...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Takeshi Ihara
April 17, 2017
Programming
2.5k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
AKIBA.swift: Layered ArchitectureにおけるRxSwiftを用いたErrorの伝搬
https://classmethod.connpass.com/event/53603/
Takeshi Ihara
April 17, 2017
More Decks by Takeshi Ihara
See All by Takeshi Ihara
iOSDC20200921: Feature Flagを適切に分類することでA/Bテストの運用コストを下げる
nonchalant
3
1.4k
iOSDC 20190906: 動画アプリの投げ銭機能における 消耗型課金の仕組みと実装
nonchalant
3
6.4k
iOSDC 20190906: 動画アプリの投げ銭機能における 消耗型課金の仕組みと実装 with 発表ノート
nonchalant
2
640
Sign In with Apple
nonchalant
1
2.5k
iOSDC RejectCon 20180915: Factoryの自動生成によりテストを書きやすくする
nonchalant
1
760
iOSDC 20180902: 小さくはじめる端末管理
nonchalant
2
1k
devsap 20180728: コード生成のススメ
nonchalant
0
150
potatotips #50: iOSは自動生成の夢を見るか?
nonchalant
0
2k
try! Swift Tokyo 2018: Best Docker Container in Swift
nonchalant
1
1.4k
Other Decks in Programming
See All in Programming
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
220
信頼性の目標を誰も求めてない
shubox
0
490
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
1
640
AIを上手に使っていこうとしたら越境せざるを得なくなった話 〜実践1年で見えた境界を越えなければならない理由と進め方〜 / Crossing borders with AI
tomoyakitaura
4
1.1k
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
0
250
コンパウンドプロダクト開発のためのローカルプロセスマネージャー再発明 #layerxgo
izumin5210
0
660
デプロイ直後のレイテンシスパイクを調べたら、 Railsの仕様にたどり着いた
nhsykym
0
110
20260828_品質と開発生産性を両立させる、AI時代のE2Eテストの考え方
magicpod
0
170
新卒PdEのリアル
ryu1013
1
420
AI時代に学ぶ 好きなルール 嫌いなルール Linter編
shorty5121
0
880
「AI時代、配布するPythonコードをどう守るか: 難読化の実験と判断軸」 #PyconJP2026
pkshadeck
PRO
2
180
30年振りにコンパイラの定数整数除算を改善した
herumi
9
4.5k
Featured
See All Featured
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
Build your cross-platform service in a week with App Engine
jlugia
234
19k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.3k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
520
Code Review Best Practice
trishagee
74
20k
エンジニアに許された特別な時間の終わり
watany
108
250k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Transcript
Layered Architectureʹ͓͚Δ RxSwiftΛ༻͍ͨErrorͷൖ Kyobashi.swift Recruit Marketing Partners
ࣗݾհ • Takeshi Ihara / @nonchalant0303 • Recruit Marketing Partners
• iOS Engineer
RxSwiftʹContribute͠·ͨ͠
Layered Architecture *OGSB 1SFTFOUBUJPO %PNBJO
Layered Architecture *OGSB "1*3FRVFTU %# 1SFTFOUBUJPO 6* %PNBJO ϏδωεϩδοΫ
Error *OGSB 1SFTFOUBUJPO %PNBJO $POOFDUJPO 6OBVUIPSJ[FE 4FSWFS&SSPS -PHJD 5SBOTMBUJPO
*OGSB 1SFTFOUBUJPO %PNBJO $POOFDUJPO 4FSWFS&SSPS -PHJD 5SBOTMBUJPO 6OBVUIPSJ[FE "MFSU'BMMCBDL "MFSU3FUSZ
Each Error, Each Process
͜ͷ֤ͷErrorΛͲ͏ͬͯ RxSwiftΛͬͯ ϋϯυϦϯά͢Δ͔͕ࠓճͷ
RxSwift Rx is a generic abstraction of computation expressed through
Observable<Element> interface. This is a Swift version of Rx.
class ViewController: UIViewController { … override func viewDidLoad() { super.viewDidLoad()
presenter.prepare() .subscribe( onNext: { domainModel in // Viewʹө }, onError: { error in // Τϥʔॲཧ } ) .addDisposableTo(disposeBag) } } subscribe - onError Ͳ͜Ͱى͖ͨΤϥʔ͔͔Βͳ͍ʜ
·ͣ
֤ͷΤϥʔΛఆٛ [Infra] enum InfrastructureError: Error { case connection case anthorization
} extension InfrastructureError { static func create(error: Error) -> InfrastructureError { ... return infraError } }
֤ͷΤϥʔΛఆٛ [Domain] enum DomainError: Error { case logic case translation
} extension DomainError { static func create(error: Error) -> DomainError { ... return domainError } }
֤ͷΤϥʔΛఆٛ [Presentation] enum PresentationError: Error { case connection case unknown
}
Layered Architecture x RxSwift *OGSB 1SFTFOUBUJPO %PNBJO 0CTFSWBCMF&OUJUZ 0CTFSWBCMF%PNBJO.PEFM "1*3FRVFTU
&WFOU 7JFXʹө
Layered Architecture x RxSwift *OGSB 1SFTFOUBUJPO %PNBJO 0CTFSWBCMF&OUJUZ 0CTFSWBCMF%PNBJO.PEFM "1*3FRVFTU
&WFOU 7JFXʹө *OGSB&SSPS %PNBJO&SSPS
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ͯ͠ճ෮ॲཧΛ͢Δ
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
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
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ܕͷͱ͖ʹ ಛผͳΤϥʔΛฦ͢
͋ͱPresentationErrorͷܕ ΛݟͯݸผͷॲཧΛ͢Ε
*OGSB 1SFTFOUBUJPO %PNBJO $POOFDUJPO 4FSWFS&SSPS -PHJD 5SBOTMBUJPO 6OBVUIPSJ[FE "MFSU'BMMCBDL "MFSU3FUSZ
Each Error, Each Process
·ͱΊ • Layered Architecture x RxSwiftͷΤϥʔ ൖʹ͍ͭͯͷҰྫΛߟ͑ͨ • catchErrorerrorΛฦͣ͞ճ෮ॲཧॻ͚ ΔͷͰҟৗܥ͔Βਖ਼ৗܥʹΔ͜ͱՄೳ