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
700
スマートコントラクトのデプロイって何だろう
ngo275
0
890
プロトタイピングするならFirebaseを使ってみよう
ngo275
0
1.9k
Ethereumで開発を始めるなら知っておきたいこと
ngo275
10
5.3k
スマートコントラクトをHTTPで実行する
ngo275
0
170
EOSでスマートコントラクトを実行してみる
ngo275
0
1.2k
iOSアプリエンジニアがReact Nativeを使ってみて
ngo275
0
300
中東のシリコンバレーことイスラエルに行ってきた
ngo275
0
170
Other Decks in Programming
See All in Programming
GDG Korea Android: 2026 I/O Extended ~ What's new in Android development tools
pluu
0
220
今さら聞けない .NET CLI
htkym
0
180
わからない話を追いかけたら、プログラミング言語を作る側にいた
ydah
3
470
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
440
<title><a id="</title>君はこのHTMLをパースできるか"></a></title> #雑LT_study
pizzacat83
0
140
AIが無かった頃の素敵な出会いの話
codmoninc
1
390
React本体のコードリーディング
high_g_engineer
1
140
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
540
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
1
250
OpenSpecのproposalにbrainstormingを持たせてみた
tigertora7571
1
200
VibeCodingからAgenticWorkflowへ
starfish719
0
310
『コードを書く以外の』エンジニアリング〜課金基盤移行プロジェクト推進のためのTips4選
yuriko1211
0
580
Featured
See All Featured
Practical Orchestrator
shlominoach
191
12k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
460
Facilitating Awesome Meetings
lara
57
7.1k
GitHub's CSS Performance
jonrohan
1033
470k
How to Ace a Technical Interview
jacobian
281
24k
Odyssey Design
rkendrick25
PRO
2
750
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
350
RailsConf 2023
tenderlove
30
1.5k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
460
New Earth Scene 8
popppiees
3
2.5k
[SF Ruby Conf 2025] Rails X
palkan
2
1.2k
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