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
Clean Swift
Search
Yoann Coldefy
October 01, 2016
Programming
360
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Clean Swift
iOSでクリーンアーキテクチャー
Yoann Coldefy
October 01, 2016
More Decks by Yoann Coldefy
See All by Yoann Coldefy
ViewControllerの単体テスト
luinily
1
300
Other Decks in Programming
See All in Programming
Oxcを導入して開発体験が向上した話
yug1224
4
290
AI時代のUIはどこへ行く?その2!
yusukebe
19
6.7k
tsserverとは何だったのか、これからどうなるのか
nowaki28
1
450
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
110
関係性から理解する"同一性"の型用語たち
pvcresin
2
640
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
4.1k
Swiftのレキシカルスコープ管理
kntkymt
0
210
ふつうのFeature Flag実践入門
irof
7
3.6k
CSC307 Lecture 17
javiergs
PRO
0
310
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
140
権限チェックの一貫性を型で守る TypeScript による多層防御
mnch
4
1.1k
プロパティの順序で型推論が壊れる!? TypeScript6.0の修正からContext-Sensitivityの仕組みを追う
bicstone
2
1.3k
Featured
See All Featured
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.3k
Abbi's Birthday
coloredviolet
2
7.9k
Designing Powerful Visuals for Engaging Learning
tmiket
1
400
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
250
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.3k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
590
GraphQLとの向き合い方2022年版
quramy
50
15k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
200
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
ラッコキーワード サービス紹介資料
rakko
1
3.5M
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Paper Plane (Part 1)
katiecoart
PRO
0
8.5k
Transcript
Clean Swift
ࣗݾհ • ໊લɿίʔυώʔϤΞϯ • ग़ɿGrenoble • ৬ۀɿιϑτΤΞʔΤϯδχΞʔ • ։ൃܦݧɿDelphiʢ7ʣɺSwiftʢʣ •
Facebookɿhttps://www.facebook.com/yoann.coldefy • Twitterɿ@luinily
• View Controllerେ͖͘ͳΔ • View Controller͕ෳࡶʹͳΔ • อक͠ʹ͍͘ • ༷มߋʹରԠ͠ʹ͍͘
• ΫϦʔϯߏ • Λ͚Δ • ґଘΛੵۃతʹ͑Δ
• ୯ମςετ • ςετۦಈͰࣗવʹมߋ͍͢͠ߏங • ϦϑΝΫτϦϯάͯ҆͠৺
iOSͰͲ͏͢Ε͍͍ʁ
View Controller Interactor Presenter VIP cycle
View Controller Interactor Presenter VIP cycle Viewͷίϯτϩʔϧ
View Controller Interactor Presenter VIP cycle ϞσϧͱͷΓͱΓ
View Controller Interactor Presenter VIP cycle දࣔ༻ͷσʔλΛܗ
View Controller Interactor Presenter VIP cycle
Input protocol Output protocol Data Data Data Data
View Controller View Model Request View
class ApodViewController: UIViewController { var output: ApodViewControllerOutput! }
class ApodViewControllerTests { override func setUp() { super.setUp() window =
UIWindow() setupApodViewController() outputSpy = MockApodViewControllerOutput() target.output = outputSpy } func test_viewDidLoad_fetchTodaysApodIsCalled() { // Arrange // Act loadView() // Assert XCTAssertTrue(outputSpy.fetchTodayApodCalled) } }
class ApodViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() fetchTodaysApod()
} func fetchTodaysApod() { let request = TodayApodRequest() output.fetchTodayApod(request: request) } }
Interactor Worker Worker Worker Request Response Business Logic
class ApodInteractor: ApodInteractorInput { var output: ApodInteractorOutput! private var
_apodWorker: ApodWorker }
func test_fetchTodayApod_callsApodWorkerFetchTodayApod() { // Arrange let request = TodayApodRequest()
// Act target.fetchTodayApod(request: request) // Assert XCTAssertTrue(mochApodWorker.fetchTodayApodCalled) } func test_fetchTodayApod_callsOutputPresentApod() { // Arrange let request = TodayApodRequest() // Act target.fetchTodayApod(request: request) // Assert XCTAssertTrue(mochOutput.presentOutputCalled) }
class ApodInteractor: ApodInteractorInput { func fetchTodayApod(request: TodayApodRequest) { _apodWorker.fetchTodayAPOD()
{ apodData, error in let response = ApodResponse(apodData: apodData) self.output.presentApod(response: response) } } }
Presenter Response View Model
class ApodPresenter: ApodPresenterInput { weak var output: ApodPresenterOutput! }
func test_presentApod_callsDisplayAPOD() func test_presentApod_viewModelContainsTitle() func test_presentApod_viewModelContainsFormatedDate() { {…} //
Assert XCTAssertEqual(mockOutput.apodViewModel?.date, "201607݄18") }
class ApodPresenter: ApodPresenterInput { func presentApod(response: ApodResponse) { let
apodViewModel = makeApodViewModel(apodData: response.apodData) output.displayApod(viewModel: apodViewModel) } private func makeApodViewModel(apodData: ApodData) -> ApodDataViewModel { let title = apodData.title let date = dateToString(date: apodData.date) let explanation = apodData.explanation let copyright = apodData.copyright return ApodDataViewModel(title: title, date: date, explanation: explanation, copyright: copyright) } }
View Controller View Model Request View
func test_displayApod_TitleIsDisplayed() { // Arrange loadView() let viewModel =
prepareViewModel() // Act target.displayApod(viewModel: viewModel) // Assert XCTAssertEqual(target.titleLabel.text, viewModel.title) }
extension ApodViewController: ApodViewControllerInput { func displayApod(viewModel: ApodDataViewModel) { titleLabel.text
= viewModel.title explanationTextView.text = viewModel.explanation } }
• InteractorɺPresenterͳͲͷઃఆͱ݁ͼ͚ͭ class ApodConfigurator { func configure(viewController: ApodViewController) { let
router = ApodRouter() router.viewController = viewController let presenter = ApodPresenter() presenter.output = viewController let interactor = configureInteractor(presenter: presenter) viewController.output = interactor viewController.router = router } }
protocol ApodViewControllerOutput { func fetchTodayApod(request: TodayApodRequest) func fetchRandomApod(request: RandomApodRequest)
} protocol ApodInteractorInput { func fetchTodayApod(request: TodayApodRequest) func fetchRandomApod(request: RandomApodRequest) }
extension ApodInteractor: ApodViewControllerOutput { }
·ͱΊ • ςετۦಈ։ൃ͕Ͱ͖Δ • σΟάϨʔυ͠ʹ͍͘ • ֤Ϋϥεͷ͕͖ͬΓ͍ͯ͠ΔͷͰɺό άमਖ਼มߋ͕͍͢͠
• Ϋϥεؒͷґଘੑ͕͍ͨΊɺผͷΫϥ ε͕ೖΓม͍͑͢ • View ControllerϏϡʔͷ੍ޚͱೖྗؔ ͷίʔυ͔͠ͳ͍
• ίʔυ͕݁ߏ૿͑ͯ͠·͍·͢ • ςετॻ͘ͷͰɺඞཁ࣌ؒ૿͑·͢ • ࠷ॳϋʔυϧ͕ͪΐͬͱߴΊ
http://clean-swift.com https://github.com/luinily/spaceApp http://qiita.com/takahia/items/67b9e1229682127d924e