Setting Boundaries

Setting Boundaries

Presented at ViDIA meetup.

675a0b0e911ee6c1c270a8d86a44e716?s=128

Francisco Díaz

March 10, 2016
Tweet

Transcript

  1. Setting Boundaries

  2. None
  3. Francisco Díaz @fco_diaz

  4. 3 iOS Devs 28 hours 1 project == Merge Conflicts

  5. What do we want? → Minimize duplication of code. →

    Develop independently without stepping on each other's toes.
  6. Feature verticals: → Big Panic button → Today widget →

    Knock
  7. Big Panic button:

  8. What needs to be done? → Create the button. →

    We need a way to create reports. → Make a backend call to save this information.
  9. Today widget:

  10. What needs to be done? → Create the extension button.

    → We need a way to create reports. → Make a backend call to save this information.
  11. What was it that we wanted? → Minimize duplication of

    code. → Develop independently without stepping on each other's toes.
  12. None
  13. Let's try again!

  14. → Create the button. → We need a way to

    create reports. → Make a backend call to save this information.
  15. UI / Presentation Create the button.

  16. Business logic We need a way to create reports.

  17. Backend connection Make a backend call to save this information.

  18. None
  19. To recap: → Minimize duplication of code. → Develop independently

    without stepping on each other's toes.
  20. We can solve any problem by introducing an extra level

    of indirection — David Wheeler
  21. Dependency inversion

  22. struct ModelDataManager { let APIClient: APIType init(APIClient: APIType) { self.APIClient

    = APIClient } }
  23. protocol APIType { func createReport(completion: JSONDictionary? -> Void) } struct

    API { private let manager: Alamofire.Manager init() { manager = Alamofire.Manager() } } extension API: APIType { func createReport(completion: JSONDictionary? -> Void) { manager.request(.POST, "https://some.com/api/report") .responseJSON { response in completion(response) } } }
  24. struct ModelDataManager { let APIClient: APIType init(API: APIType) { self.APIClient

    = API } static func defaultManager() -> ModelDataManager { let APIClient = API() return ModelDataManager(API: APIClient) } func createReport(completionHandler completion: Report? -> Void) { APIClient.createReport() { jsonDictionary in let report = ... // Parse jsonDictionary into Report completion(report) } } }
  25. Benefits → Testable. → Decoupled. → Easy to fake our

    networking layer.
  26. None
  27. struct FakeAPI: APIType { func createReport(completion: JSONDictionary? -> Void) {

    let dictionary = ["id": 12345] completion(dictionary) } }
  28. struct ModelDataManager { let APIClient: APIType init(API: APIType) { self.APIClient

    = API } static func defaultManager() -> ModelDataManager { // let APIClient = API() let APIClient = FakeAPI() return ModelDataManager(API: APIClient) } }
  29. Questions? Slides are available at: https://github.com/fdiaz/settings-boundaries-talk References: Architecture: The Lost

    Years The Clean Architecture