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.

Protocol-Oriented Programming in Swift

472 views

Published on

Swift is not only a new programming language to develop software for all Apple products, but it brought a new approach to the iOS development as well. This report is about it. Less theory, maximum of examples.

Agenda:
1. Protocols in Swift vs Objective-C
2. Protocol-oriented programming approach.
3. Abstract example of POP approach
4. UIKit example of POP approach
5. Foundation example of POP approach.

Published in: Software
  • Be the first to comment

Protocol-Oriented Programming in Swift

  1. 1. Protocol-Oriented Programming in Swift Oleksandr Stepanov
  2. 2. Oleksandr Stepanov iOS developer @ AKQA Inc.
  3. 3. We are hiring!
  4. 4. Agenda
  5. 5. Agenda • Protocols in Swift vs Objective-C
  6. 6. Agenda • Protocols in Swift vs Objective-C • Protocol-oriented programming ‣ What is that? ‣ Why to use it? ‣ How to use it?
  7. 7. Agenda • Protocols in Swift vs Objective-C • Protocol-oriented programming ‣ What is that? ‣ Why to use it? ‣ How to use it? • Examples
  8. 8. Protocols
  9. 9. protocol someProtocol { }
  10. 10. protocol someProtocol { var someInt: Int { get } var someString: String? { get set } }
  11. 11. protocol someProtocol { var someInt: Int { get } var someString: String? { get set } func doSomething(inputA: Int) -> String? }
  12. 12. protocol someProtocol { associatedtype TypeA; var someInt: Int { get } var someString: String? { get set } func doSomething(inputA: Int) -> String? func doSomethingWithTypeA(typeA: TypeA) }
  13. 13. protocol someProtocol { associatedtype TypeA; var someInt: Int { get } var someString: String? { get set } func doSomething(inputA: Int) -> String? func doSomethingWithTypeA(typeA: TypeA) } protocol successorProtocol: someProtocol { }
  14. 14. … extension somethingProtocol { func doSomethingDifferent() { print("Oh man, that is different") } func doSomethingWithTypeA(typeA: TypeA) { print("typeA: (typeA)") } }
  15. 15. Protocols Swift Objective-C Protocol Inheritance ✅ ❌ Protocol extensions ✅ ❌ Default implementation ✅ ❌ Associated Types (aka Generics) ✅ ❌ Available in structures and enums as well ✅ ❌
  16. 16. Swift Objective-C Protocol Inheritance ✅ ❌ Protocol extensions ✅ ❌ Default implementation ✅ ❌ Associated Types (aka Generics) ✅ ❌ Available in structures and enums as well ✅ ❌ Optional methods ❌ ✅ Protocols
  17. 17. import Foundation @objc protocol optionalProtocol { @objc optional func someOptionalMethod() @objc optional var someOptionalInt: Int { get set } }
  18. 18. Swift Objective-C Protocol Inheritance ✅ ❌ Protocol extensions ✅ ❌ Default implementation ✅ ❌ Associated Types (aka Generics) ✅ ❌ Available in structures and enums as well ✅ ❌ Optional methods ✅ (@objc) ✅ Protocols
  19. 19. Protocol-oriented programming 🤔
  20. 20. Protocol-oriented programming What is this? 🤔
  21. 21. WWDC 2015 - Session 408 Protocol-Oriented Programming in Swift “Swift is a protocol-oriented programming language.” Dave Abrahams
  22. 22. WWDC 2015 - Session 408 Protocol-Oriented Programming in Swift “Swift is a protocol-oriented programming language.” Dave Abrahams https://developer.apple.com/videos/play/wwdc2015/408/ https://developer.apple.com/videos/play/wwdc2016/419/
  23. 23. Cars project 🚗
  24. 24. Implementation Inheritance approach
  25. 25. class Car { let wheels = 4 func make() { print("🚗 is built") } }
  26. 26. class Car { let wheels = 4 func make() { print("🚗 is built") } } class CarFactory { var model: Car? func makeACar() { model?.make() } }
  27. 27. … class Sedan: Car {} let sedan = Sedan() let carFactory = CarFactory() carFactory.model = sedan carFactory.makeACar() // prints “🚗 is built”
  28. 28. Let’s make 🏎
  29. 29. … class Bolide: Car { override func make() { print("🏎 is built") } } let bolide = Bolide() let bolideFactory = CarFactory() bolideFactory.model = bolide bolideFactory.makeACar() // prints "🏎 is built" Page 1 of 1
  30. 30. Let’s make 🏍
  31. 31. Implementation Inheritance problems
  32. 32. class CarFactory { var model: Car? func makeACar() { model?.make() } } Tight coupling Hard to maintain
  33. 33. Inheritance hierarchies Hard to extend class Car { let wheels = 4 func make() { print("🚗 is built") } } class Sedan: Car {}
  34. 34. Implementation is a white-box … even using proper encapsulation class Car { let wheels = 4 func make() { print("🚗 is built") } } class Sedan: Car {}
  35. 35. Protocol-oriented programming approach
  36. 36. ✦ Separation of public interface from the implementation
  37. 37. ✦ Separation of public interface from the implementation ✦ Software defined in components that talk to each other using interfaces
  38. 38. ✦ Separation of public interface from the implementation ✦ Software defined in components that talk to each other using interfaces ✦ May be used in conjunction with classes, structs and enums.
  39. 39. protocol Vehicle { func make() } protocol WheelsVehicle { var wheels: Int { get } }
  40. 40. … protocol FourWheelsVehicle: WheelsVehicle {} extension FourWheelsVehicle { var wheels: Int { get { return 4 } } }
  41. 41. … struct Car: Vehicle, FourWheelsVehicle { func make() { print("🚗 is built") } } } struct Bolide: Vehicle, FourWheelsVehicle { func make() { print("🏎 is built") } }
  42. 42. … struct Car: Vehicle, FourWheelsVehicle { func make() { print("🚗 is built") } } } struct Bolide: Vehicle, FourWheelsVehicle { func make() { print("🏎 is built") } }
  43. 43. … struct Car: Vehicle, FourWheelsVehicle { func make() { print("🚗 is built") } } } struct Bolide: Vehicle, FourWheelsVehicle { func make() { print("🏎 is built") } }
  44. 44. … protocol TwoWheelsVehicle: WheelsVehicle {} extension TwoWheelsVehicle { var wheels: Int { get { return 2 } } } struct MotorBike: Vehicle, TwoWheelsVehicle { func make() { print("🏍 is built") } } }
  45. 45. … protocol VehicleFactory { var model: Vehicle? { get set } func makeACar() } extension VehicleFactory { func makeACar() { model?.make() } }
  46. 46. … extension VehicleFactory { func repairACar() { // ... } }
  47. 47. … class CarFactory: VehicleFactory { var model: Vehicle? } let bolide = Bolide() let carFactory = CarFactory() carFactory.model = bolide carFactory.makeACar() // prints "🏎 is built"
  48. 48. ✦ Reusability
  49. 49. ✦ Reusability ✦ Extensibility
  50. 50. ✦ Reusability ✦ Extensibility ✦ Black-boxed
  51. 51. ✦ Reusability ✦ Extensibility ✦ Black-boxed MORE MAINTAINABLE
  52. 52. Patterns where it can be useful
  53. 53. ✦ Data types • Abstraction • Mock objects for test
  54. 54. ✦ Data types • Abstraction • Mock objects for test ✦ Dependency injection
  55. 55. ✦ Data types • Abstraction • Mock objects for test ✦ Dependency injection ✦ Detached architecture • MVVM
  56. 56. ✦ Data types • Abstraction • Mock objects for test ✦ Dependency injection ✦ Detached architecture • MVVM ✦ Testing • Unit • A/B testing interfaces
  57. 57. Real life example
  58. 58. Real life example UIKit
  59. 59. Table view cell
  60. 60. import UIKit struct Event { } class EventTableViewCell: UITableViewCell { }
  61. 61. import UIKit struct Event { let icon: UIImage? let title: String let date: Date } class EventTableViewCell: UITableViewCell { @IBOutlet var iconView: UIImageView! @IBOutlet var titleLabel: UILabel! @IBOutlet var dateLabel: UILabel! }
  62. 62. import UIKit struct Event { let icon: UIImage? let title: String let date: Date } class EventTableViewCell: UITableViewCell { @IBOutlet var iconView: UIImageView! @IBOutlet var titleLabel: UILabel! @IBOutlet var dateLabel: UILabel! func set(event: Event) { iconView.image = event.icon titleLabel.text = event.title dateLabel.text = event.date.description } }
  63. 63. Collection view cell
  64. 64. … class EventTableViewCell: UITableViewCell { … func set(event: Event) { iconView.image = event.icon titleLabel.text = event.title dateLabel.text = event.date.description } } class EventCollectionViewCell: UICollectionViewCell { … func set(event: Event) { iconView.image = event.icon titleLabel.text = event.title dateLabel.text = event.date.description } }
  65. 65. Header view
  66. 66. … class EventTableViewCell: UITableViewCell { … func set(event: Event) { iconView.image = event.icon titleLabel.text = event.title dateLabel.text = event.date.description } } class EventCollectionViewCell: UICollectionViewCell { … func set(event: Event) { iconView.image = event.icon titleLabel.text = event.title dateLabel.text = event.date.description } } class EventHeaderView: UIView { … func set(event: Event) { iconView.image = event.icon titleLabel.text = event.title dateLabel.text = event.date.description } }
  67. 67. Maintenance
  68. 68. Maintenance 😢
  69. 69. POP approach
  70. 70. protocol EventViewProtocol { var iconView: UIImageView! { get set } var titleLabel: UILabel! { get set } var dateLabel: UILabel! { get set } func set(event: Event) }
  71. 71. protocol EventViewProtocol { var iconView: UIImageView! { get set } var titleLabel: UILabel! { get set } var dateLabel: UILabel! { get set } func set(event: Event) } extension EventViewProtocol { func set(event: Event) { iconView.image = event.icon titleLabel.text = event.title dateLabel.text = event.date.description } }
  72. 72. … class EventTableViewCell: UITableViewCell { @IBOutlet var iconView: UIImageView! @IBOutlet var titleLabel: UILabel! @IBOutlet var dateLabel: UILabel! } extension EventTableViewCell: EventViewProtocol {}
  73. 73. Test it! 🔨
  74. 74. … import XCTest class TestView { var iconView: UIImageView! = UIImageView() var titleLabel: UILabel! = UILabel() var dateLabel: UILabel! = UILabel() } extension TestView: EventViewProtocol {}
  75. 75. … let eventDate = Date.init() let event = Event.init(icon: UIImage.init(named: “testEventIcon”) title: "event title", date: eventDate) let testView = TestView() testView.set(event: event)
  76. 76. … let eventDate = Date.init() let event = Event.init(icon: UIImage.init(named: “testEventIcon”) title: "event title", date: eventDate) let testView = TestView() testView.set(event: event) XCTAssertEqual ( testView.iconView.image, UIImage.init(named:”testEventIcon”) ) XCTAssertEqual ( testView.titleLabel.text, "event title” ) XCTAssertEqual ( testView.dateLabel.text, eventDate.description )
  77. 77. ✦ No code duplication -> better maintainable
  78. 78. ✦ No code duplication -> better maintainable ✦ Better testable
  79. 79. ✦ No code duplication -> better maintainable ✦ Better testable PROFIT!
  80. 80. One more sample POP + Enums
  81. 81. One more sample POP + Enums NSNotification
  82. 82. -Literal string names
  83. 83. -Literal string names -Potential for mismatched strings
  84. 84. -Literal string names -Potential for mismatched strings -There must be a better approach
  85. 85. -Slightly better …
  86. 86. -Slightly better … -… but can we do even better?
  87. 87. }
  88. 88. }
  89. 89. }
  90. 90. How to enhance it with POP ? }
  91. 91.
  92. 92. ✦ No mismatched strings
  93. 93. ✦ No mismatched strings ✦Simpler to read and maintain
  94. 94. ✦ No mismatched strings ✦Simpler to read and maintain ✦ Notification handlers may be classes, structs and enums
  95. 95. ✦ No mismatched strings ✦Simpler to read and maintain ✦ Notification handlers may be classes, structs and enums ✦ … the same for notification type
  96. 96. reusability
  97. 97. reusability extensibility
  98. 98. understandability reusability extensibility
  99. 99. maintainability understandability reusability extensibility
  100. 100. maintainability understandability testability reusability extensibility
  101. 101. POP maintainability understandability testability reusability extensibility
  102. 102. it’s not a
  103. 103. it’s not a
  104. 104. treat it carefully
  105. 105. Thank you!
  106. 106. Q&A

×