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

Erica Sadun erica at ericasadun.com
Sat Jan 23 18:33:21 CST 2016


> On Jan 23, 2016, at 1:21 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> on Fri Jan 22 2016, Erica Sadun <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> 
>>> On Jan 22, 2016, at 5:26 PM, Michael Wells via swift-evolution
>>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> 
>>>> On Sat, Jan 23, 2016 at 12:00 AM, David Owens II via
>> 
>>>> swift-evolution
>>>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>>
>>>> wrote:
>>>>> Compensate For Weak Type Information as needed to clarify a parameter’s role.
>>>>> 
>>>>> Especially when a parameter type is NSObject, Any, AnyObject, or a
>>>>> fundamental type such Int or String, type information and context
>>>>> at the point of use may not fully convey intent. In this example,
>>>>> the declaration may be clear, but the use site is vague:
>>>>> 
>>>>> func add(observer: NSObject, for keyPath: String)
>>>>> grid.add(self, for: graphics) // vague
>>>>> 
>>>>> To restore clarity, precede each weakly-typed parameter with a noun describing its role:
>>>>> 
>>>>> func addObserver(_ observer: NSObject, forKeyPath path: String)
>>>>> grid.addObserver(self, forKeyPath: graphics) // clear
>>>> 
>>> 
>>> Where this rule feels clumsy to me is in code such as
>>> 
>>> func loginWithUsername(username: String, password: String) -> Bool
>>> 
>>> vs.
>>> 
>>> func login(username: String, password: String) -> Bool
>>> 
>>> But maybe it just takes some time to get used to the style.
>> 
>> Consider an exception rule:
>> 
>> Prefer external names for the first parameter when the natural
>> semantic relationship between the parameters is stronger than their
>> relation to the operation. So
>> 
>> login(username: String, password:String)
>> moveTo(x: Double, y: Double)
> 
> used as
> 
>    login("dave", password: secret)
>    moveTo(width, y: height)
> ?
> 
> I can't imagine you meant the latter one.
> 
>> but 
>> 
>> addLineToPoint(p1: CGPoint, withThickness: CGFloat)
> 
>   addLineToPoint(origin, withThickness: CGFloat)
> 
> ?
> 
> I don't see what salient information the word "Point" is adding here.
> 

Dave,

I typoed on the second and I was insufficiently clear on my point. Trying again:

Prefer external names for the first parameter when the natural
semantic relationship between the parameters is stronger than their
relation to the operation. 

For example, the following calls use labels for the first parameter:

login(userName: "blah", password: "...")
moveTo(x: 50.0, y: 30.0)

This example is contrary to Swift's normal naming scheme which integrates the
first argument into the function or method name, for example:

loginWithUserName("blah", password: "...")
moveToX(50.0, y: 30.0)

The coupling between x and y, username and password, (and yes it is a judgement call) 
should be considered as a reason to employ an external label.

I had included the following as a counter example:

addLineToPoint(p1, withWidth: 25.0)

In this call, the point and width have no natural or compelling relationship and there's no reason to
create an external label for the first argument. This example follows the standard
Swift call approach.

Differentiate related calls whose implementations are distinguished by their
parameters, as you would with initializers, using first parameter labels.

Instead of loginWithUserName("blah", password: "...") and loginWithCredential(myCredential),
prefer:

login(userName: "blah", password: "...")
login(credential: myCredential)

And to reply to another point raised in-thread:

When working with standard library calls, retain APIs even if they are
not sufficiently clear from a Swift design perspective rather than wrapping-the-cat
to provide a Swift interface that doesn't really exist. (As the call is just a redirection.)

For example, prefer

let x = pow(2.0, 5.0)

to

let x = raise(2.0, toPower: 5.0)

In this example, the two arguments for pow are not specified as this call is sourced
externally and follows the naming convention for math.h.

-- Erica


> -- 
> -Dave
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <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/c5b5c21d/attachment.html>


More information about the swift-evolution mailing list