Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
AKIBA.swift: Layered ArchitectureにおけるRxSwiftを用い...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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.5k
iOSDC 20190906: 動画アプリの投げ銭機能における 消耗型課金の仕組みと実装 with 発表ノート
nonchalant
2
650
Sign In with Apple
nonchalant
1
2.5k
iOSDC RejectCon 20180915: Factoryの自動生成によりテストを書きやすくする
nonchalant
1
770
iOSDC 20180902: 小さくはじめる端末管理
nonchalant
2
1.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
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
SFCで実現する病院・医療システムの動的組み立て式UI
koukimiura
1
120
Domain-Driven Transformation
hschwentner
2
2.3k
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
1
1.8k
React Native에 현대적인 빌드 도구 더하기: Rollipop 구현기
leegeunhyeok
0
150
npm との違いを手がかりにGo の依存管理を理解したい
optim
0
1.1k
Compiling a real-world CLI tool to native with Static Hermes
tmikov2023
0
130
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
210
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
160
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
1.2k
AIがコードを書いてくれる時代、我々は何を確かめるのか
yosuke_furukawa
PRO
12
4.3k
Railsバージョンを4倍にした話
optim
0
720
Featured
See All Featured
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
560
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
530
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
290
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.3k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
340
Tell your own story through comics
letsgokoyo
1
1.1k
The untapped power of vector embeddings
frankvandijk
2
2k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Chasing Engaging Ingredients in Design
codingconduct
0
370
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
310
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Λฦͣ͞ճ෮ॲཧॻ͚ ΔͷͰҟৗܥ͔Βਖ਼ৗܥʹΔ͜ͱՄೳ