[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