SE-0261: Identifiable Protocol

No, it's not a feature to prevent the use of a protocol through the use of common names for requirements when the name has no single common use.

3 Likes

Well, I guess we'll have to agree to disagree then.

Collection.count isn't named Collection.elementCount just because a collection type might have other notions of count (as, for example, does String); Equatable.== isn't named Equatable.equalForThePurposesOfEquatable just because types might have multiple notions of equality.

Constraining the semantics of members of conforming types, as they are most obviously named, is precisely one of the points of having a protocol.

3 Likes

That's hardly the point I or anyone else was making. And your argument might make sense if id had a single, common usage across both programming and the English language, but it doesn't. This thread has already pointed out the difference between reference and value identity, and id is further overloaded in the industry at large. So your fundamental assertion that id is "most obviously named" is false just from the discussion in this thread.

I think you misunderstand my point, then. It's precisely because id on its own does not imply a single notion of identity that I argue that it's a feature for the requirement to be named Identifier.id, because then it bestows on conforming types the single, common usage that the name itself does not imply. That is the whole point of the argument.

It does not detract from the argument (in fact, it enhances it) if most usages of id don't imply record identity; the only premise that's required is users who reach for a member name to describe record identity tend to reach for id.

1 Like

In that case we're back to the original issue here: id is already used in a variety of contexts inconstent with Identifiable's use, and attempting to unify around such a commonly used name doesn't buy us anything, just pain for people trying to adopt the protocol. You can achieve the same goal with a different name just as well.

3 Likes

For the record, RxDataSources has the IdentifiableType protocol. It doesn't use id. And it blends in all code bases I've met quite smoothly. As all nice utility protocols, it does not try to rule the world. Instead, humble, it waits for types to opt in for its services, and does not beg for attention.

Again, I think we'll have to agree to disagree. My point is that what you describe as "pain" is the feature. It's a syntactic barrier that stops existing types with a notion of identity incompatible with Identifiable from being conformed without the author actually undertaking the effort to align semantics.

1 Like

That's an argument against using id. If a developer has a type which already has an id variable, attempting to conform to Identifiable would be automatic, and the developer wouldn't be prompted to use a valid identifier. Given we've already established both problematic usage in the simple identity case, and in the the more widespread usage case, using a less common name is more likely to force the developer to "undertake the effort to align semantics".

1 Like

I am still interested in seeing concrete examples of such types for which an Identifiable conformance makes sense. Specifically, I am interested in seeing the other identifier-related properties and understanding which one would be the correct one to use with an Identifiable conformance.

2 Likes

I love the name id but the world would not end of it was named identity. In fact I would not be mad if we took the Reactjs way of making something unique and just call the property key, what about .keyId? This shed is going to have the best name.

+1 from me (with the caveat below), and the property should definitely be spelled id . I’ve been wracking my brain trying to think of a use for the id spelling on any model type that isn’t semantically equivalent to the use case defined by the protocol.

In all my years of experience writing software, I’ve never come across a property spelled id that wasn’t a record id. Have I seen it spelled differently? Sure. id , _id, identifier... but id is by far the most common I’ve seen.

I would like to see the default implementation using object identifier removed, as it seems to add confusion and will be a probable footgun, especially for new developers.

2 Likes

Please keep the tone civil and respectful. This was uncalled for, is hostile and not conducive to a constructive conversation about the merits of the proposal.

7 Likes

-1.

I think the Identifiable protocol is a good idea, but I think that the automatic conformance for classes could be a potential pitfall.

As the identifier is supposed to be unique, what about uid which is still common enough to be understandable, and short enough to remain convenient.

There has been a lot of arguing over the last 40 or so posts over whether the name should be the acronym id or spelled out as a word, identifier/identity.

First, I will say I actually do not care which way the final decision lands.

But then I want to add that the name‐clash argument is entirely unhelpful towards that decision.

Others have said above that id would clash with names in their projects, but that identifier would stay nicely out of the way. However, in many of the projects I have been involved with, identifier would clash with all sorts of things, but id would stay out of the way. (@ahti said the same earlier.)

Ultimately, since id, identifier and identity are semantically identical, all three can be found used to refer to record identity, and all three can be found used to refer to other kinds of identity. That means the name‐clash and easy‐to‐slot‐in arguments apply equally to all three names. The only difference is who has trouble and who has it easy. These name‐clash arguments are useful only in choosing between the id/identifier/identity group and the recordID/recordIdentifier/recordIdentity group, because those are semantically more specific and actually would reduce unwanted collisions without forcing them on someone else instead. If that is really what you want to argue, go ahead. (But from what I read, it does not seem like anyone here really wants it to go that direction.)

The choice between the semantically identical id, identifier and identity really can only be made based on understandability, brevity, search‐ability, or something similar. If you prefer one over the other, make your case in one of those areas. Please refrain from making arguments that amount to “I shouldn’t have to adjust my code; it’s the other developers who should.”

A silver lining in all of this is that it is demonstrating how helpful it would be to have some standard name at the level of the standard library. RxDataSources has been brought up as an example using identity, and since not everyone uses that pattern, it causes trouble four half of us. Now we have SwiftUI’s id property, which causes trouble for the other half of us. It isn’t the library authors’ fault that they conflict. Neither library was built on top of the either. Maybe neither’s author even new of the other. But if a client wants to link against both libraries, now there are two names to support and two names to get out of the way of. Having something in the standard library—no matter what it is called—will cause some initial code churn, but it will definitely simplify things for the whole library graph over the long term.

19 Likes

id is not a keyword, it's a typedef. You can in fact have a property named id in an Objective-C class.

recordIdentifier seems fine to me, given it makes the type of id explicit and rather unlikely to collide with existing user code.

2 Likes

If we're going to go in this direction, then I think the protocol should be IdentifiableRecord. Even so the member would be more succinctly recordID, I think.


But again, I would reiterate that not colliding with user code is contrary to one of the design principles of Swift protocols. The search function here isn't great for surfacing the original text, but on these forums at least two principles have been enunciated:

  • Protocols aren't bags of syntax; they carry semantics.
  • Protocol conformance can be discovered.

The mental model is this: one can create a bunch of types, discover that they share something syntactically and semantically in common, then formalize it in a protocol to which the types can then be conformed. Hence Swift's robust support for retroactive conformance. The idea that the protocol should have syntactic requirements that potentially conforming types would almost never choose if the protocol didn't exist is a repudiation of this mental model.

This mental model isn't purely theoretical: it's essentially what we're doing here, discovering that a protocol currently vended by SwiftUI has broader applications and can be conformed to by a wide variety of existing types. Adopting the practice of choosing obscure names for protocol requirements has the practical implication, therefore, that new protocols would always cause an increase in the API surface area of conforming types even if those types already fit the semantics perfectly. This would be quite unfortunate if adopted pervasively for future additions to the standard library.

8 Likes

I think this should a be non goal. lets not fileprivate this.

8 Likes

Huh, you're absolutely right! Don't know where i picked that up from, maybe the syntax highlighting? Sorry for the confusion :sweat_smile: