[Review] SE-0006 Apply API Guidelines to the Standard Library

The "too specific" I'm railing against is that naming guidance should not depend on implementation details to
the point it creates Hungarian Swiftisms.

-- E

···

On Jan 29, 2016, at 1:20 PM, Dave Abrahams <dabrahams@apple.com> wrote:

on Fri Jan 29 2016, Erica Sadun <erica-AT-ericasadun.com> wrote:

For example, for "HasNoun", I'd go with something more like
NounContainingType or NounSupplier.

Non-Abrahams Dave writes: "I like -Type for protocols that can only be
used a generic constraint, and -able/-ible for protocols that can be
“concrete” types.

And Canonical Dave replies: "But that's not how they're used. I'd
have to rename Equatable and Comparable to follow that convention."

This is the big bit though and you didn't respond here, although it's
mostly that I'm agreeing with you but what do you think about just
cutting out things that get too specific? (I say the same more or less
in the longer review email)

I don't think that's going to fly. One of the main purposes of these
API guidelines is to remove the overhead of having to figure out how to
name things, at least as much as possible. Programmers and designers
have enough to think about. Teams that accept strong and specific
coding guidelines can spend more time effectively applying their domain
expertise and less time bike-shedding trivial details.

--
-Dave

:

I agree with all of the small criticisms mentioned below by Radoslaw
except for the renaming of precondition() to require(). I think it is
an improvement that it describes an action now, just like assert().

Interestingly, I was the one that insisted on that change, as I felt
“precondition” was too much of a term-of-art and “require” would be more
accessible, but I am now regretting that decision. This function is not
conceptually an action; like “assert,” it's a declarative statement, and
“precondition” conveyed that aspect much better, IMO.

How about expect()? Should not have much string attached to it. Only thing coming to mind is the
TCL extension used for automation.

That's not bad, but to me "expect" seems more open-ended than
"require" or "precondition", i.e. "if it isn't true, then what?". I
don't assume that it's going to be fatal.

(It even feels a little like an optimization hint to me, like
"expect(self.dynamicType === BaseClass.self)". It could still be a
subclass, but the compiler would know what the common case is.)

Someone I spoke with had a good idea about this IMO. They recommended
we have debugAssert and releaseAssert (or debugRequire and
releaseRequire). I think this makes the semantics obvious and has
consistent terminology between the functions. There’s no question at
the call site what was intended.

Here's the problem with that suggestion: these things really have
completely different purposes; we don't want them to lose the semantic
distinction that "this is a sanity check (assert)" and "this is checking
whether my client is breaking his contract (precondition).”

I think that naming convention works fine as long as you think about
the behavior as tied to how the module that contains that code is
compiled, right? If you use debugAssert in a module that compiles as
debug, then that assert will be checked. If you use releaseAssert, it
will be checked in both release and debug. Maybe I’m missing something
here though...

One thing I’d really like to improve about the current naming is
making it obvious at the call site what the behavior of the function
is. I find that with the current names it’s just a memorization
game—and I’m not good at memorization :-)

You're not supposed to think about the behavior when you use it. You're
supposed to ask, "am I checking to make sure that I haven't messed up
(e.g. broken invariants), or that my client hasn't messed up
(precondition violation)?”

If that’s really the intended axis `precondition` is better than `require` or similar.

Another outlook on asserts is essentially that you should classify each potential assertion on two axes:

- semantic importance of checked invariant (e.g. “expected” vs “requirement”)
- performance impact of check (e.g. negligible, moderate overhead, or materially-slower (e.g. O(n) -> O(n^2))

…and then use a suitably-“strong” strength-of-assertion for that setting.

I think at least a few of us have been interpreting the two assertion types along these lines—in spite of the name!—whence the focus on the “what is included in which build types?” behavior.

···

On Jan 29, 2016, at 3:03 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Fri Jan 29 2016, Alex Migicovsky <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Jan 29, 2016, at 8:33 AM, Dave Abrahams via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
on Thu Jan 28 2016, Alex Migicovsky >> >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>> >>> wrote:

On Jan 27, 2016, at 3:33 PM, Jordan Rose via swift-evolution >>>>> <swift-evolution@swift.org> wrote:

On Jan 26, 2016, at 18:06, Dany St-Amant via swift-evolution >>>> >>>>>> <swift-evolution@swift.org> wrote:

Le 26 janv. 2016 à 19:39, Dave Abrahams via swift-evolution >>>>>>> <swift-evolution@swift.org> a écrit
on Tue Jan 26 2016, Charles Kissinger <swift-evolution@swift.org> wrote:

--
-Dave

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

The "too specific" I'm railing against is that naming guidance should not depend on implementation details to
the point it creates Hungarian Swiftisms.

I understand the overall concern, but I don't think these guidelines do
that. Whether something has side effects is hardly an implementation
detail.

···

on Fri Jan 29 2016, Erica Sadun <erica-AT-ericasadun.com> wrote:

-- E

On Jan 29, 2016, at 1:20 PM, Dave Abrahams <dabrahams@apple.com> wrote:

on Fri Jan 29 2016, Erica Sadun <erica-AT-ericasadun.com> wrote:

For example, for "HasNoun", I'd go with something more like
NounContainingType or NounSupplier.

Non-Abrahams Dave writes: "I like -Type for protocols that can only be
used a generic constraint, and -able/-ible for protocols that can be
“concrete” types.

And Canonical Dave replies: "But that's not how they're used. I'd
have to rename Equatable and Comparable to follow that convention."

This is the big bit though and you didn't respond here, although it's
mostly that I'm agreeing with you but what do you think about just
cutting out things that get too specific? (I say the same more or less
in the longer review email)

I don't think that's going to fly. One of the main purposes of these
API guidelines is to remove the overhead of having to figure out how to
name things, at least as much as possible. Programmers and designers
have enough to think about. Teams that accept strong and specific
coding guidelines can spend more time effectively applying their domain
expertise and less time bike-shedding trivial details.

--
-Dave

--
-Dave

I've been spending a ridiculous amount of time trying to hash out exactly what I'd prefer because this overlaps with another project I'm currently working on:

  - use nouns for unambiguously functional items without side effects (distanceTo(), successor)
  - use verbs for unambiguously procedural items
  - prefer verbs for items with side effects, whether there's mutation or other real-world effects
  - Otherwise decide what the most relevant description of the member's purpose is: to return a value or to perform an action. In such cases, name nouny-things with nouns and verby-things with verbs.

Under the current system, you could have:

// This is a mutating version
mutating func login(credential: SomeCredentialType)
-> LoginTokenType? {
    ...
    // store login time, etc in self
    ...
    return successToken
}
// This is a non-mutating version with side effects
func login(credential: SomeCredentialType)
-> LoginTokenType? {
    ...
    // store login time, etc in a file on disk
    ...
    return successToken
}

// This is a non-mutating version
func login(credential: SomeCredentialType)
-> LoginTokenType? {
    ...
    return successToken
}

All three versions are verb named as their primary purpose is to log in. But what if they're recast as tokenForCredential, with their primary purpose
being to fetch a token?

For the first example, you could refactor with a purely functional tokenForCredential and a mutating login function that updates self.

But what about the second example, that does not mutate, whose primary purpose is to return a token, but that introduces side effects by writing to disk? Should this be verb named and re-factored? (probably) If so, using "mutating"/"non-mutating" is not sufficient to offer guidance and overly specific as to implementation details. In other words, "hungarian".

One final point: I think the -ed/-ing advice is wrong. Adding "ed" isn't really creating a past tense verb (reversed). It's creating an adjective with an implied noun. Same rule for -ing. Like "ed", applying "ing" can create an adjective form with an implied subject. (Words ending with "ing" are not always gerunds. It might sound daring and frightning but it's true.)

-- E

···

On Jan 29, 2016, at 2:14 PM, Dave Abrahams <dabrahams@apple.com> wrote:

on Fri Jan 29 2016, Erica Sadun <erica-AT-ericasadun.com <http://erica-at-ericasadun.com/&gt;&gt; wrote:

The "too specific" I'm railing against is that naming guidance should not depend on implementation details to
the point it creates Hungarian Swiftisms.

I understand the overall concern, but I don't think these guidelines do
that. Whether something has side effects is hardly an implementation
detail.

The "too specific" I'm railing against is that naming guidance should
not depend on implementation details to
the point it creates Hungarian Swiftisms.

I think we agree on everything after "that." I just don't see how the
guidelines as written would do that.

···

on Fri Jan 29 2016, Erica Sadun <swift-evolution@swift.org> wrote:

-- E

On Jan 29, 2016, at 1:20 PM, Dave Abrahams <dabrahams@apple.com> wrote:

on Fri Jan 29 2016, Erica Sadun <erica-AT-ericasadun.com> wrote:

For example, for "HasNoun", I'd go with something more like
NounContainingType or NounSupplier.

Non-Abrahams Dave writes: "I like -Type for protocols that can only be
used a generic constraint, and -able/-ible for protocols that can be
“concrete” types.

And Canonical Dave replies: "But that's not how they're used. I'd
have to rename Equatable and Comparable to follow that convention."

This is the big bit though and you didn't respond here, although it's
mostly that I'm agreeing with you but what do you think about just
cutting out things that get too specific? (I say the same more or less
in the longer review email)

I don't think that's going to fly. One of the main purposes of these
API guidelines is to remove the overhead of having to figure out how to
name things, at least as much as possible. Programmers and designers
have enough to think about. Teams that accept strong and specific
coding guidelines can spend more time effectively applying their domain
expertise and less time bike-shedding trivial details.

--
-Dave

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

--
-Dave

Hear, hear!

-jcr

···

On Jan 29, 2016, at 12:29 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

The "too specific" I'm railing against is that naming guidance should not depend on implementation details to
the point it creates Hungarian Swiftisms.

The "too specific" I'm railing against is that naming guidance
should not depend on implementation details to
the point it creates Hungarian Swiftisms.

I understand the overall concern, but I don't think these guidelines do
that. Whether something has side effects is hardly an implementation
detail.

I've been spending a ridiculous amount of time trying to hash out
exactly what I'd prefer because this overlaps with another project I'm
currently working on:

  - use nouns for unambiguously functional items without side effects (distanceTo(), successor)
  - use verbs for unambiguously procedural items

This works great so far. I think you can say

  - use nouns for methods with no side effects (or only incidental ones,
    like logging)
  - use verbs for methods with significant side-effects

and you can stop there. Why does this have to be more complicated than
that?

  - prefer verbs for items with side effects, whether there's mutation or other real-world effects
  - Otherwise decide what the most relevant description of the member's purpose is: to return a value or to perform an action. In such cases, name nouny-things with nouns and verby-things with verbs.

Under the current system, you could have:

// This is a mutating version
mutating func login(credential: SomeCredentialType)
-> LoginTokenType? {
    ...
    // store login time, etc in self
    ...
    return successToken
}
// This is a non-mutating version with side effects
func login(credential: SomeCredentialType)
-> LoginTokenType? {
    ...
    // store login time, etc in a file on disk
    ...
    return successToken
}

// This is a non-mutating version
func login(credential: SomeCredentialType)
-> LoginTokenType? {
    ...
    return successToken
}

All three versions are verb named as their primary purpose is to log
in. But what if they're recast as tokenForCredential, with their
primary purpose being to fetch a token?

For the first example, you could refactor with a purely functional
tokenForCredential and a mutating login function that updates self.

But what about the second example, that does not mutate, whose primary
purpose is to return a token, but that introduces side effects by
writing to disk? Should this be verb named and re-factored? (probably)
If so, using "mutating"/"non-mutating" is not sufficient to offer
guidance and overly specific as to implementation details. In other
words, "hungarian".

One final point: I think the -ed/-ing advice is wrong. Adding "ed"
isn't really creating a past tense verb (reversed).

No, it's creating the past participle. We had this checked by a
linguist :-).

http://apple.github.io/swift-internals/api-design-guidelines/index.html
uses the correct terminology but apparently we haven't propagated the
changes up to Swift.org

*goes to fix up Swift.org*

It's creating an adjective with an implied noun. Same rule for
-ing. Like "ed", applying "ing" can create an adjective form with an
implied subject. (Words ending with "ing" are not always gerunds. It
might sound daring and frightning but it's true.)

These are the present participles. The linguist again :-)

···

on Fri Jan 29 2016, Erica Sadun <swift-evolution@swift.org> wrote:

On Jan 29, 2016, at 2:14 PM, Dave Abrahams <dabrahams@apple.com> wrote:
on Fri Jan 29 2016, Erica Sadun <erica-AT-ericasadun.com <http://erica-at-ericasadun.com/&gt;&gt; wrote:

--
-Dave

Canonical Dave:

Me:
- use nouns for unambiguously functional items without side effects (distanceTo(), successor)
- use verbs for unambiguously procedural items

This works great so far. I think you can say

- use nouns for methods with no side effects (or only incidental ones,
   like logging)
- use verbs for methods with significant side-effects

and you can stop there. Why does this have to be more complicated than
that?

Because *someone* put mutating/nonmutating rules into the guidelines. And I'm OCD enough that
they are irritating me. It's the mutating/nonmutating bits that I perceive as unneeded hungarianisms that push a
little too far into detailed advice by tying method naming to overly specific fancy rules. (Insert a joke here about
fancy cats and fussy linguistic grooming.)

One final point: I think the -ed/-ing advice is wrong. Adding "ed"
isn't really creating a past tense verb (reversed).

No, it's creating the past participle. We had this checked by a
linguist :-).

This is why I love you guys.

-- E, appreciative

Canonical Dave:

Me:
- use nouns for unambiguously functional items without side effects (distanceTo(), successor)
- use verbs for unambiguously procedural items

This works great so far. I think you can say

- use nouns for methods with no side effects (or only incidental ones,
   like logging)
- use verbs for methods with significant side-effects

and you can stop there. Why does this have to be more complicated than
that?

Because *someone* put mutating/nonmutating rules into the
guidelines.

Okay, guilty as charged already! :-)

And I'm OCD enough that they are irritating me. It's the
mutating/nonmutating bits that I perceive as unneeded hungarianisms
that push a little too far into detailed advice by tying method naming
to overly specific fancy rules. (Insert a joke here about fancy cats
and fussy linguistic grooming.)

I'm saying, why don't we replace the mutating/nonmutating stuff with
what I wrote above, and stop there? Doesn't that fix the problem?

One final point: I think the -ed/-ing advice is wrong. Adding "ed"
isn't really creating a past tense verb (reversed).

No, it's creating the past participle. We had this checked by a
linguist :-).

This is why I love you guys.

A benefit of working in a large company: an expert in <whatever> will
pop out of the woodwork to correct your mistakes.

···

on Sun Jan 31 2016, Erica Sadun <swift-evolution@swift.org> wrote:

--
-Dave

Canonical Dave:

Me:
- use nouns for unambiguously functional items without side effects (distanceTo(), successor)
- use verbs for unambiguously procedural items

This works great so far. I think you can say

- use nouns for methods with no side effects (or only incidental ones,
  like logging)
- use verbs for methods with significant side-effects

and you can stop there. Why does this have to be more complicated than
that?

Because *someone* put mutating/nonmutating rules into the
guidelines.

Okay, guilty as charged already! :-)

And I'm OCD enough that they are irritating me. It's the
mutating/nonmutating bits that I perceive as unneeded hungarianisms
that push a little too far into detailed advice by tying method naming
to overly specific fancy rules. (Insert a joke here about fancy cats
and fussy linguistic grooming.)

I'm saying, why don't we replace the mutating/nonmutating stuff with
what I wrote above, and stop there? Doesn't that fix the problem?

Why, yes. YES IT DOES.

That will do. That will do.

-- E, :)

···

On Jan 31, 2016, at 3:52 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Sun Jan 31 2016, Erica Sadun <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

One final point: I think the -ed/-ing advice is wrong. Adding "ed"
isn't really creating a past tense verb (reversed).

No, it's creating the past participle. We had this checked by a
linguist :-).

This is why I love you guys.

A benefit of working in a large company: an expert in <whatever> will
pop out of the woodwork to correct your mistakes.

--
-Dave

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