Advertisement
Guest User

Untitled

a guest
Feb 4th, 2016
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.48 KB | None | 0 0
  1. ##Introduction because I have OCD
  2.  
  3. Swift prizes clarity. Its parameter labeling system emphasizes self-documentation
  4. and guides code production. In nearly every case, labels follow
  5. three simple rules:
  6.  
  7. * Skip argument labels for a method or function's first parameter
  8. * Use argument labels for a method or function's subsequent parameters
  9. * Require argument labels for initializers
  10.  
  11. These base rules enhance Swift legibility. Unlike other languages whose positional argument
  12. names have meaning only within the implementation context, Swift's labels convey use and
  13. meaning at the calling site. This creates better communication, enhances maintainability,
  14. and adheres to the principle that code is written rarely and read and reviewed often.
  15.  
  16. At times, special circumstances may apply to your code as explored in the following rules:
  17.  
  18. ------
  19. ###Dave:
  20. If and only if the first argument could complete a sentence*
  21. beginning in the base name and describing the primary semantics of
  22. the call, it gets no argument label:
  23.  
  24. a.contains(b) // b completes the phrase "a contains b"
  25. a.mergeWith(b) // b completes the phrase "merge with b"
  26.  
  27. a.dismiss(animated: b) // "a, dismiss b" is a sentence but
  28. // doesn't describe the semantics at all,
  29. // thus we add a label for b.
  30.  
  31. a.moveTo(x: 300, y: 400) // "a, move to 300" is a sentence
  32. // but doesn't describe the primary
  33. // semantics, which are to move in both
  34. // x and y. Thus, x gets a label.
  35.  
  36. a.readFrom(u, ofType: b) // "a, read from u" describes
  37. // the primary semantics, so u gets no
  38. // label. b is an
  39. // option that tunes the primary
  40. // semantics
  41.  
  42. [Note that this covers all the direct object cases and, I believe,
  43. all the default argument cases too, so maybe that exception can be
  44. dropped. We still need the exceptions for full-width type
  45. conversions and indistinguishable peers]
  46.  
  47. ------
  48.  
  49. * *Skip first argument labels* when the first argument completes a sentence established in the base name. If the argument describes a call's primary semantics, it does not require a label:
  50.  
  51. ```swift
  52. a.contains(b) // b completes the phrase "a contains b"
  53. a.mergeWith(b) // b completes the phrase "merge with b"
  54. a.readFrom(u, ofType: b) // "a, read from u" describes
  55. // primary semantics so u gets no
  56. // label.
  57. // b is an option that tunes the
  58. // primary semantics
  59. ```
  60.  
  61. **Changes** Rule is now a directive. Dismiss and moveTo are moved to their own rules. I only minorly tweaked the comments.
  62.  
  63. ------
  64. ###Dave:
  65. Note: when there is a noun in the base name describing the role of the
  66. first argument, we skip it in considering this criterion:
  67.  
  68. a.addObserver(b) // "a, add b" completes a sentence describing
  69. // the semantics. "Observer" is omitted in
  70. // making this determination.
  71. ----
  72. * *Skip the first argument label* when a noun in the base name describes the first argument's role.
  73.  
  74. ```swift
  75. a.addObserver(b) // "add b" completes a meaningful sentence that
  76. // defines the intended semantics. The first
  77. // argument is the "Observer".
  78. ```
  79.  
  80. **Changes** Rephrasing, rule directive, rewrote comments
  81.  
  82. -----
  83.  
  84. ###Dave:
  85. 3. (this one is separable) When the first argument is the *name* or
  86. *identifier* of the subject in the base name, do not label it or
  87. describe it in the base name.
  88.  
  89. a.transitionToScene(.GreatHall) // yes
  90. a.transitionToSceneWithIdentifier(.GreatHall) // no
  91.  
  92. let p = someFont.glyph("propellor") // yes
  93. let p = someFont.glyphWithName("propellor") // no
  94. let p = someFont.glyph(name: "propellor") // no
  95.  
  96. ----
  97.  
  98. * *Move the first argument label* to the base name when it describes a name or identifier that acts as the subject of the base action.
  99.  
  100. ```swift
  101. a.transitionToScene(.GreatHall) // yes
  102. a.transitionToSceneWithIdentifier(.GreatHall) // no
  103.  
  104. let p = someFont.glyph("propellor") // yes
  105. let p = someFont.glyphWithName("propellor") // no
  106. let p = someFont.glyph(name: "propellor") // no
  107. ```
  108.  
  109. **Changes** Rule directive, grouped below with similar rule
  110.  
  111. ----
  112.  
  113. ###Dave:
  114.  
  115.  
  116. 2. Words that describe attributes of an *already-existing* instance
  117. should go in the base name rather than in a label:
  118.  
  119. a.tracksHavingMediaType("Wax Cylinder") // yes
  120. a.removeFirstTrackHavingMediaType("BetaMax") // yes
  121.  
  122. a.tracks(mediaType: "Wax Cylinder") // no
  123. a.removeFirstTrack(havingMediaType: "BetaMax") // no
  124.  
  125. [yes, we could use "With" instead of "Having", but it's more
  126. ambiguous]
  127.  
  128. Words that describe attributes of an instance *to be created* should
  129. go in argument labels, rather than the base name (for parity with
  130. initializers):
  131.  
  132. AudioTrack(mediaType: "BetaMax") // initializer
  133. trackFactory.newTrack(mediaType: "Wax Cylinder") // yes
  134.  
  135. trackFactory.newTrackWithMediaType("Wax Cylinder") // no
  136.  
  137. ----
  138.  
  139. * *Move the first argument label* to the base name when it describes argument attributes of existing instances.
  140.  
  141. ```swift
  142. a.tracksOfMediaType("Wax Cylinder") // yes
  143. a.removeFirstTrackOfMediaType("BetaMax") // yes
  144.  
  145. a.tracks(mediaType: "Wax Cylinder") // no
  146. a.removeFirstTrack(havingMediaType: "BetaMax") // no
  147. ```
  148.  
  149. **Changes** Rule directive, grouped with previous rule, split out initializer-like rules for later, changed first "Having" to "Of" because that's the way I roll.
  150.  
  151. ----
  152.  
  153. * *Use first label arguments* when the first parameter is semantically distinct from the base name and does not complete a meaningful "sentence"
  154. ```swift
  155. a.dismiss(animated: b) // "a, dismiss b" is a sentence but
  156. // doesn't describe the semantics at all,
  157. // thus we add a label for b.
  158. ```
  159.  
  160. ----
  161.  
  162. **Changes** Broke this one out into its own rule because it's about when not to merge into base name but still use a label. By the way, I loathe "we" voice.
  163.  
  164. ----
  165.  
  166. * *Use all argument labels* when the relationship between arguments is semantically stronger than
  167. the relationship between the first argument and the base name.
  168.  
  169. ```swift
  170. moveTo(x: a, y: b)
  171. login(userName: a, password: b)
  172. constructColor(red: r, green: g, blue: b, alpha: a)
  173. ```
  174.  
  175. ----
  176.  
  177. **Changes** Completely new rule
  178.  
  179. ----
  180.  
  181. * *Omit labels* for argument peers that cannot be usefully distinguished.
  182.  
  183. ```swift
  184. min(number1, number2)
  185. zip(sequence1, sequence2)
  186. ```
  187.  
  188. ----
  189.  
  190. **Changes** Stolen from doc, moved here because it fits, and rephrased a teeeeeny bit to make it more a directive
  191.  
  192. What follows next is a group of initializer-ish rules grouped together.
  193.  
  194. ----
  195.  
  196. * *Use explicit argument labels* to describe attributes of an instance that's *being created*.
  197. Your calls should resemble initializers.
  198.  
  199. ```
  200. AudioTrack(mediaType: "BetaMax") // initializer
  201. trackFactory.newTrack(mediaType: "Wax Cylinder") // yes
  202.  
  203. trackFactory.newTrackOfMediaType("Wax Cylinder") // no
  204. ```
  205.  
  206. * *Use first argument labels* that would have normally appeared in the base name when building
  207. groups of related calls whose implementations are distinguished specifically by their parameters.
  208. Your calls should resemble initializers.
  209.  
  210. ```swift
  211. login(userName: a, password: b) // not loginWithUserName(a, password: b)
  212. login(credential: a) // not loginWithCredential(a)
  213. ```
  214.  
  215. ----
  216.  
  217. **Changes** New rule
  218.  
  219. ----
  220.  
  221. * *Skip first argument labels* for initializers when using full width type conversions, that is
  222. when initializing from instances of another type.
  223.  
  224. ```swift
  225. extension String {
  226. // Convert `x` into its textual representation
  227. // in the given radix
  228. init(_ x: BigInt, radix: Int = 10)
  229. }
  230. text = "The value is: "
  231. text += String(veryLargeNumber)
  232. text += " and in hexadecimal, it's"
  233. text += String(veryLargeNumber, radix: 16)
  234. ```
  235.  
  236. * *Use first argument labels* when narrowing initial values to make it conform
  237. to restrictions within the new type. The label should describe how the instance
  238. will be modified:
  239.  
  240. ```swift
  241. extension UInt32 {
  242. init(_ value: Int16) // Widening, so no label
  243. init(truncating bits: UInt64)
  244. init(saturating value: UInt64)
  245. }
  246. ```
  247.  
  248. ----
  249.  
  250. **Changes** Both of these are stolen from docs, but rephrased to be more readable
  251.  
  252. ----
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement