Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

0

Partager

Télécharger pour lire hors ligne

Best Practices

Télécharger pour lire hors ligne

Slides for a talk on best practices in Swift delivered at SwiftConf 2019

Livres associés

Gratuit avec un essai de 30 jours de Scribd

Tout voir
  • Soyez le premier à aimer ceci

Best Practices

  1. 1. Best Practices
  2. 2. Swift BestPractices
  3. 3. 📅 - Journey through 7 Best Practices - The Bigger Picture
  4. 4. ⚠ Opinions ⚠
  5. 5. 7 Best Practices
  6. 6. 1. Never force unwrap
  7. 7. Banned by many style guides
  8. 8. Unwrap an optional that should never be nil
  9. 9. Undefined state Nil auth token Failure to load payment data Data Corruption
  10. 10. print(token!)
  11. 11. guard let token = token else { fatalError(“You must supply a token”) } print(token)
  12. 12. let number = number !! "Number should never be nil"
  13. 13. What if you can’t provide a good error message?
  14. 14. guard let number = number else { fatalError("Number should never be nil") } Vs number!
  15. 15. 1. Never force unwrap
  16. 16. 1. Never force unwrap when you can provide a useful error message
  17. 17. let url = URL(string: “http://www.google.com”) let image = UIImage(named: “icon")
  18. 18. The developer made a typo
  19. 19. let url = URL(string: “http://www.google.com”) let image = UIImage(named: “icon")
  20. 20. Validate with test or script let url = URL(string: “http://www.google.com”)! let image = UIImage(named: “icon”)!
  21. 21. 1. Never force unwrap when you can provide a useful error message
  22. 22. 1. Never force unwrap when you can provide a useful error message or its not a static developer typo
  23. 23. 2. Document all public methods
  24. 24. Documentation = 💯
  25. 25. Is your documentation actually useful?
  26. 26. /// Create item /// /// - Parameters: /// - author: The item's author /// - title: The item's title /// - length: The item's length func createItem(author: String, title: String, length: TimeInterval) { }
  27. 27. 2. Document all public methods
  28. 28. 2. Document all public methods if the documentation adds value
  29. 29. 3. Aim for high unit test code coverage.
  30. 30. Unit tests = 💯
  31. 31. Are your tests actually useful?
  32. 32. func testConstructor() { let viewController = factory.makeViewContoller() XCTAssertTrue(viewController is TestViewController) }
  33. 33. Only test things that might actually fail.
  34. 34. 3. Aim for high unit test code coverage.
  35. 35. 3. Cover a unit’s behaviour with good unit tests.
  36. 36. 4. Avoid Singletons
  37. 37. One shared instance. Globally Accessible.
  38. 38. class UserData { static let shared = UserData() var authToken: String? var name: String? var image: UIImage? }
  39. 39. class UserData { static let shared = UserData() var authToken: String? var name: String? var image: UIImage? } Why it’s ‘bad' - Mutable shared state - Implicit lifetime - Difficulty testing - Implicit dependency
  40. 40. UIApplication.shared UserDefaults.standard FileManager.default
  41. 41. Represents a single property of the environment.
  42. 42. 4. Avoid Singletons
  43. 43. 4. Avoid Singletons for objects that are not single properties of the environment
  44. 44. Dependency Injection
  45. 45. But what if you’re working on open source framework?
  46. 46. import Kingfisher imageView.kf.setImage(with: url)
  47. 47. Simple API Easier Adoption.
  48. 48. let task = KingfisherManager.shared.retrieveImage( with: source, options: options, completionHandler: { result in CallbackQueue.mainCurrentOrAsync.execute { completionHandler?(result) } } )
  49. 49. 4. Avoid Singletons for objects that are not single properties of the environment
  50. 50. 4. Avoid Singletons for objects that are not single properties of the environment unless it improves the API and integration of your framework for third party apps
  51. 51. 5. Prefer structs over classes
  52. 52. Structs -> Value Classes -> Reference
  53. 53. Similarities - Stored / Computed Properties - Methods - Subscripts - Initialisers - Extensions. - Protocol conformance.
  54. 54. Struct benefits - No shared state - Generally faster/lighter - Multi threading
  55. 55. struct Germany { let towns = ["Cologne", "Düsseldorf" , "Wuppertal"] }
  56. 56. Replacing singletons: FileManager / BluetoothManager etc.
  57. 57. Properties should be value types too for some of the benefits
  58. 58. struct SwiftConf { var text: String } var a = SwiftConf(text: "StructText") var b = a b.text = "ModifiedStructText" print(a.text) print(b.text)
  59. 59. class TextContainer { var text: String init(text: String) { self.text = text } } struct SwiftConf { var textContainer: TextContainer } var a = SwiftConf(textContainer: TextContainer(text: "ClassText")) var b = a b.textContainer.text = "ModifiedClassText" print(a.textContainer.text) print(b.textContainer.text)
  60. 60. 5. Prefer structs over classes
  61. 61. 5. Prefer structs over classes when the thing it represents and its properties have value semantics
  62. 62. Stack allocation = 🚀
  63. 63. Until we’re talking about complex nested structs
  64. 64. Arrays, dictionaries, and strings use copy-on-write optimization
  65. 65. struct User { var name: String? }
  66. 66. class UserStorage { var name: String? init() {} } struct User { public var storage: UserStorage init() { self.storage = UserStorage() } public var name: String? { get { return storage.name } set { if isKnownUniquelyReferenced(&storage) { storage.name = newValue } else { storage = UserStorage() storage.name = newValue } } } }
  67. 67. 5. Prefer structs over classes when the thing it represents and its properties have value semantics
  68. 68. 5. Prefer structs over classes when the thing it represents and its properties have value semantics unless it’s a complex nested struct, which should be backed by a class
  69. 69. 6. Use immutable data models
  70. 70. Mutable data model - Shared state - Multi threading
  71. 71. Structs to the rescue
  72. 72. struct User { let name: String }
  73. 73. struct User { let name: String } extension User { func withName(_ name: String) -> User { return User(name: name) } }
  74. 74. Value types are always ‘immutable’ *
  75. 75. struct User { var name: String }
  76. 76. 7.Don’t store things in user defaults
  77. 77. Key-value store
  78. 78. UserDefaults.standard.set("SwiftConf", forKey: "Conference") let name = UserDefaults.standard.value(forKey: "Conference")
  79. 79. Alternatives - Writing to a file - Keychain - Sqlite - Core Data
  80. 80. Unencrypted plist 🔐
  81. 81. Loads into memory the entire suite on first read. 🐌
  82. 82. 7.Don’t store things in user defaults
  83. 83. 7.Don’t store a lot of data or anything sensitive in user defaults
  84. 84. The Bigger Picture
  85. 85. Swift BestPractices
  86. 86. How do they develop?
  87. 87. 2016
  88. 88. class Wurst: NSObject, Edible, Purchasable, UIToolbarDelegate { func eat() { // Eat } func buy() { // Buy } func position(for bar: UIBarPositioning) -> UIBarPosition { return .top } }
  89. 89. class Wurst: NSObject { } //MARK: Purchasable Conformance extension Wurst: Purchasable { func buy() { // Buy } } //MARK: Edible Conformance extension Wurst: Edible { func eat() { // Eat } } //MARK: UIToolbarDelegate Conformance extension Wurst: UIToolbarDelegate { func position(for bar: UIBarPositioning) -> UIBarPosition { return .top } }
  90. 90. 9. Use extensions for better code structure 🆕
  91. 91. They can also fall out of favour
  92. 92. 10. Swift naming convention
  93. 93. var someString = "a String " someString.stringByAppendingString("anotherString")
  94. 94. Clarity at point of use
  95. 95. var someString = "a String " someString.append("another String")
  96. 96. Best practices are a snapshot of what the community currently believes
  97. 97. Local community
  98. 98. Software Engineering community
  99. 99. They are good general guidelines
  100. 100. 1. Never force unwrap when you can provide a useful error message or its not a static developer typo
  101. 101. 1. Never force unwrap
  102. 102. Understand why
  103. 103. Better developer
  104. 104. Code Review Comments
  105. 105. Imposter syndrom
  106. 106. We are all potential authors
  107. 107. Challenge and help evolve better programming practices
  108. 108. @marmelroy

Slides for a talk on best practices in Swift delivered at SwiftConf 2019

Vues

Nombre de vues

12

Sur Slideshare

0

À partir des intégrations

0

Nombre d'intégrations

0

Actions

Téléchargements

0

Partages

0

Commentaires

0

Mentions J'aime

0

×