[swift-evolution] [swift-evolution-announce] [Review] SE-0169: Improve Interaction Between private Declarations and Extensions

Matthew Johnson matthew at anandabits.com
Wed Apr 12 15:24:36 CDT 2017


> On Apr 12, 2017, at 3:15 PM, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution at swift.org> wrote:
> 
> In order to evaluate this proposal, I created a table of as many relevant scenarios as I could think of, and listed how each of the proposed solutions would work there. The four access level systems I compared are:
> 
> No change: The existing Swift 3 status quo with “fileprivate” and “private”.
> 
> SE–0159: Revert to the Swift 2 meaning of “private” (file visibility) and eliminate scoped access altogether.
> 
> SE–0169: Expand “private” to include the current type and all its extensions in the same file.
> 
> Rename: Change the spelling of “private” to “scoped”, and “fileprivate” to “private”.
> 
> I ended up with a list of eight scenarios to evaluate. These are:
> 
> 1. “Simple file”, a single type with no extensions.
> 2. “Extensions”, a single type and extensions thereof.
> 3. “Sharing”, multiple types that need privileged access to each other.
> 4. “Helper visible”, the interface of a helper (or nested) type for use within the file.
> 5. “Helper hidden”, the details of a helper type that should not be visible to other types.
> 6. “Invariants”, the details of a type that should only be touched by dedicated methods.
> 7. “Multi-type”, multiple types that should not have privileged access to each other.
> 8. “Multi-type + ext”, multiple types that should not have privileged access to each other, and extensions thereof.
> 
> The entries in the table have seven possible values:
> 
> private: The “private” keyword works.
> 
> fileprivate: The “fileprivate” keyword works.
> 
> scoped: The “scoped” keyword works.
> 
> private x2: The “private” keyword works if the types are put into separate files.
> 
> fileprivate x2: The “fileprivate” keyword works if the types are put into separate files.
> 
> helper type: The goal can only be achieved by creating a helper type.
> 
> no hiding: The specified items cannot be hidden from the rest of the file.
> 
> Here is the completed and color-coded table (I hope it displays properly in this email):
> 
> 
> 
> No change
> SE–0159
> SE–0169
> Rename
> Simple file
> private
> private
> private
> private
> Extensions
> fileprivate
> private
> private
> private
> Sharing
> fileprivate
> private
> fileprivate
> private
> Helper visible
> fileprivate
> private
> fileprivate
> private
> Helper hidden
> private
> no hiding
> private
> scoped
> Invariants
> private
> no hiding
> helper type
> scoped
> Multi-type
> private
> private x2
> private
> scoped
> Multi-type + ext
> fileprivate x2
> private x2
> private
> private x2
> 
> 
> Analysis
> 
> Some people have said on-list that they view cross-type sharing as an anti-pattern. If that is true, then we can simply ignore the “Sharing” row because it would not be worth optimizing for. This hardly changes the table though, as that row is identical to the “Helper visible” row below it.
> 
> Regarding the “Invariants” row, note that a helper type can be used for this purpose under “No change” and “Rename” just as well as under “SE–0169”. The difference is that SE-0169 provides no other way to hide invariants from the rest of the type, whereas the other two have an access level suited to the purpose. Similarly, the multi-type rows can be satisfied by separate files regardless of which access system is in place.
> 
> If a person takes the view that things in the same file should naturally have access to one another, then the bottom four rows of the table can be ignored. Such a person might have the mantra, “Only put things together if they belong together”, and they would ask, “What else is in the file that you are trying to hide from?”
> 
> For someone whose primary use-case is to put one type in a file and build it up through extensions, the “Extension” row is of greatest concern. To them, any of SE–0159, SE–0169, or renaming would let them use “private” instead of “fileprivate” everywhere.
> 
> As a final remark, each of the four options has one notable benefit and one notable drawback, not all of which are apparent from the above table:
> 
> No change
> Benefit: No change to the language.
> Drawback: Must use “fileprivate” to build up a type through extensions.
> 
> SE–0159
> Benefit: Simplifies the access control model.
> Drawback: Cannot protect invariants within a file.
> 
> SE–0169
> Benefit: Cross-type sharing is clearly marked.
> Drawback: Must use a helper type to protect invariants within a file.

FWIW, a secondary drawback to SE-0169 is that the protection afforded by this helper type is permeable - the helper type can be extended anywhere inside the file.  It is more than SE-0159 but not as strong a guarantee as either no change or rename.  Extensions to the helper type will stand out much more clearly than inadvertent use of a `private` member under SE-0159 but readers still need to know they don’t exist or look for them to be sure.

> 
> Rename
> Benefit: No change to semantics.
> Drawback: Two separate keywords are changed.
> 
>  • • •
> 
> And now, having said all that, I need to go take a nap!
> 
> Once everything has percolated, I’ll come back to write a review of the current proposal.
> 
> Nevin
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170412/4faafbf5/attachment.html>


More information about the swift-evolution mailing list