Top Banner
Jorge D. Ortiz-Fuentes @jdortiz Escape from Mars Thank your Architecture #SwiftMars
45

Escape from Mars

Jan 11, 2017

Download

Software

Jorge Ortiz
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Escape from Mars

Jorge D. Ortiz-Fuentes @jdortiz

Escape from Mars Thank your Architecture

#SwiftMars

Page 2: Escape from Mars

A Canonical Examples production

#SwiftMars

Page 3: Escape from Mars

#SwiftMars

Agenda

Learning from NASA

SOLID Architecture

Design patterns

Page 4: Escape from Mars

Learning from NASA

Page 5: Escape from Mars

Agility and the MVP

Page 6: Escape from Mars

Always grow

Page 7: Escape from Mars

NO SPoF

Page 8: Escape from Mars

Know where problems come from

Page 9: Escape from Mars

Last long

Page 10: Escape from Mars

Teams can work together

Page 11: Escape from Mars

Shit happens

Page 12: Escape from Mars

Do you have any problems?

Page 13: Escape from Mars

#SwiftMars

Needs to Address

Fast growth

Robustness

• testable

• decoupled

• debuggable (blame)

Team collaboration

Reusable

Defer decisions

Replaceable frameworks

Page 14: Escape from Mars

There is a way: SOLID Principles

Page 15: Escape from Mars

AKA Clean

Architecture

Page 16: Escape from Mars

Impossible to grow anything in Mars?

Page 17: Escape from Mars

SOLID Architecture

Page 18: Escape from Mars

App

Architecture?View Controller

View Controller

View Controller

View Controller

Sys

tem

Fram

ewor

ks

Page 19: Escape from Mars

ArchitectureView Controller

View Controller

View Controller

View Controller

Sys

tem

Fram

ewor

ks

System

Frameworks

View Controller

View ControllerView Controller ModelPresenterViewModel

Page 20: Escape from Mars

Persistance FW

View

Presenter

Entity Gateway

Clean Architecture

Interactor

Entity

Net

wor

k

Loca

tion

FW

Page 21: Escape from Mars

Clean ArchitectureAppDelegate

View (VC) Presenter Interactor Entity Gateway

Connector

Page 22: Escape from Mars

#SwiftMars

Single Responsibility

MVC is not enough

More classes, but more cohesive: only one reason to change

Page 23: Escape from Mars

#SwiftMars

Business Logicextension ShowAllSpeakersInteractor: InteractorCommandProtocol { func execute() { let entities = entityGateway.fetchAllSpeakers() let displayData = entities.map({entity in return SpeakerDisplayData(speaker: entity)}) presenter?.presentAllSpeakers(displayData) } }

Page 24: Escape from Mars

#SwiftMars

Open Close

Open to Extension, Closed to Modification

Page 25: Escape from Mars

#SwiftMars

Passive Viewclass SpeakersTableViewController: UITableViewController, SegueHandlerTypeProtocol {

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return numberOfRows }

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(SpeakersTableViewController.speakerCellIdentifier, forIndexPath: indexPath) as! SpeakerTableViewCell eventHandler?.presentCell(cell, indexPath: indexPath) return cell } }

Page 26: Escape from Mars

#SwiftMars

Liskov Substitution

It should be possible to use derived classes without special care

Page 27: Escape from Mars

#SwiftMars

Presentationclass SpeakersListsPresenter { weak var view: SpeakersListViewProtocol? let interactor: ShowAllSpeakersInteractor private var speakers: [SpeakerDisplayData]=[] }

extension SpeakersListsPresenter: SpeakersListPresenterProtocol { func presentAllSpeakers(speakers: [SpeakerDisplayData]) { view?.configureListWithNumberOfRows(speakers.count) self.speakers = speakers let addedIndexPaths = speakers.enumerate() .map({(index, _) in return NSIndexPath(forRow: index, inSection: 0)}) view?.addRowsAtIndexPaths(addedIndexPaths) } }

Page 28: Escape from Mars

#SwiftMars

Dependency Inversion

The business case SHOULDN’T depend on the frameworks

Page 29: Escape from Mars

#SwiftMars

Deletion Use Caseclass DeleteSpeakerInteractor { let entityGateway: EntityGatewayDeleteSpeakerProtocol var id: String?

init(entityGateway: EntityGatewayDeleteSpeakerProtocol) { self.entityGateway = entityGateway } }

extension DeleteSpeakerInteractor : InteractorCommandProtocol { func execute() { guard let id = self.id else { return } entityGateway.deleteSpeaker(id) } }

Page 30: Escape from Mars

#SwiftMars

Interface Segregation

Don’t force a class to depend on methods that it won’t use

One interactor will not likely use every functionality of the entity gateway

Page 31: Escape from Mars

#SwiftMars

class InMemorySpeakersRepo { }

extension InMemorySpeakersRepo: EntityGatewayFetchSpeakersProtocol { func fetchAllSpeakers() -> [Speaker] { … } }

extension InMemorySpeakersRepo: EntityGatewayCreateSpeakerProtocol { func createSpeaker(name name: String, title: String, synopsis: String, dateSubmitted: NSDate) { … } }

extension InMemorySpeakersRepo: EntityGatewayDeleteSpeakerProtocol { func deleteSpeaker(id: String) { … } }

Different Functions of the Entity Gateway

Page 32: Escape from Mars

Persistance FW

View

Presenter

Entity Gateway

Clean Architecture

Interactor

Entity

Net

wor

k

Loca

tion

FW

Page 33: Escape from Mars

Design Patterns

Page 34: Escape from Mars

Take me Outta Here

func presentCell(cell: SpeakerCellProtocol, indexPath: NSIndexPath) { let index = indexPath.row guard index < speakers.count else { return } let speaker = speakers[index] cell.displayName(speaker.name) cell.displayTitle(speaker.title) }

Know That!

Page 35: Escape from Mars

#SwiftMars

Ready for Lifeclass Houston { func launchSpaceship() throws { guard fuel >= 1.0 else { throw LaunchError.NoFuel } guard astronaut != "" else { throw LaunchError.NoAstronaut } guard spaceshipOK else { throw LaunchError.BrokenShip("Engine") } print("Launching spaceship") } } var control = Houston(fuel: 1.0, astronaut: nil, spaceshipOK: true) do { try control.launchSpaceship() } catch Houston.LaunchError.NoFuel { print("Adding fuel") } catch Houston.LaunchError.NoAstronaut { print("Next in line") } catch Houston.LaunchError.BrokenShip(let problem) { print(problem) } catch let unknowError { // }

Know That!

Page 36: Escape from Mars

#SwiftMars

Null Objectclass Sample { let identifier: String let biohazard: Bool func check() { let result = (biohazard ? "Care with sample \(identifier)" : "OK") print(result) } }

func fetchSample() -> Sample? { return nil }

if let sample = fetchSample() { sample.check() } else { print("OK") }

Page 37: Escape from Mars

#SwiftMars

Null Objectclass Sample { let identifier: String let biohazard: Bool /* … */ }

class NullSample: Sample { init() { super.init(identifier: "", biohazard: false) } override func check() { print("OK (empty)") } }

func fetchSample() -> Sample { return NullSample() }

let sample = fetchSample() sample.check()

Page 38: Escape from Mars

Poor Templateclass PoorAstronaut { func getIntoSpaceShip() { print("Commencing countdown engines on") }

func travelTo(destination: String) { fatalError() }

func comeBack() { print("Planet earth is blue") }

func performMissionTo(destination: String) { getIntoSpaceShip() travelTo(destination) comeBack() } }

let astronaut = PoorAstronaut() astronaut.performMissionTo("Moon")

Page 39: Escape from Mars

Swifty Templateprotocol Mission { func getIntoSpaceShip() func travelTo(destination: String) func comeBack() func performMissionTo(destination: String) }

extension Mission { func getIntoSpaceShip() { print("Commencing countdown engines on") } func comeBack() { print("Planet earth is blue") } func performMissionTo(destination: String) { getIntoSpaceShip() travelTo(destination) comeBack() } }

class Astronaut: Mission { func travelTo(destination: String) { print("I always wanted to visit \(destination)") } }

let markWatney = Astronaut() markWatney.performMissionTo("Mars")

Page 40: Escape from Mars

Next Steps

Page 41: Escape from Mars

#SwiftMars

Recommendations

Pay attention to your architecture; It always pays off

Use Principles to take decisions

Take advantage of the language and adapt the patterns to it

In case of doubt, ask for an architecture loan and ship it

Page 42: Escape from Mars

canonicalexamples.com coupon:

CODEMOTIONVIII

Page 43: Escape from Mars

Thank you!

Page 44: Escape from Mars

@jdortiz #SwiftMars

Page 45: Escape from Mars