Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

MCE^3 - Jorge D. Ortiz - Fuentes - Escape From Mars

131 views

Published on

Everybody involved in a mid size project or bigger is concerned about architecture. We have all been told that a good architecture can help us to have a more agile, robust, and easier to work with application, but it is not always clear how nor the architecture everybody else is talking about. By establishing parallelisms with Andy Weir's story, The Martian, I will go through the most relevant problems we usually find, explain how a well though out architecture can be valuable to us, and share some code that implements it.
I will use Swift in all of the code examples, because, in my opinion, it is very well suited to implement those advanced architectures. I will highlight its advantages and disadvantages compared Objective-C and other languages from an architectural point of view.
If you care:- The talk includes only minor spoilers- No, it isn't about MVC, but beyond that

Published in: Technology
  • Be the first to comment

  • Be the first to like this

MCE^3 - Jorge D. Ortiz - Fuentes - Escape From Mars

  1. 1. Jorge D. Ortiz-Fuentes @jdortiz Escape from Mars Thank your Architecture #SwiftMars
  2. 2. A Canonical Examples production #SwiftMars
  3. 3. #SwiftMars Agenda Learning from NASA SOLID Architecture Design patterns
  4. 4. Learning from NASA
  5. 5. Agility and the MVP
  6. 6. Always grow
  7. 7. NO SPoF
  8. 8. Know where problems come from
  9. 9. Last long
  10. 10. Teams can work together
  11. 11. Shit happens
  12. 12. Do you have any problems?
  13. 13. #SwiftMars Needs to Address Fast growth Robustness • testable • decoupled • debuggable (blame) Team collaboration Reusable Defer decisions Replaceable frameworks
  14. 14. There is a way: SOLID Principles
  15. 15. AKA Clean Architecture
  16. 16. Impossible to grow anything in Mars?
  17. 17. SOLID Architecture
  18. 18. App Architecture? View Controller View Controller View Controller View Controller System Frameworks
  19. 19. Architecture View Controller View Controller View Controller View Controller System Frameworks System Frameworks View Controller View ControllerView Controller ModelPresenterViewModel
  20. 20. Persistance FW View Presenter Entity Gateway Clean Architecture Interactor Entity Network LocationFW
  21. 21. Clean Architecture AppDelegate View (VC) Presenter Interactor Entity Gateway Connector
  22. 22. #SwiftMars Single Responsibility MVC is not enough More classes, but more cohesive: only one reason to change
  23. 23. #SwiftMars Business Logic extension ShowAllSpeakersInteractor: InteractorCommandProtocol { func execute() { let entities = entityGateway.fetchAllSpeakers() let displayData = entities.map({entity in return SpeakerDisplayData(speaker: entity)}) presenter?.presentAllSpeakers(displayData) } }
  24. 24. #SwiftMars Open Close Open to Extension, Closed to Modification
  25. 25. #SwiftMars Passive View class 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 } }
  26. 26. #SwiftMars Liskov Substitution It should be possible to use derived classes without special care
  27. 27. #SwiftMars Presentation class 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) } }
  28. 28. #SwiftMars Dependency Inversion The business case SHOULDN’T depend on the frameworks
  29. 29. #SwiftMars Deletion Use Case class 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) } }
  30. 30. #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
  31. 31. #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
  32. 32. Design Patterns
  33. 33. 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!
  34. 34. #SwiftMars Ready for Life class 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!
  35. 35. #SwiftMars Null Object class 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") }
  36. 36. #SwiftMars Null Object class 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()
  37. 37. Poor Template class 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")
  38. 38. Swifty Template protocol 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")
  39. 39. Next Steps
  40. 40. #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
  41. 41. canonicalexamples.com coupon: MCE316
  42. 42. Thank you!
  43. 43. @jdortiz #SwiftMars

×