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
ペイモのアーキテクチャ
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Shuichi Nagao
February 19, 2018
Programming
720
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ペイモのアーキテクチャ
割り勘アプリのアーキテクチャについての発表です。
Shuichi Nagao
February 19, 2018
More Decks by Shuichi Nagao
See All by Shuichi Nagao
UX for Key Management
ngo275
0
140
深センではテクノロジーを使う人がイノベーションを起こしている
ngo275
0
680
スマートコントラクトのデプロイって何だろう
ngo275
0
880
プロトタイピングするならFirebaseを使ってみよう
ngo275
0
1.9k
Ethereumで開発を始めるなら知っておきたいこと
ngo275
10
5.2k
スマートコントラクトをHTTPで実行する
ngo275
0
160
EOSでスマートコントラクトを実行してみる
ngo275
0
1.2k
iOSアプリエンジニアがReact Nativeを使ってみて
ngo275
0
300
中東のシリコンバレーことイスラエルに行ってきた
ngo275
0
160
Other Decks in Programming
See All in Programming
ふつうのFeature Flag実践入門
irof
7
4k
net-httpのHTTP/2対応について
naruse
0
490
AIだと陥りがちなJakarta EE最新技術への移行時の落とし穴と解決策
tnagao7
0
110
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
ユニットテストの先へ:テスト技法で要求・仕様を整理するJava開発実践 / Beyond_Unit_Testing_Practical_Java_Development_Techniques_for_Organizing_Requirements_and_Specifications
shimashima35
0
410
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
340
Oxcを導入して開発体験が向上した話
yug1224
4
320
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
12k
dRuby over BLE
makicamel
2
340
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
4.1k
セキュリティの専門家じゃなくてもできる。「セキュリティ意識」をアップデートして サプライチェーン攻撃への耐性を高めよう。
tk3fftk
5
770
そのテスト、説明できますか?~LWテスト戦略FW~のご紹介
nakahara
0
130
Featured
See All Featured
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
300
How to Think Like a Performance Engineer
csswizardry
28
2.7k
Google's AI Overviews - The New Search
badams
0
1k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.9k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
1.1k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
120k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
840
Evolving SEO for Evolving Search Engines
ryanjones
0
220
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.5k
First, design no harm
axbom
PRO
2
1.2k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
190
Transcript
ϖΠϞͷΞʔΩςΫνϟ @NGO275 1
AGENDA ࠓ͢͜ͱ ▸ ΫϦʔϯΞʔΩςΫνϟͱ ▸ ϖΠϞͷΞʔΩςΫνϟ֓؍ ▸ ϖΠϞͷ࣮ࡍͷϦϑΝΫλྫ ▸ ·ͱΊ
2
WHAT IS CLEAN ARCHITECTURE? ΫϦʔϯΞʔΩςΫνϟͱ 3
WHAT IS CLEAN ARCHITECTURE? ΞϓϦ։ൃ͋Δ͋Δ ▸ ϏδωεϩδοΫ͕ͩΜͩΜΘ͔Βͳ͘ͳΔ ▸ ೖग़ྗͷॲཧ͕ࢄࡒͯ͠ॲཧΛ͏ͷ͕େมʹͳΔ ▸
ঢ়ଶΛ࣋ͭͷ͕૿Ճͯ͠෭࡞༻Λଟ͘ੜΜͰ͠·͏ 4
WHAT IS CLEAN ARCHITECTURE? ղܾ͍ͨ͜͠ͱ ▸ ϏδωεϩδοΫΛ໌֬ʹ͍ͨ͠ ▸ ϑϨʔϜϫʔΫ͔Βಠཱ͢Δ ▸
ϏδωεϩδοΫετΞ͔Βಠཱ͢Δ ▸ ϏδωεϩδοΫUI͔Βಠཱ͢Δ ▸ ϏδωεϩδοΫΛςετ͘͢͠Δ 5
WHAT IS CLEAN ARCHITECTURE? ղܾํ๏ Πϝʔδਤ https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html 6
PAYMO ARCHITECTURE ϖΠϞͷΞʔΩςΫνϟ֓؍ 7
PAYMO ARCHITECTURE ϦϦʔεॳͷϖΠϞͷΞʔΩςΫνϟΠϝʔδ ▸ View͕Ͱ͔͘ɺPresenterͱUseCase΄΅ۭͬΆ ▸ DataStore͕গʑେ͖͍ ▸ ϩδοΫ͕ViewDataStoreʹॻ͍ͯ͋ͬͨ ▸
1݄ࠒ 8
PAYMO ARCHITECTURE ϦϦʔεॳͷϖΠϞͷΞʔΩςΫνϟΠϝʔδ ▸ View͕Ͱ͔͘ɺPresenterͱUseCase΄΅ۭͬΆ ▸ DataStore͕গʑେ͖͍ ▸ ϩδοΫ͕ViewDataStoreʹॻ͍ͯ͋ͬͨ ▸
1݄ࠒ 9
PAYMO ARCHITECTURE վળޙͷϖΠϞͷΞʔΩςΫνϟΠϝʔδᶃ ▸ PresenterʹUIϩδοΫҠߦ ▸ 7݄ࠒ 10
PAYMO ARCHITECTURE վળޙͷϖΠϞͷΞʔΩςΫνϟΠϝʔδᶃ ▸ PresenterʹUIϩδοΫҠߦ ▸ 7݄ࠒ 11
PAYMO ARCHITECTURE վળޙͷϖΠϞͷΞʔΩςΫνϟΠϝʔδᶄ ▸ ϏδωεϩδοΫΛUseCaseʹҠߦ ▸ 10݄ࠒ 12
PAYMO ARCHITECTURE վળޙͷϖΠϞͷΞʔΩςΫνϟΠϝʔδᶄ ▸ ϏδωεϩδοΫΛUseCaseʹҠߦ ▸ 10݄ࠒ 13
PAYMO REFACTORING ϖΠϞͷ࣮ࡍͷϦϑΝΫλྫ 14
TIMELINE ’S VIEWCONTROLLER REFACTORING func displayShiharaiItem(item: ShiharaiItem, indexPath: IndexPath) ->
TimelineTableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier, for: indexPath) as! TimelineTableViewCell let name: String guard let date = item.createdAt else { return cell } switch item.status { case .accepted: if (ࢧ͍͕ࣗ) { // ඳըͷͨΊͷॲཧ } else { // ඳըͷͨΊͷॲཧ } cell.mainLabel.attributedText = … case .rejected: if (ࢧ͍͕ࣗ) { if item.merchant == nil{ // ඳըͷͨΊͷॲཧ } else { // ඳըͷͨΊͷॲཧ } } else { // ඳըͷͨΊͷॲཧ } // ඳըͷͨΊͷॲཧ case .requested: if (ࢧ͍͕ࣗ) { if (݅1) { // ඳըͷͨΊͷॲཧ } else { // ඳըͷͨΊͷॲཧ } } else { // ඳըͷͨΊͷॲཧ } // ඳըͷͨΊͷॲཧ case .unknown: return cell } // ඳըͷͨΊͷॲཧ return cell } 15
TIMELINE ’S VIEWCONTROLLER REFACTORING func displayShiharaiItem(item: ShiharaiItem, indexPath: IndexPath) ->
TimelineTableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier, for: indexPath) as! TimelineTableViewCell let name: String guard let date = item.createdAt else { return cell } switch item.status { case .accepted: if (ࢧ͍͕ࣗ) { // ඳըͷͨΊͷॲཧ } else { // ඳըͷͨΊͷॲཧ } cell.mainLabel.attributedText = … case .rejected: if (ࢧ͍͕ࣗ) { if item.merchant == nil{ // ඳըͷͨΊͷॲཧ } else { // ඳըͷͨΊͷॲཧ } } else { // ඳըͷͨΊͷॲཧ } // ඳըͷͨΊͷॲཧ case .requested: if (ࢧ͍͕ࣗ) { if (݅1) { // ඳըͷͨΊͷॲཧ } else { // ඳըͷͨΊͷॲཧ } } else { // ඳըͷͨΊͷॲཧ } // ඳըͷͨΊͷॲཧ case .unknown: return cell } // ඳըͷͨΊͷॲཧ return cell } ViewControllerͳͷʹෳࡶͳذΛ͍ͯ͠Δ 16
TIMELINE ’S VIEWCONTROLLER REFACTORING ▸ ViewControllerͷ͋Δ1ͭͷϝιουͰλΠϜϥΠϯCellͷ ذͱඳը͢ΔใΛ٧ΊࠐΜͰ͍ͨ ղܾํ๏ ▸
ViewControllerͰPresenter͔ΒݴΘΕͨඳըʹઐ೦ ▸ λΠϜϥΠϯCellͷذϩδοΫ͚ͩͷϝιουΛPresenter ʹੜ͢ ▸ ͜ͷλΠϓͷCell͜ΕΛඳը͢Δɺͱ͍͏ϝιουΛੜ ͢(͜͜ͰCellʹੜͨ͠) 17
TIMELINE ’S VIEWCONTROLLER REFACTORING // ViewController override func tableView(_ tableView:
UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let item = getTimelineItem(indexPath: indexPath) else { return UITableViewCell() } guard let cellInfo = getTimelineCellInfo(indexPath: indexPath) else { return UITableViewCell() } return getCell(tableView, indexPath: indexPath, item: item, cellInfo: cellInfo) } // Presenter func getTimelineCellInfo(_ item: TimelineItem) -> TimelineCellInfo? { switch item { case let (ٻobject) as (ٻobject): switch (ٻobject).status { case .accepted: return TimelineCellInfo(type: .accepted(ٻobject)) case .requested: return TimelineCellInfo(type: .requested(ٻobject)) case .rejected: return TimelineCellInfo(type: .rejected(ٻobject)) default: return nil } case let (ࢧ͍object) as (ࢧ͍object): if (݅1) { switch (ࢧ͍object).status { case .accepted: return TimelineCellInfo(type: .accepted(ࢧ͍object)) case .requested: return TimelineCellInfo(type: .requested(ࢧ͍object)) case .rejected: return TimelineCellInfo(type: .rejected(ࢧ͍object)) default: return nil } } else if (݅2) { guard let subject = .. else { return nil } guard let secondarySubject = .. else { return nil } return TimelineCellInfo(type: .(ࢧ͍objectλΠϓ1), subject: subject, secondarySubject: secondarySubject) } else { if (݅a) { if let subject = .., let secondarySubject = .. { return TimelineCellInfo(type: .(ࢧ͍objectλΠϓ1), subject: subject, secondarySubject: secondarySubject) } } else if (݅b) { if let .. { return TimelineCellInfo(type: .(ࢧ͍objectλΠϓ2), subject: subject) } } else if (݅c) { if let .. { return TimelineCellInfo(type: .(ࢧ͍objectλΠϓ2), subject: subject) } } } case _ as ..: return TimelineCellInfo(type: .fuga) VC Presenter 18
TIMELINE ’S VIEWCONTROLLER REFACTORING // ViewController override func tableView(_ tableView:
UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let item = getTimelineItem(indexPath: indexPath) else { return UITableViewCell() } guard let cellInfo = getTimelineCellInfo(indexPath: indexPath) else { return UITableViewCell() } return getCell(tableView, indexPath: indexPath, item: item, cellInfo: cellInfo) } // Presenter func getTimelineCellInfo(_ item: TimelineItem) -> TimelineCellInfo? { switch item { case let (ٻobject) as (ٻobject): switch (ٻobject).status { case .accepted: return TimelineCellInfo(type: .accepted(ٻobject)) case .requested: return TimelineCellInfo(type: .requested(ٻobject)) case .rejected: return TimelineCellInfo(type: .rejected(ٻobject)) default: return nil } case let (ࢧ͍object) as (ࢧ͍object): if (݅1) { switch (ࢧ͍object).status { case .accepted: return TimelineCellInfo(type: .accepted(ࢧ͍object)) case .requested: return TimelineCellInfo(type: .requested(ࢧ͍object)) case .rejected: return TimelineCellInfo(type: .rejected(ࢧ͍object)) default: return nil } } else if (݅2) { guard let subject = .. else { return nil } guard let secondarySubject = .. else { return nil } return TimelineCellInfo(type: .(ࢧ͍objectλΠϓ1), subject: subject, secondarySubject: secondarySubject) } else { if (݅a) { if let subject = .., let secondarySubject = .. { return TimelineCellInfo(type: .(ࢧ͍objectλΠϓ1), subject: subject, secondarySubject: secondarySubject) } } else if (݅b) { if let .. { return TimelineCellInfo(type: .(ࢧ͍objectλΠϓ2), subject: subject) } } else if (݅c) { if let .. { return TimelineCellInfo(type: .(ࢧ͍objectλΠϓ2), subject: subject) } } } case _ as ..: return TimelineCellInfo(type: .fuga) VC Presenter ViewController΄ͱΜͲԿ͠ͳ͍ PresenterʹUIϩδοΫΛ·ͱΊͨͷͰςετॻ͖͍͢ 19
CONCLUSION ·ͱΊ ▸ ߏΫϦʔϯΞʔΩςΫνϟ͕ͩɺΛΓ͚Δաఔ Ͱਖ਼͘͠ఆٛ͠ͳ͍ͱബͬΒ͍͕ੜ·Εͯ͠·͏ ▸ ViewController -> Presenter ->
UseCase ͱϩδοΫΛΓ ͚͍ͯͬͨ ▸ ͦ͏͢Δ͜ͱͰϢχοτςετ͕ॻ͔Ε͍ͯͬͨ 20