[swift-evolution] [Review] SE-0023 API Design Guidelines

Douglas Gregor dgregor at apple.com
Sun Jan 24 01:10:53 CST 2016


> On Jan 23, 2016, at 10:45 AM, Joe Groff <jgroff at apple.com> wrote:
> 
> This all looks good to me (aside from the linguistic problems with verb conjugation I've raised in another subthread). However, I think these naming guidelines lead us to reconsider our default argument labeling rules for 'func' declarations again, as David Owens and others have suggested. The stated goal of the current language rule is to guide people into good API design following our conventions, but I don't think it succeeds in serving that purpose. If you follow the guidelines, the argument labels for your secondary arguments generally end up becoming prepositional phrases, which make for poor variable names, and you're naturally guided to giving the argument an explicit descriptive binding name:
> 
> func perform(stuff: Stuff, with: Thing) {
>   with.apply(stuff) // 'with' is a weird variable name
> }
> 
> func perform(stuff: Stuff, with thing: Thing) {
>   thing.apply(stuff) // 'thing' is better
> }

I don’t understand how you came to the conclusion that secondary arguments generally end up becoming prepositional phrases. I know you’re using abstract examples, but the “with” in your example above is essentially vacuous. Indeed, the Clang importer rules of SE-0005 won’t allow us to prune argument labels if the result is just “with” (or “for”, or one of a few other vacuous words). I would expect the API above to use:

	func perform(stuff: Stuff, thing: Thing) {

Now, meaningful prepositions do show up sometimes as the argument label. For example

	func insert(x: Element, at index: Index)

but this case doesn’t seem like the dominant case it all: you’re often just describing what the argument is rather than its relationship to the operation, and it only can be “just a preposition” if any word you add to clarify the role of the parameter would be redundant with the type information.

> The shorthand thus doesn't save the good API citizen from much work. On the other hand, a developer who's unaware or uninterested in the guidelines and is just trying to C or Java in Swift gets argument labels by default that neither follow the guidelines nor meet their expectation:
> 
> func atan2(y: Double, x: Double) -> Double { ... }
> 
> atan2(10, 10) // Why doesn't this work?
> atan2(10, x: 10) // Nobody wants this
> 
> And when staring down potentially dozens or hundreds of compile errors at various mismatched use sites, they're unlikely to reconsider their API naming choice, and will instead do the minimal amount of work to get their code to compile by suppressing the argument label.

*Any* refactoring tool for Swift should be able to handle renaming argument labels, so this shouldn’t be any more painful that your typical rename.

> The language hasn't led this developer to better conventional API design either.
> 
> I can think of a couple possible modifications to the language rule that could help reduce the surprise factor, and still lead people to good API design:
> 
> - Require all 'func' arguments after the first to explicitly specify both a label and a binding name. Users following the guidelines will usually end up doing this anyway, and users who aren't will get a helpful message instead of unexpected behavior. This also avoids a problem with our current rule, where otherwise identical-looking parameter declarations in a 'func' end up behaving differently based on position. A diagnostic immediately at the declaration site also seems more likely to me to lead the developer to think more about their API naming; diagnosing call sites that don't look the way they want is just going to lead them to reactively suppress the labels to get their code to compile.

Obviously, I’d be concerned about us introducing a significant amount of boilerplate by doing this. We could determine just how much boilerplate this would be added by proxy: how many second-or-later parameters in Objective-C methods have the same identifier as the corresponding selector piece? If it’s a significant fraction, then this kind of change becomes hard to justify.

> - Change the default rule so that all arguments *after an explicitly labeled argument* default to being labeled (instead of all arguments after the first). It's unlikely anyone wants an unlabeled argument positionally after a labeled one, and the rare methods in Cocoa that take more than two arguments do tend to use noun rather than preposition phrases for arguments after the second. Users following the guidelines get nice labeled APIs, and users who aren't get the bare, uncaring anonymous arguments they deserve:
> 
> func perform(stuff: Stuff, with thing: Thing, options: StuffOptions) // perform(_:with:options:)
> func atan2(y: Double, x: Double) // atan2(_:_:)

It seems to me that this nudges us toward less-readable call sites, with anonymous arguments dominating simply because it’s the easy thing. It’s more motivating to fix a poor API decision (i.e., a bad argument label) if you’re seeing it at each and every call site...

	- Doug


> 
> -Joe
> 
>> On Jan 22, 2016, at 1:02 PM, Douglas Gregor via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> Hello Swift community,
>> 
>> The review of SE-0023"API Design Guidelines" begins now and runs through January 31, 2016. The proposal is available here:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0023-api-guidelines.md <https://github.com/apple/swift-evolution/blob/master/proposals/0023-api-guidelines.md>
>> Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at
>> 
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:
>> 
>> Proposal link:
>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0023-api-guidelines.md <https://github.com/apple/swift-evolution/blob/master/proposals/0023-api-guidelines.md>
>> Reply text
>> 
>> Other replies
>>  <https://github.com/apple/swift-evolution#what-goes-into-a-review-1>What goes into a review?
>> 
>> The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:
>> 
>> What is your evaluation of the proposal?
>> Is the problem being addressed significant enough to warrant a change to Swift?
>> Does this proposal fit well with the feel and direction of Swift?
>> If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
>> How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
>> More information about the Swift evolution process is available at
>> 
>> https://github.com/apple/swift-evolution/blob/master/process.md <https://github.com/apple/swift-evolution/blob/master/process.md>
>> Thank you,
>> 
>> -Doug Gregor
>> 
>> Review Manager
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160123/41e82626/attachment.html>


More information about the swift-evolution mailing list