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

Radosław Pietruszewski radexpl at gmail.com
Wed Jan 27 04:27:00 CST 2016


Here’s what I meant:

>    resource.load()
>        .onCompletion { _ in stopSpinnyThing() }
>        .onSuccess { _ in showHappyFace() }
>        .onFailure { _ in showSadFace() }
>        .onNewData { _ in soundTrumpets() }

Is a nice DSL, but not a universal pattern we see everywhere.

However something like this:

    someNetworkingOperation(success: { … }, failure: { … })
    someAnimatingThing(completionHandler: { … })

Is very, very common, and I wouldn’t call that an EDSL, it’s just closure passing.

And while not a super big deal, I would like to see the naming of such names be standardized as “onSuccess”, “onFailure”, “onCompletion”.

Rationale:

   someAction(completion: () -> Void)

A word describing the event itself, such as "completion", "success", "failure", isn't always immediately obvious, depending on the context. For instance, when passing a function reference instead of an inline closure, it might not be fully clear that it is, in fact, a function that is called _when_ completion/success/failure occurs. It might give an impression that, say, "completion" is a _thing_, a term of art describing something meaningful.

And so, presumably for this reason, the Cocoa convention is to use the word "handler", like so:

    someAction(completionHandler: () -> Void)

This isn't too bad, but it is slightly verbose in my opinion. Of course, clarity takes precedense over brevity, but I believe there's a good idiom, common in other languages/frameworks/environments, that's less verbose, conveys the semantics well if not better, and reads very nicely:

    someAction(onCompletion: () -> Void)

At call site, this reads very naturally without any ambiguity both when passing a closure inline:

    someAction(onSuccess: { ... }, onFailure: { ... })

And when passing a function reference

    someAction(onCompletion: doSomethingElse)

I know this isn’t the topic for this thread which is why I wasn’t going to elaborate too much. Do you think this level of naming guidance is appropriate for the Guidelines? If not, then never mind, not a big deal — but if maybe, then I could start a new thread. (This also ties into SE-0005 since, as far as I can tell, the “completionHandler” pattern is used exclusively in Cocoa APIs. So if there was an agreement that “onSuccess” is a better convention, the APIs could easily be translated mechanically)

— Radek

> On 26 Jan 2016, at 21:08, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> on Mon Jan 25 2016, Radosław Pietruszewski <swift-evolution at swift.org> wrote:
> 
>> Paul, let’s start a new thread about this — I was going to write about
>> the same idiom, but it’s out of scope of this review.
>> 
>> I disagree with Dave that this is just a EDSL, 
> 
> I didn't say *just* an EDSL!  EDSLs are hugely important.
> 
>> I think things like completion/success/failure handlers are a very
>> common pattern, 
> 
> That doesn't make it "not an EDSL."
> 
>> and it would be great to have consistent naming and a Guidelines
>> recommendation for them. (Usually in the context of argument names,
>> not chainable methods, which are, indeed, quite DSL-y).
> 
> Here's the problem: I don't want to make special rules for this one kind
> of EDSL, because the next declarative language that comes along will
> have the same problem with the guidelines.  I wouldn't mind saying
> something like, "mutating methods that are declarative in nature might
> not be verbs."
> 
>> 
>> 
>> — Radek
>> 
>>> On 25 Jan 2016, at 04:48, Paul Cantrell via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> 
>>> Siesta uses the widespread fluent style of attaching callbacks to a request:
>>> 
>>>    resource.load()
>>>        .onCompletion { _ in stopSpinnyThing() }
>>>        .onSuccess { _ in showHappyFace() }
>>>        .onFailure { _ in showSadFace() }
>>>        .onNewData { _ in soundTrumpets() }
>>> 
>>> These methods mutate the receiving request (by adding a callback), and the guidelines thus say that they should be named as imperative verbs. The results of that don’t seem like an improvement:
>>> 
>>>    resource.load()
>>>        .addCompletionCallback { _ in stopSpinnyThing() }
>>>        .addSuccessCallback { _ in showHappyFace() }
>>>        .addFailureCallback { _ in showSadFace() }
>>>        .addNewDataCallback { _ in soundTrumpets() }
>>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> -- 
> -Dave
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list