<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I really like the general spirit of these guidelines. I particularly appreciate their emphasis on clarity at the point of use, and their recognition that both brevity and verbosity can be the enemy of clarity.</div><div class=""><br class=""></div><div class="">Some of the particulars of the guidelines haven’t worked well for me in practice — and I see from this thread that others have hit some of the same problems. The guidelines as they stand feel like they’ve mostly been vetted against a bunch of ADTs (which is probably true — stdlib?), and could use exposure to a broader range of libraries.</div><div class=""><br class=""></div><div class="">Immediately after the guidelines were published, before this review began, I tried applying them to Siesta. The project has 244 public declarations, of which I found 28 that the guidelines seemed to recommend changing. Of those 28, after much reflection and discussion, I ended up changing only 7 to match the guidelines (and also cleaning up several others, but in a non-guideline-compliant way).</div><div class=""><br class=""></div><div class="">In short, in a real-world project, pre-guidelines code agreed with the guidelines 89% of the time, but where it disagreed, the guidelines achieved only a 25% acceptance rate with the curmudgeonly developers.</div><div class=""><br class=""></div><div class="">You can follow that discussion here:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span><a href="https://gist.github.com/pcantrell/22a6564ca7d22789315b" class="">https://gist.github.com/pcantrell/22a6564ca7d22789315b</a></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><a href="https://github.com/bustoutsolutions/siesta/issues/15" class="">https://github.com/bustoutsolutions/siesta/issues/15</a></div><div class=""><br class=""></div><div class="">Several places where we rejected the guidelines relate to the raging debate about <b class="">first argument labels</b>. Here’s a rundown of those particular cases. (Since this message will be a long one, I’ll share in a separate message some notes on the other places where we rejected the guidelines on questions other than the first arg label.)</div><div class=""><br class=""></div><div class="">Hopefully some more concrete examples can be useful in informing the discussion.</div><div class=""><br class=""></div><div class="">_____________________________</div><div class=""><b class=""><br class=""></b></div><div class="">Quick context: there are things called resources. Resources can have observers. Observers are either self-owned or have an external owner object. Observers can either conform to a protocol or be closures; if the the latter, then they _must_ have an external owner (because closures aren’t objects).</div><div class=""><br class=""></div><div class="">There are thus three different methods to add observers to a resource — though they all cover the same underlying notion of “observer” (and in fact all boil down to the same thing internally):</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> resource.addObserver(<span style="color: rgb(50, 62, 125);" class="">foo</span>)</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> resource.addObserver(fancyIndicator, owner: <span style="color: rgb(50, 62, 125);" class="">foo</span>)</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> resource.addObserver(owner: <span style="color: rgb(50, 62, 125);" class="">foo</span>) {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> resource, event <span style="color: rgb(50, 62, 125);" class="">in</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> updateStuff(resource.latestData)</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> }</div></div><div class=""><br class=""></div><div class="">The API guidelines as stated would have us change that last one to:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> resource.addObserverWithOwner(<span style="color: rgb(50, 62, 125);" class="">foo</span>) {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> resource, event <span style="color: rgb(50, 62, 125);" class="">in</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> updateStuff(resource.latestData)</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> }</div></div><div class=""><br class=""></div><div class="">However, this incorrectly implies that there is a distinct kind of thing that is an “observer with owner,” and that we will get one only from the third flavor of the method. That implication is wrong.</div><div class=""><br class=""></div><div class="">The consistency in the original of the “addObserver” name and the “owner:” label make the correct implication: all three methods serve the same purpose, observers are observers, and “owner” means the same thing in the two places it appears. I certainly think the non-compliant version of the code reads better.</div><div class=""><br class=""></div><div class="">There was extensive discussion around another family of methods that return a resource given either a path fragment or an absolute URL. This is where we ended up:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(88, 126, 168);" class=""><span style="color: rgb(0, 0, 0);" class=""> </span>service<span style="color: rgb(0, 0, 0);" class="">.</span>resource<span style="color: rgb(0, 0, 0);" class="">(</span><span style="color: rgb(132, 62, 100);" class="">"/foo"</span><span style="color: rgb(0, 0, 0);" class="">)</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168);" class="">service</span>.<span style="color: rgb(88, 126, 168);" class="">resource</span>(absoluteURL: <span style="color: rgb(132, 62, 100);" class="">"<a href="http://bar.com" class="">http://bar.com</a>"</span>)</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168);" class="">service</span>.<span style="color: rgb(88, 126, 168);" class="">resource</span>(absoluteURL: <span style="color: rgb(88, 126, 168);" class="">NSURL</span>(string: <span style="color: rgb(132, 62, 100);" class="">"<a href="http://bar.com" class="">http://bar.com</a>"</span>))</div></div><div class=""><br class=""></div><div class="">(The first is by far the most common, the “standard” flavor.)</div><div class=""><br class=""></div><div class="">The guidelines would have had us do this:</div><div class=""><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(88, 126, 168);" class=""><span style="color: rgb(0, 0, 0);" class=""> </span>service<span style="color: rgb(0, 0, 0);" class="">.</span>resourceWithPathFragment<span style="color: rgb(0, 0, 0);" class="">(</span><span style="color: rgb(132, 62, 100);" class="">"/foo"</span><span style="color: rgb(0, 0, 0);" class="">)</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168);" class="">service</span>.<span style="color: rgb(88, 126, 168);" class="">resourceWithAbsoluteURL</span>(<span style="color: rgb(132, 62, 100);" class="">"<a href="http://bar.com" class="">http://bar.com</a>"</span>)</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168);" class="">service</span>.<span style="color: rgb(88, 126, 168);" class="">resourceWithAbsoluteURL</span>(<span style="color: rgb(88, 126, 168);" class="">NSURL</span>(string: <span style="color: rgb(132, 62, 100);" class="">"<a href="http://bar.com" class="">http://bar.com</a>"</span>))</div></div></div><div class=""><br class=""></div><div class="">To my eyes, this crosses the line into verbosity that impedes clarity, but there’s an even more serious problem: it wrongly implies that there’s a distinction between “resources with path fragments” and “resources with absolute URLs.” That’s dangerously wrong. One of the central conceits of the whole library is that _all_ resources get a canonicalized absolute URL, and there’s a uniqueness guarantee for that URL no matter whether it was constructed for a path fragment, an absolute URL, or resource-relative navigation.</div><div class=""><br class=""></div><div class="">In the cases of both addObserver(…) and service.resource(…), the guidelines would have us actively mislead users.</div><div class=""><br class=""></div><div class="">Another trickier example of the same issue is the much-discussed typedContent method, which downcasts based on inferred type and returns a default value if content is either missing <i class="">or</i> of the wrong type:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(50, 62, 125);" class="">var</span> image: <span style="color: rgb(88, 126, 168);" class="">UIImage?</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""><font color="#949494" class=""> ...</font></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168); font-size: 10.5px;" class="">image</span><span style="font-size: 10.5px;" class=""> =</span><span style="font-size: 10.5px;" class=""> </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">imageResource</span><span style="font-size: 10.5px;" class="">.</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">typedContent</span><span style="font-size: 10.5px;" class="">(ifNone: </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">placeholderImage</span><span style="font-size: 10.5px;" class="">)</span></div></div><div class=""><br class=""></div><div class="">How to make this conform to the guidelines? The obvious fix is terrible:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168); font-size: 10.5px;" class="">image</span><span style="font-size: 10.5px;" class=""> =</span><span style="font-size: 10.5px;" class=""> </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">imageResource</span><span style="font-size: 10.5px;" class="">.</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">typedContentIfNone</span><span style="font-size: 10.5px;" class="">(</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">placeholderImage</span><span style="font-size: 10.5px;" class="">)</span></div></div><div class=""><span style="font-size: 10.5px;" class=""><br class=""></span></div><div class="">This implies … what? That the method only returns typed content if there is none of the placeholder image? No, clearly a rephrasing is necessary:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168); font-size: 10.5px;" class="">image</span><span style="font-size: 10.5px;" class=""> =</span><span style="font-size: 10.5px;" class=""> </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">imageResource</span><span style="font-size: 10.5px;" class="">.</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">typedContentWithDefault</span><span style="font-size: 10.5px;" class="">(</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">placeholderImage</span><span style="font-size: 10.5px;" class="">)</span></div></div><div class=""><br class=""></div><div class="">But again we have this problem of determining whether “with default” describes the method’s behavior, its result, or its first argument. Are we attaching content with the default somehow attached to it? (No.) Are we returning some content, or a default value if there is none? (Yes.) So maybe this is better:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168); font-size: 10.5px;" class="">image</span><span style="font-size: 10.5px;" class=""> =</span><span style="font-size: 10.5px;" class=""> </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">imageResource</span><span style="font-size: 10.5px;" class="">.</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">typedContentOrDefault</span><span style="font-size: 10.5px;" class="">(</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">placeholderImage</span><span style="font-size: 10.5px;" class="">)</span></div></div><div class=""><span style="font-size: 10.5px;" class=""><br class=""></span></div><div class="">But now my brain is having parsing problems. What is the LHS of that “or?” It just doesn’t read naturally. OK, maybe even more words can save us:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168); font-size: 10.5px;" class="">image</span><span style="font-size: 10.5px;" class=""> =</span><span style="font-size: 10.5px;" class=""> </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">imageResource</span><span style="font-size: 10.5px;" class="">.</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">typedContentOrDefaultIfNone</span><span style="font-size: 10.5px;" class="">(</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">placeholderImage</span><span style="font-size: 10.5px;" class="">)</span></div></div><div class=""><span style="font-size: 10.5px;" class=""><br class=""></span></div><div class=""><div class="">Yuck. At this point, we might as well stuff the entire method abstract in the name:</div><div class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168); font-size: 10.5px;" class="">image</span><span style="font-size: 10.5px;" class=""> =</span><span style="font-size: 10.5px;" class=""> </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">imageResource</span><span style="font-size: 10.5px;" class="">.</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">typedContentOrDefaultIfNoneOrMismatchedType</span><span style="font-size: 10.5px;" class="">(</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">placeholderImage</span><span style="font-size: 10.5px;" class="">)</span></div></div><div class=""><br class=""></div><div class="">Yuck squared. The original is so much clearer:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class=""> <span style="color: rgb(88, 126, 168); font-size: 10.5px;" class="">image</span><span style="font-size: 10.5px;" class=""> =</span><span style="font-size: 10.5px;" class=""> </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">imageResource</span><span style="font-size: 10.5px;" class="">.</span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">typedContent</span><span style="font-size: 10.5px;" class="">(ifNone: </span><span style="font-size: 10.5px; color: rgb(88, 126, 168);" class="">placeholderImage</span><span style="font-size: 10.5px;" class="">)</span></div></div><div class=""><span style="font-size: 10.5px;" class=""><br class=""></span></div><div class="">IMO, there’s nothing wrong with leaning on <i class="">programming language</i> syntax to help segment and clarify <i class="">English syntax.</i></div><div class=""><br class=""></div><div class="">_______________________________</div><div class=""><br class=""></div><div class="">What’s the better guideline on first argument labels?</div><div class=""><br class=""></div><div class="">Radek had a nice thought in the aforementioned Gihub thread:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">The rationale being, ifNone doesn't really describe the method … it describes the parameter. Most of the time, the job of the method makes the first parameter obvious (hence the guideline), but here, it doesn't. So the parameter makes sense.<br class=""></blockquote></div><div class=""><br class=""></div><div class="">I’ll give a +1 for these two recommendations from Erica, which run along the same lines as Radek’s thought, but in more thorough detail:</div><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 23, 2016, at 6:33 PM, Erica Sadun via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class=""><div class=""><div class=""><b class="">Prefer external names for the first parameter when the natural</b></div><div class=""><div class=""><b class="">semantic relationship between the parameters is stronger than their<br class="">relation to the operation.</b> </div><div class=""><br class=""></div><div class="">For example, the following calls use labels for the first parameter:</div><div class=""><br class=""></div><div class=""><font face="Courier" class="">login(userName: "blah", password: "...")</font></div><div class=""><font face="Courier" class="">moveTo(x: 50.0, y: 30.0)</font></div><div class=""><br class=""></div><div class="">This example is contrary to Swift's normal naming scheme which integrates the</div><div class="">first argument into the function or method name, for example:</div><div class=""><br class=""></div><div class=""><font face="Courier" class="">loginWithUserName("blah", password: "...")</font></div><div class=""><font face="Courier" class="">moveToX(50.0, y: 30.0)</font></div><div class=""><br class=""></div><div class="">The coupling between x and y, username and password, (and yes it is a judgement call) </div><div class="">should be considered as a reason to employ an external label.</div></div></div></div></div></blockquote>…<br class=""><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><b class="">Differentiate related calls whose implementations are distinguished by their</b></div><div class=""><b class="">parameters, as you would with initializers, using first parameter labels.</b></div><div class=""><b class=""><br class=""></b></div><div class="">Instead of loginWithUserName("blah", password: "...") and loginWithCredential(myCredential),</div><div class="">prefer:</div><div class=""><br class=""></div><div class=""><font face="Courier" class="">login(userName: "blah", password: "...")</font></div><div class=""><font face="Courier" class="">login(credential: myCredential)</font></div></div></div></div></blockquote><br class=""></div><div>I’m not sure we’ve found the perfect, crisp way of saying all this — but I strongly agree that the existing guidelines are too rigid on the question of the first arg label, and Erica’s wording comes the closest I’ve seen to being a viable replacement.</div><div><br class=""></div><div>Cheers,</div><div><br class=""></div><div>Paul</div><div class=""><br class=""></div></body></html>