[SE-0088] Dispatch API names


#1

SE-0088 was accepted with revisions a month ago. However, some of the APIs just don’t feel right to me. I’ve only used DispatchQueue and DispatchSource so far, so I will only comment on those.

DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)

···

--------------------------------------------------------------
The lack of verb in the base name bothers me. The API Design Guidelines say “methods with side-effects should read as imperative verb phrases”. You could argue that the argument label “execute” serves as the verb. However, .async and .sync are most commonly used with trailing closures where the argument label is not present.

This issue was brought up during the review, but I did not see it being addressed. Why not name the methods something like .executeAsync(_:slight_smile: and .executeSync(_:)?

DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

DispatchSource subclass names
-----------------------------
Why is it DispatchSourceMemoryPressure instead of MemoryPressureDispatchSource? I don’t think I’ve ever seen subclass names where the superclass part is at the beginning of the name.

DispatchSource factory methods
------------------------------
e.g. DispatchSource.read(fileDescriptor:queue:). The API Design Guidelines mandate that factory methods begin with the prefix “make”. Indeed, DispatchSource.read might mislead people to think that a read will be performed by this method. A better name would be .makeReadSource(fileDescriptor:queue:).

And why are these factory methods on DispatchSource instead of initializers on the subclasses? ReadDispatchSource.init(fileDescriptor:queue:) would be way clearer.


(Brent Royal-Gordon) #2

DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
--------------------------------------------------------------
The lack of verb in the base name bothers me. The API Design Guidelines say “methods with side-effects should read as imperative verb phrases”. You could argue that the argument label “execute” serves as the verb. However, .async and .sync are most commonly used with trailing closures where the argument label is not present.

This issue was brought up during the review, but I did not see it being addressed. Why not name the methods something like .executeAsync(_:slight_smile: and .executeSync(_:)?

That feels a little redundant to me. It's worth remembering that the API Guidelines are a means of creating clear APIs, not an end in themselves. It's okay to deviate a little if you get a better result.

However, I could see us borrowing (and slightly modifying) terminology from Core Data:

  queue.perform { … }
  queue.performAndWait { … }

Compared to the status quo, this is clearer, a better fit for the guidelines, and better at penalizing the disfavored API.

DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

Yeah, I gave a talk about the renaming on Saturday and somebody noted that `when` reads poorly here. Fortunately, `queue.perform(after: .now() + 0.5)` reads pretty well too. :^)

···

--
Brent Royal-Gordon
Architechies


(Xiaodi Wu) #3

> DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
> --------------------------------------------------------------
> The lack of verb in the base name bothers me. The API Design Guidelines
say “methods with side-effects should read as imperative verb phrases”. You
could argue that the argument label “execute” serves as the verb. However,
.async and .sync are most commonly used with trailing closures where the
argument label is not present.
>
> This issue was brought up during the review, but I did not see it being
addressed. Why not name the methods something like .executeAsync(_:slight_smile: and
.executeSync(_:)?

That feels a little redundant to me. It's worth remembering that the API
Guidelines are a means of creating clear APIs, not an end in themselves.
It's okay to deviate a little if you get a better result.

The guideline that methods should "read as imperative verb phrases" applies
to the full name, labels and arguments and all, and not just the base name.
You'll recall that the original proposal had .asynchronously(execute:),
which is very much an imperative phrase. `.async(execute:)` was substituted
by popular demand, with "async" being regarded as a term-of-art exception.

However, I could see us borrowing (and slightly modifying) terminology
from Core Data:

        queue.perform { … }
        queue.performAndWait { … }

Compared to the status quo, this is clearer, a better fit for the
guidelines, and better at penalizing the disfavored API.

> DispatchQueue.after(when:execute:)
> ----------------------------------
> This one simply doesn’t read grammatically. For example,
`queue.after(when: .now) { … }` becomes “queue, after when now …”. Since
dispatch_after is semantically just an extended version of dispatch_async
(I think), we can name this .executeAsync(after:_:).

Yeah, I gave a talk about the renaming on Saturday and somebody noted that
`when` reads poorly here. Fortunately, `queue.perform(after: .now() + 0.5)`
reads pretty well too. :^)

Or just `queue.after(_:execute:)`, i.e. "after [this time], execute [that
routine]."

···

On Mon, Jun 20, 2016 at 9:05 PM, Brent Royal-Gordon via swift-evolution < swift-evolution@swift.org> wrote:

--

Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Matt Wright) #4

SE-0088 was accepted with revisions a month ago. However, some of the APIs just don’t feel right to me. I’ve only used DispatchQueue and DispatchSource so far, so I will only comment on those.

DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
--------------------------------------------------------------
The lack of verb in the base name bothers me. The API Design Guidelines say “methods with side-effects should read as imperative verb phrases”. You could argue that the argument label “execute” serves as the verb. However, .async and .sync are most commonly used with trailing closures where the argument label is not present.

This issue was brought up during the review, but I did not see it being addressed. Why not name the methods something like .executeAsync(_:slight_smile: and .executeSync(_:)?

DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

I replied to messages out of order but I agree, moving `.after` onto .async seems like the more natural place for it to live.

DispatchSource subclass names
-----------------------------
Why is it DispatchSourceMemoryPressure instead of MemoryPressureDispatchSource? I don’t think I’ve ever seen subclass names where the superclass part is at the beginning of the name.

I’m not so keen to remove the Dispatch prefix from the front of the source types, given that we avoided doing that for the remainder of the module.

DispatchSource factory methods
------------------------------
e.g. DispatchSource.read(fileDescriptor:queue:). The API Design Guidelines mandate that factory methods begin with the prefix “make”. Indeed, DispatchSource.read might mislead people to think that a read will be performed by this method. A better name would be .makeReadSource(fileDescriptor:queue:).

Agreed, these should probably be brought into line with that guideline.

And why are these factory methods on DispatchSource instead of initializers on the subclasses? ReadDispatchSource.init(fileDescriptor:queue:) would be way clearer.

The source types are not subclasses, due to implementation details they are protocols.

···

On Jun 20, 2016, at 5:50 PM, Darren Mo via swift-evolution <swift-evolution@swift.org> wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brandon Knope) #5

I'm not convinced that perform is clearer than async.

performAndWait *is* clearer than sync but only in context: you wouldn't know perform was async until you read it or noticed the difference with performAndWait. Nothing about *perform* on its own conveys that it's asynchronous.

Brandon

···

Sent from my iPad

On Jun 20, 2016, at 10:05 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
--------------------------------------------------------------
The lack of verb in the base name bothers me. The API Design Guidelines say “methods with side-effects should read as imperative verb phrases”. You could argue that the argument label “execute” serves as the verb. However, .async and .sync are most commonly used with trailing closures where the argument label is not present.

This issue was brought up during the review, but I did not see it being addressed. Why not name the methods something like .executeAsync(_:slight_smile: and .executeSync(_:)?

That feels a little redundant to me. It's worth remembering that the API Guidelines are a means of creating clear APIs, not an end in themselves. It's okay to deviate a little if you get a better result.

However, I could see us borrowing (and slightly modifying) terminology from Core Data:

   queue.perform { … }
   queue.performAndWait { … }

Compared to the status quo, this is clearer, a better fit for the guidelines, and better at penalizing the disfavored API.

DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

Yeah, I gave a talk about the renaming on Saturday and somebody noted that `when` reads poorly here. Fortunately, `queue.perform(after: .now() + 0.5)` reads pretty well too. :^)

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brent Royal-Gordon) #6

The guideline that methods should "read as imperative verb phrases" applies to the full name, labels and arguments and all, and not just the base name. You'll recall that the original proposal had .asynchronously(execute:), which is very much an imperative phrase. `.async(execute:)` was substituted by popular demand, with "async" being regarded as a term-of-art exception.

Right, I forgot about that. I had a vague feeling that `execute` was the verb, but the shortening obscured `async`'s role as an adverb.

···

--
Brent Royal-Gordon
Architechies


(Matt Wright) #7

> DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
> --------------------------------------------------------------
> The lack of verb in the base name bothers me. The API Design Guidelines say “methods with side-effects should read as imperative verb phrases”. You could argue that the argument label “execute” serves as the verb. However, .async and .sync are most commonly used with trailing closures where the argument label is not present.
>
> This issue was brought up during the review, but I did not see it being addressed. Why not name the methods something like .executeAsync(_:slight_smile: and .executeSync(_:)?

That feels a little redundant to me. It's worth remembering that the API Guidelines are a means of creating clear APIs, not an end in themselves. It's okay to deviate a little if you get a better result.

The guideline that methods should "read as imperative verb phrases" applies to the full name, labels and arguments and all, and not just the base name. You'll recall that the original proposal had .asynchronously(execute:), which is very much an imperative phrase. `.async(execute:)` was substituted by popular demand, with "async" being regarded as a term-of-art exception.

Right, the naming here strayed from the guidelines here under the term-of-art exception. None of the various alternatives really fit amazingly well, the async{,hronous} part of the API name communicates an important facet of what the call does. In that it goes away and executes the closure “somewhere else”. I feel this particular point is lost in example such as perform{andWait}. `.asynchronously` was an attempt to move towards the guidelines but it still missed that mark. I believe it’s still clearer to have `.async` as an exception.

However, I could see us borrowing (and slightly modifying) terminology from Core Data:

        queue.perform { … }
        queue.performAndWait { … }

Compared to the status quo, this is clearer, a better fit for the guidelines, and better at penalizing the disfavored API.

> DispatchQueue.after(when:execute:)
> ----------------------------------
> This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

Yeah, I gave a talk about the renaming on Saturday and somebody noted that `when` reads poorly here. Fortunately, `queue.perform(after: .now() + 0.5)` reads pretty well too. :^)

Or just `queue.after(_:execute:)`, i.e. "after [this time], execute [that routine].”

.after is already going to need some tweaking as I don’t believe the current incarnation is sufficiently named to avoid being ambiguous in the common case. Though, removing the label will also not help in that regard. I agree, there is probably merit in the idea of moving after to being an optional argument on `.async`.

···

On Jun 20, 2016, at 7:12 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:
On Mon, Jun 20, 2016 at 9:05 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


#8

DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

I replied to messages out of order but I agree, moving `.after` onto .async seems like the more natural place for it to live.

Yay!

DispatchSource subclass names
-----------------------------
Why is it DispatchSourceMemoryPressure instead of MemoryPressureDispatchSource? I don’t think I’ve ever seen subclass names where the superclass part is at the beginning of the name.

I’m not so keen to remove the Dispatch prefix from the front of the source types, given that we avoided doing that for the remainder of the module.

What is the rationale for keeping the Dispatch prefix anyways? (I couldn’t find it in the archives.)

DispatchSource factory methods
------------------------------
e.g. DispatchSource.read(fileDescriptor:queue:). The API Design Guidelines mandate that factory methods begin with the prefix “make”. Indeed, DispatchSource.read might mislead people to think that a read will be performed by this method. A better name would be .makeReadSource(fileDescriptor:queue:).

Agreed, these should probably be brought into line with that guideline.

Yay!

And why are these factory methods on DispatchSource instead of initializers on the subclasses? ReadDispatchSource.init(fileDescriptor:queue:) would be way clearer.

The source types are not subclasses, due to implementation details they are protocols.

Oops, missed that. Sorry.

···

On Jun 21, 2016, at 5:28 PM, Matt Wright <mww@apple.com> wrote:

On Jun 20, 2016, at 5:50 PM, Darren Mo via swift-evolution <swift-evolution@swift.org> wrote:


#9

Can you link me something that says it applies to the full name? In all the examples, the verb is always in the base name and the argument labels are always prepositions or objects (the grammar version).

And what about when a trailing closure is used? Then the verb disappears.

···

On Jun 20, 2016, at 10:12 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Mon, Jun 20, 2016 at 9:05 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
> --------------------------------------------------------------
> The lack of verb in the base name bothers me. The API Design Guidelines say “methods with side-effects should read as imperative verb phrases”. You could argue that the argument label “execute” serves as the verb. However, .async and .sync are most commonly used with trailing closures where the argument label is not present.
>
> This issue was brought up during the review, but I did not see it being addressed. Why not name the methods something like .executeAsync(_:slight_smile: and .executeSync(_:)?

That feels a little redundant to me. It's worth remembering that the API Guidelines are a means of creating clear APIs, not an end in themselves. It's okay to deviate a little if you get a better result.

The guideline that methods should "read as imperative verb phrases" applies to the full name, labels and arguments and all, and not just the base name. You'll recall that the original proposal had .asynchronously(execute:), which is very much an imperative phrase. `.async(execute:)` was substituted by popular demand, with "async" being regarded as a term-of-art exception.


(Adrian Zubarev) #10

Just yesterday I filed a bug because Data and DispatchData overlap but the api is not consistent: https://bugs.swift.org/browse/SR–1843

I never used libdispatch in depth but wanted to learn how it works to evolve my TCP module.

At first glance I spotted one wrong label name on DispatchIO:

public class func write(fromFileDescriptor: Int32, data: DispatchData, runningHandlerOn queue: DispatchQueue, handler: (data: DispatchData?, error: Int32) -> Swift.Void)
This should look like (because we write TO a file):

public class func write(toFileDescriptor: Int32, data: DispatchData, runningHandlerOn queue: DispatchQueue, handler: (data: DispatchData?, error: Int32) -> Swift.Void)
Interesting thing is also that this wasn’t proposed that way at all:

class func write(fileDescriptor: Int32, data: DispatchData, queue: DispatchQueue, handler: (DispatchData?, Int32) -> Void)

···

--
Adrian Zubarev
Sent with Airmail

Am 21. Juni 2016 um 08:40:55, Brent Royal-Gordon via swift-evolution (swift-evolution@swift.org) schrieb:

The guideline that methods should "read as imperative verb phrases" applies to the full name, labels and arguments and all, and not just the base name. You'll recall that the original proposal had .asynchronously(execute:), which is very much an imperative phrase. `.async(execute:)` was substituted by popular demand, with "async" being regarded as a term-of-art exception.

Right, I forgot about that. I had a vague feeling that `execute` was the verb, but the shortening obscured `async`'s role as an adverb.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #11

> DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
> --------------------------------------------------------------
> The lack of verb in the base name bothers me. The API Design Guidelines
say “methods with side-effects should read as imperative verb phrases”. You
could argue that the argument label “execute” serves as the verb. However,
.async and .sync are most commonly used with trailing closures where the
argument label is not present.
>
> This issue was brought up during the review, but I did not see it being
addressed. Why not name the methods something like .executeAsync(_:slight_smile: and
.executeSync(_:)?

That feels a little redundant to me. It's worth remembering that the API
Guidelines are a means of creating clear APIs, not an end in themselves.
It's okay to deviate a little if you get a better result.

The guideline that methods should "read as imperative verb phrases"
applies to the full name, labels and arguments and all, and not just the
base name. You'll recall that the original proposal had
.asynchronously(execute:), which is very much an imperative phrase.
`.async(execute:)` was substituted by popular demand, with "async" being
regarded as a term-of-art exception.

Can you link me something that says it applies to the full name?

In the document, all examples for verb phrases and noun phrases include the
labels and arguments (e.g.: "distance to y"). In the subsequent section, it
outlines scenarios for labeling the first argument when it forms part of a
prepositional phrase or other grammatical phrase; in either case, the label
is read as part of the phrase. The only exception to this convention is
explicitly outlined: "Initializer and factory method calls should form a
phrase that does not include the first argument."

In all the examples, the verb is always in the base name and the argument
labels are always prepositions or objects (the grammar version).

Yes; these names are exceptional in that way. But it is apt: the base name
holds the distinguishing feature (async vs. sync), whereas the verb here is
correctly a label for the argument, which is a code block to be executed.

And what about when a trailing closure is used? Then the verb disappears.

Which is fine, because the verb couldn't really be anything else
(`doNotExecute`?). To me, at least, braces surrounding code blocks
satisfactorily imply 'do' or 'execute,' much like parentheses around
arguments are sometimes taken to imply 'with' or 'using.'

···

On Tue, Jun 21, 2016 at 6:44 PM, Darren Mo <darren.mo@me.com> wrote:

On Jun 20, 2016, at 10:12 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Mon, Jun 20, 2016 at 9:05 PM, Brent Royal-Gordon via swift-evolution < > swift-evolution@swift.org> wrote:


#12

What do you think of the names .executeAsync/.executeSync or .asyncExecute/.syncExecute?

···

On Jun 21, 2016, at 5:24 PM, Matt Wright <mww@apple.com> wrote:

On Jun 20, 2016, at 7:12 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:
On Mon, Jun 20, 2016 at 9:05 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
--------------------------------------------------------------
The lack of verb in the base name bothers me. The API Design Guidelines say “methods with side-effects should read as imperative verb phrases”. You could argue that the argument label “execute” serves as the verb. However, .async and .sync are most commonly used with trailing closures where the argument label is not present.

This issue was brought up during the review, but I did not see it being addressed. Why not name the methods something like .executeAsync(_:slight_smile: and .executeSync(_:)?

That feels a little redundant to me. It's worth remembering that the API Guidelines are a means of creating clear APIs, not an end in themselves. It's okay to deviate a little if you get a better result.

The guideline that methods should "read as imperative verb phrases" applies to the full name, labels and arguments and all, and not just the base name. You'll recall that the original proposal had .asynchronously(execute:), which is very much an imperative phrase. `.async(execute:)` was substituted by popular demand, with "async" being regarded as a term-of-art exception.

Right, the naming here strayed from the guidelines here under the term-of-art exception. None of the various alternatives really fit amazingly well, the async{,hronous} part of the API name communicates an important facet of what the call does. In that it goes away and executes the closure “somewhere else”. I feel this particular point is lost in example such as perform{andWait}. `.asynchronously` was an attempt to move towards the guidelines but it still missed that mark. I believe it’s still clearer to have `.async` as an exception.


#13

Should I create a bug report for changing `DispatchQueue.after` and `DispatchSource.read`?

Darren

···

On Jun 21, 2016, at 7:35 PM, Darren Mo <darren.mo@me.com> wrote:

On Jun 21, 2016, at 5:28 PM, Matt Wright <mww@apple.com <mailto:mww@apple.com>> wrote:

On Jun 20, 2016, at 5:50 PM, Darren Mo via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

I replied to messages out of order but I agree, moving `.after` onto .async seems like the more natural place for it to live.

Yay!

DispatchSource subclass names
-----------------------------
Why is it DispatchSourceMemoryPressure instead of MemoryPressureDispatchSource? I don’t think I’ve ever seen subclass names where the superclass part is at the beginning of the name.

I’m not so keen to remove the Dispatch prefix from the front of the source types, given that we avoided doing that for the remainder of the module.

What is the rationale for keeping the Dispatch prefix anyways? (I couldn’t find it in the archives.)

DispatchSource factory methods
------------------------------
e.g. DispatchSource.read(fileDescriptor:queue:). The API Design Guidelines mandate that factory methods begin with the prefix “make”. Indeed, DispatchSource.read might mislead people to think that a read will be performed by this method. A better name would be .makeReadSource(fileDescriptor:queue:).

Agreed, these should probably be brought into line with that guideline.

Yay!

And why are these factory methods on DispatchSource instead of initializers on the subclasses? ReadDispatchSource.init(fileDescriptor:queue:) would be way clearer.

The source types are not subclasses, due to implementation details they are protocols.

Oops, missed that. Sorry.


(Matt Wright) #14

Just yesterday I filed a bug because Data and DispatchData overlap but the api is not consistent: https://bugs.swift.org/browse/SR–1843

I never used libdispatch in depth but wanted to learn how it works to evolve my TCP module.

At first glance I spotted one wrong label name on DispatchIO:

public class func write(fromFileDescriptor: Int32, data: DispatchData, runningHandlerOn queue: DispatchQueue, handler: (data: DispatchData?, error: Int32) -> Swift.Void)

This should look like (because we write TO a file):

public class func write(toFileDescriptor: Int32, data: DispatchData, runningHandlerOn queue: DispatchQueue, handler: (data: DispatchData?, error: Int32) -> Swift.Void)

Please file a bug for this and I’ll get it fixed.

···

On Jun 21, 2016, at 1:24 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

Interesting thing is also that this wasn’t proposed that way at all:

class func write(fileDescriptor: Int32, data: DispatchData, queue: DispatchQueue, handler: (DispatchData?, Int32) -> Void)

--
Adrian Zubarev
Sent with Airmail

Am 21. Juni 2016 um 08:40:55, Brent Royal-Gordon via swift-evolution (swift-evolution@swift.org) schrieb:

> The guideline that methods should "read as imperative verb phrases" applies to the full name, labels and arguments and all, and not just the base name. You'll recall that the original proposal had .asynchronously(execute:), which is very much an imperative phrase. `.async(execute:)` was substituted by popular demand, with "async" being regarded as a term-of-art exception.

Right, I forgot about that. I had a vague feeling that `execute` was the verb, but the shortening obscured `async`'s role as an adverb.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jordan Rose) #15

I honestly want these to stay light. I like perform/performAndWait fine, but executeAsync/asyncExecute seem overly verbose. They’re more English-like but don’t actually add any clarity, in that I think it’s really quite clear what the API does.

Jordan

···

On Jun 21, 2016, at 16:46, Darren Mo via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 21, 2016, at 5:24 PM, Matt Wright <mww@apple.com <mailto:mww@apple.com>> wrote:

On Jun 20, 2016, at 7:12 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Mon, Jun 20, 2016 at 9:05 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

DispatchQueue.async(execute:) and DispatchQueue.sync(execute:)
--------------------------------------------------------------
The lack of verb in the base name bothers me. The API Design Guidelines say “methods with side-effects should read as imperative verb phrases”. You could argue that the argument label “execute” serves as the verb. However, .async and .sync are most commonly used with trailing closures where the argument label is not present.

This issue was brought up during the review, but I did not see it being addressed. Why not name the methods something like .executeAsync(_:slight_smile: and .executeSync(_:)?

That feels a little redundant to me. It's worth remembering that the API Guidelines are a means of creating clear APIs, not an end in themselves. It's okay to deviate a little if you get a better result.

The guideline that methods should "read as imperative verb phrases" applies to the full name, labels and arguments and all, and not just the base name. You'll recall that the original proposal had .asynchronously(execute:), which is very much an imperative phrase. `.async(execute:)` was substituted by popular demand, with "async" being regarded as a term-of-art exception.

Right, the naming here strayed from the guidelines here under the term-of-art exception. None of the various alternatives really fit amazingly well, the async{,hronous} part of the API name communicates an important facet of what the call does. In that it goes away and executes the closure “somewhere else”. I feel this particular point is lost in example such as perform{andWait}. `.asynchronously` was an attempt to move towards the guidelines but it still missed that mark. I believe it’s still clearer to have `.async` as an exception.

What do you think of the names .executeAsync/.executeSync or .asyncExecute/.syncExecute?


(Matt Wright) #16

Feel free to create one for .read, I already have a radar that covers .after

···

On Jul 7, 2016, at 7:16 PM, Darren Mo <darren.mo@me.com> wrote:

Should I create a bug report for changing `DispatchQueue.after` and `DispatchSource.read`?

Darren

On Jun 21, 2016, at 7:35 PM, Darren Mo <darren.mo@me.com> wrote:

On Jun 21, 2016, at 5:28 PM, Matt Wright <mww@apple.com> wrote:

On Jun 20, 2016, at 5:50 PM, Darren Mo via swift-evolution <swift-evolution@swift.org> wrote:
DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

I replied to messages out of order but I agree, moving `.after` onto .async seems like the more natural place for it to live.

Yay!

DispatchSource subclass names
-----------------------------
Why is it DispatchSourceMemoryPressure instead of MemoryPressureDispatchSource? I don’t think I’ve ever seen subclass names where the superclass part is at the beginning of the name.

I’m not so keen to remove the Dispatch prefix from the front of the source types, given that we avoided doing that for the remainder of the module.

What is the rationale for keeping the Dispatch prefix anyways? (I couldn’t find it in the archives.)

DispatchSource factory methods
------------------------------
e.g. DispatchSource.read(fileDescriptor:queue:). The API Design Guidelines mandate that factory methods begin with the prefix “make”. Indeed, DispatchSource.read might mislead people to think that a read will be performed by this method. A better name would be .makeReadSource(fileDescriptor:queue:).

Agreed, these should probably be brought into line with that guideline.

Yay!

And why are these factory methods on DispatchSource instead of initializers on the subclasses? ReadDispatchSource.init(fileDescriptor:queue:) would be way clearer.

The source types are not subclasses, due to implementation details they are protocols.

Oops, missed that. Sorry.


(Karl) #17

I just discovered this thread by accident - thank the Lord I’m not the only one who feels like this about the new Dispatch API!

Should I create a bug report for changing `DispatchQueue.after` and `DispatchSource.read`?

Darren

DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

I replied to messages out of order but I agree, moving `.after` onto .async seems like the more natural place for it to live.

Yay!

So long as the signature then reads grammatically - I had a little battle about this yesterday: http://comments.gmane.org/gmane.comp.lang.swift.evolution/23867

To summarise:
- “after” should take a plain time interval
- “deadline” is just simply the wrong word - means something else entirely
- since we can’t take an interval without a clock, we need a default clock
- but the nuances with those clocks are very important and a source of subtle bugs, so we should also ask for precise intention

=> I think we should split DispatchQueue.after() based on clock type. This would allow us to provide a default value for “now”, meaning we can also accept plain time intervals, as the resulting API would be explicit about the clock nuances that are often overlooked.

DispatchSource subclass names
-----------------------------
Why is it DispatchSourceMemoryPressure instead of MemoryPressureDispatchSource? I don’t think I’ve ever seen subclass names where the superclass part is at the beginning of the name.

I’m not so keen to remove the Dispatch prefix from the front of the source types, given that we avoided doing that for the remainder of the module.

What is the rationale for keeping the Dispatch prefix anyways? (I couldn’t find it in the archives.)

I would also like to know this. I really don’t like typing Dispatch... every time. It doesn’t seem to be very forgiving with code-completion.

Also, dispatch code tends to contain a fair amount of nested closures. It’s nice to keep the line lengths short in that case.

Karl

···

On 8 Jul 2016, at 04:16, Darren Mo via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 21, 2016, at 7:35 PM, Darren Mo <darren.mo@me.com <mailto:darren.mo@me.com>> wrote:
On Jun 21, 2016, at 5:28 PM, Matt Wright <mww@apple.com <mailto:mww@apple.com>> wrote:

On Jun 20, 2016, at 5:50 PM, Darren Mo via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:


(Matt Wright) #18

I just discovered this thread by accident - thank the Lord I’m not the only one who feels like this about the new Dispatch API!

Should I create a bug report for changing `DispatchQueue.after` and `DispatchSource.read`?

Darren

DispatchQueue.after(when:execute:)
----------------------------------
This one simply doesn’t read grammatically. For example, `queue.after(when: .now) { … }` becomes “queue, after when now …”. Since dispatch_after is semantically just an extended version of dispatch_async (I think), we can name this .executeAsync(after:_:).

I replied to messages out of order but I agree, moving `.after` onto .async seems like the more natural place for it to live.

Yay!

To somewhat follow up on Darren’s suggestion: after internal discussion, moving `.after` into `.async` isn’t as good an idea as I had hoped. The behaviour of `.after`, both in execution and performance, differ substantially from `.async`.

So long as the signature then reads grammatically - I had a little battle about this yesterday: http://comments.gmane.org/gmane.comp.lang.swift.evolution/23867

To summarise:
- “after” should take a plain time interval
- “deadline” is just simply the wrong word - means something else entirely
- since we can’t take an interval without a clock, we need a default clock
- but the nuances with those clocks are very important and a source of subtle bugs, so we should also ask for precise intention

=> I think we should split DispatchQueue.after() based on clock type. This would allow us to provide a default value for “now”, meaning we can also accept plain time intervals, as the resulting API would be explicit about the clock nuances that are often overlooked.

I don’t think this topic needs forking and rehashing on this thread too.

DispatchSource subclass names
-----------------------------
Why is it DispatchSourceMemoryPressure instead of MemoryPressureDispatchSource? I don’t think I’ve ever seen subclass names where the superclass part is at the beginning of the name.

I’m not so keen to remove the Dispatch prefix from the front of the source types, given that we avoided doing that for the remainder of the module.

What is the rationale for keeping the Dispatch prefix anyways? (I couldn’t find it in the archives.)

I would also like to know this. I really don’t like typing Dispatch... every time. It doesn’t seem to be very forgiving with code-completion.

This was covered somewhat during initial evolution, after discussion with the core team we decided to keep the Dispatch prefix. Several of the class names make more contextual sense with a Dispatch prefix, where they would not otherwise; Queues, Groups, etc. Secondly, Dispatch is implicitly imported by Foundation and we feel that keeping the prefix is clearer to the developer what it is you’re actually using.

···

On Jul 14, 2016, at 3:44 AM, Karl <razielim@gmail.com> wrote:

On 8 Jul 2016, at 04:16, Darren Mo via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 21, 2016, at 7:35 PM, Darren Mo <darren.mo@me.com> wrote:
On Jun 21, 2016, at 5:28 PM, Matt Wright <mww@apple.com> wrote:

On Jun 20, 2016, at 5:50 PM, Darren Mo via swift-evolution <swift-evolution@swift.org> wrote:

Also, dispatch code tends to contain a fair amount of nested closures. It’s nice to keep the line lengths short in that case.

Karl