[Review] SE-0159: Fix Private Access Levels

I’ll second the -1 and the reference to Drew’s post, with the added comment that the concern with extensions could be easily solved simply by giving extensions access to private members of the extended type as long as those extensions are in the same module/submodule (or file, if you prefer, but I don’t). This would probably eliminate almost all of the use cases for fileprivate, as well as freeing us from the sometimes clumsy situation where we’re rather artificially forced to use files as a scope, instead enabling us to organize code into files as is appropriate for the project.

Charles

···

On Mar 20, 2017, at 9:33 PM, Greg Parker via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 20, 2017, at 4:54 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md

-1. I yield the remainder of my time to Drew Crawford who satisfactorily explained my concerns.

I also disagree with the proposal, and Drew's explanation is spot on.

I wonder if there is a way to basically accept that this is what we want to do, but delay implementing it until we have other changes to make to the access system (e.g. submodules) at the same time?

If things like that are scoped for Swift 5, then I would say delay implementing this until then. If it will be longer than that, we may as well fix it now.

···

On Mar 21, 2017, at 2:07 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 20, 2017, at 4:54 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md

  • What is your evaluation of the proposal?

I'm torn. During the SE-0025 review, I argued against scoped private. I still think it was a mistake to add it. But we did, it's out there, and I don't want to introduce churn unnecessarily.

Long ago, judges realized the problems caused by re-litigating old disputes and created a doctrine called "stare decisis": standing by things decided. That doesn't mean they won't correct obvious mistakes, but it does mean that they default to upholding the precedent they've already set. I think that would be a wise course here.

I personally would prefer to have Swift behave as SE-0159 proposes. But if the core team thinks this is going to come out 50/50—that is, this change will help about as many people as it hurts—I think they should reject this proposal and keep the status quo. I really don't want to write another review next year for SE-0289 "Reintroduce Scoped Private".

--
Brent Royal-Gordon
Architechies

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

-1 on this as well for similar reasons. Places where I use fileprivate (aside from what was automatically migrated by Xcode) can be counted on fingers of one or two hands.

I feel that this proposal is reverting something without offering an alternative solution.

···

On Mar 21, 2017, at 3:33 AM, Greg Parker via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 20, 2017, at 4:54 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md

-1. I yield the remainder of my time to Drew Crawford who satisfactorily explained my concerns.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

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

+1

   • What is your evaluation of the proposal?

Makes the language easier to understand, lowers cognitive load during coding.

Is it really a problem for cognitive load during coding? In a world where protocol extensions defined default methods introducing back the nice and easy to understand concept of polymorphism by reference type where casting an instances class that overrides the method declared in the protocol extensions decides which method is actually executed... well, having to juggle file and scope based access levels breaks the camel's back?

I remain unconvinced of this, no offense meant Rien.

···

Sent from my iPhone

On 21 Mar 2017, at 07:05, Rien via swift-evolution <swift-evolution@swift.org> wrote:

I also hope this will pave the way for a overhaul of the access level system including modularization.

   • Is the problem being addressed significant enough to warrant a change to Swift?

yes.

   • Does this proposal fit well with the feel and direction of Swift?

Yes

   • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

private vs fileprivate seems swift-only, as such I have no comparison.

   • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Followed and participated in the discussions.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: Balancingrock (Rien) · GitHub
Project: http://swiftfire.nl

On 21 Mar 2017, at 00:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

   • What is your evaluation of the proposal?
   • Is the problem being addressed significant enough to warrant a change to Swift?
   • Does this proposal fit well with the feel and direction of Swift?
   • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
   • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md
Thank you,

-Doug

Review Manager

_______________________________________________
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

Forgot to cc.

···

Sent from my iPhone

On 21 Mar 2017, at 07:43, Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 21 Mar 2017, at 02:33, Greg Parker via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 20, 2017, at 4:54 PM, Douglas Gregor <dgregor@apple.com> wrote:

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md

-1. I yield the remainder of my time to Drew Crawford who satisfactorily explained my concerns.

-1 here as well, fully support Drew Crawford's points too.

To add my own 2c to it, I would say better time would be spent gathering data on number of bugs, severity, performance and more correlated to the (growing) use of Swift for example rather than just vocally discuss what is Swifty and what is not, talk about safety by default and performance to drive our community decisions without tracking those kpi's (data driven decisions). As much as it could be improved, Mozilla's AreWeFastYet.org's project is a direction we could explore.

--
Greg Parker gparker@apple.com Runtime Wrangler

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

Perhaps it was a mistake, but I purposefully did not go into too much detail in the proposal because I think this debate is purely a question of philosophy on Swift and its language features. I did not want to add un-necessary bloat that would have added little rationalisation. Let me try to explain the holes in the proposal by answering your review:

I disagree quite strongly with the proposal.

First, the document draws conclusions without apparent supporting evidence, e.g.

> Since the release of Swift 3, the access level change of SE–0025 was met with dissatisfaction by a substantial proportion of the general Swift community. Those changes can be viewed as actively harmful, the new requirement for syntax/API changes.
What is “dissatisfaction by a substantial proportion of the general Swift community”? How was this measured/determined?

It’s not feasible to measure precisely the feeling of a whole community. But we get a feeling for it by following the mailing-list, by talking to colleagues, by reading twitter, etc… And it think we all agree that the debate is highly divisive and that a “substantial proportion” of the community was dissatisfied: I’m not arguing that it is less or more than a majority. I’m just saying that we’ve seen a lot of talk against the original change.

What was done to control for the population happy with SE-0025 who would e.g. not be likely to take up pitchforks?

That’s why its important we have this debate now.

Who argues these changes are “actively harmful” and where were they during SE-0025?

The proposal makes the argument that the changes are actively harmful. It’s now up to debate. By the way, even if several people (including me) were already against this proposal during the review, I don’t see why anybody would not have the right to change his mind, especially after several months of production usage and argue differently now.

> subtly encourages overuse of scoped access control and discourages the more reasonable default
Who claims that scoped access is “overused” and what is their argument for doing so?
Why is “fileprivate” the “more reasonable default”? In fact neither fileprivate *nor* private are default (reasonable or not!). Internal is the default. Nor does this proposal suggest we change that. So this seems a very strange statement.

By default, I did not mean the syntactic default of the language but the access modifier users will use “by default” when trying to restrict visibility. In most languages, that keyword is “private” so its valid to say that newcomers to the language will “default” to using that one. If the proposal is accepted, file-scoped private will regain that status.

> But is that distinction between private and fileprivate actively used by the larger community of Swift developers?
Yes. To cite some evidence, here are codebases I actively maintain:

> codebase | private # | fileprivate # | ratio |

>--------------------------------------------------------|-----------|---------------|-------|

> "M" (proprietary) | 486 | 249 | 2x |

> "N"(proprietary) | 179 | 59 | 3x |

> NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | 1 | 15x |

> atbuild GitHub - AnarchyTools/atbuild: The Anarchy Tools build tool | 54 | 5 | 11x |

So from my chair, not only is the distinction useful, but scoped access control (private) is overwhelmingly (2-15x) more useful than fileprivate.

My own statistics in my projects show the contrary. At best, this shows how divisive this feature is. During the discussion of this proposal, it was argued that making decisions based upon project statistics would be dangerous:

In old code, statistics could be biased by the migrator having replaced all previous instances of private by fileprivate.
In new code, satistics could be biased by people using private because of it being the “soft-default”, regardless of proper semantics.

> And if it were used pervasively, would it be worth the cognitive load and complexity of keeping two very similar access levels in the language? This proposal argues that answer to both questions is no

This proposal does not make any later argument about “cognitive load” or “complexity” I can identify. Did the proposal get truncated?

Sorry if I did not state it explicitly, but I see any feature/keyword added to the language as “additional complexity”. And that complexity is completely worth it when the feature adds significant expressivity. I'm just arguing that the additional scope-based access modifier does not provide enough differentiation to be worth that complexity.

What is stated (without evidence) is that "it is extremely common to use several extensions within a file” and that use of “private” is annoying in that case. I now extend the above table

> codebase | private # | fileprivate # | ratio | # of extensions (>=3 extensions in file) |

>--------------------------------------------------------|-----------|---------------|-------|------------------------------------------|

> "M" (proprietary) | 486 | 249 | 2x | 48 |

> "N"(proprietary) | 179 | 59 | 3x | 84 |

> NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | 1 | 15x | 3 |

> atbuild GitHub - AnarchyTools/atbuild: The Anarchy Tools build tool | 54 | 5 | 11x | 6 |

in order to demonstrate in my corner of Swift this is not “extremely common”, and is actually less popular than language features the proposal alleges aren’t used.

My point here is that **different people in different corners of the community program Swift differently and use different styles**. I can definitely empathize with folks like the author who use extensions to group functions and are annoyed that their favorite visibility modifier grew four extra characters. Perhaps we can come up with a keyword that is more succint.

I agree that different people in different corners use different styles. But you could use that argument to validate many features which would make a group of users happy; but all those feature together would just add bloat to the language. Swift has been known to be a very opinionated language, to keep the language simple yet expressive.

···

On 21 Mar 2017, at 02:26, Drew Crawford via swift-evolution <swift-evolution@swift.org> wrote:
However, that is no reason to take away features from working codebases. A scoped access modifier is perhaps my favorite feature in Swift 3. Let’s not throw stuff away because it adds extra characters to one programming style.

Finally, SE-0025 establishes clear motivation for the scoped access modifier:

> Currently, the only reliable way to hide implementation details of a class is to put the code in a separate file and mark it as private. This is not ideal for the following reasons:

> It is not clear whether the implementation details are meant to be completely hidden or can be shared with some related code without the danger of misusing the APIs marked as private. If a file already has multiple classes, it is not clear if a particular API is meant to be hidden completely or can be shared with the other classes.

> It forces a one class per file structure, which is very limiting. Putting related APIs and/or related implementations in the same file helps ensure consistency and reduces the time to find a particular API or implementation. This does not mean that the classes in the same file need to share otherwise hidden APIs, but there is no way to express such sharability with the current access levels.

As far as I can see, the proposal does not actually address or acknowledge these problems at all, but cheerfully returns us to them. It would be a mistake to deprecate this feature without examining at all why we introduced it. And realistically we need new solutions to those problems before removing the existing one.

Drew

On March 20, 2017 at 6:54:55 PM, Douglas Gregor (dgregor@apple.com <mailto:dgregor@apple.com>) wrote:

Hello Swift community,

The review of SE–0159 “Fix Private Access Levels” begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md Reply text Other replies What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

What is your evaluation of the proposal? Is the problem being addressed significant enough to warrant a change to Swift? Does this proposal fit well with the feel and direction of Swift? If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those? How much effort did you put into your review? A glance, a quick reading, or an in-depth study? More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md Thank you,

-Doug

Review Manager

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

I disagree quite strongly with the proposal.

First, the document draws conclusions without apparent supporting evidence, e.g.

> Since the release of Swift 3, the access level change of SE–0025 was met with dissatisfaction by a substantial proportion of the general Swift community. Those changes can be viewed as actively harmful, the new requirement for syntax/API changes.
What is “dissatisfaction by a substantial proportion of the general Swift community”? How was this measured/determined?
What was done to control for the population happy with SE-0025 who would e.g. not be likely to take up pitchforks?
Who argues these changes are “actively harmful” and where were they during SE-0025?
> subtly encourages overuse of scoped access control and discourages the more reasonable default
Who claims that scoped access is “overused” and what is their argument for doing so?
Why is “fileprivate” the “more reasonable default”? In fact neither fileprivate *nor* private are default (reasonable or not!). Internal is the default. Nor does this proposal suggest we change that. So this seems a very strange statement.
> But is that distinction between private and fileprivate actively used by the larger community of Swift developers?
Yes. To cite some evidence, here are codebases I actively maintain:

> codebase | private # | fileprivate # | ratio |

>--------------------------------------------------------|-----------|---------------|-------|

> "M" (proprietary) | 486 | 249 | 2x |

> "N"(proprietary) | 179 | 59 | 3x |

> NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | 1 | 15x |

> atbuild GitHub - AnarchyTools/atbuild: The Anarchy Tools build tool | 54 | 5 | 11x |

So from my chair, not only is the distinction useful, but scoped access control (private) is overwhelmingly (2-15x) more useful than fileprivate.

> And if it were used pervasively, would it be worth the cognitive load and complexity of keeping two very similar access levels in the language? This proposal argues that answer to both questions is no

This proposal does not make any later argument about “cognitive load” or “complexity” I can identify. Did the proposal get truncated?

What is stated (without evidence) is that "it is extremely common to use several extensions within a file” and that use of “private” is annoying in that case. I now extend the above table

> codebase | private # | fileprivate # | ratio | # of extensions (>=3 extensions in file) |

>--------------------------------------------------------|-----------|---------------|-------|------------------------------------------|

> "M" (proprietary) | 486 | 249 | 2x | 48 |

> "N"(proprietary) | 179 | 59 | 3x | 84 |

> NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | 1 | 15x | 3 |

> atbuild GitHub - AnarchyTools/atbuild: The Anarchy Tools build tool | 54 | 5 | 11x | 6 |

in order to demonstrate in my corner of Swift this is not “extremely common”, and is actually less popular than language features the proposal alleges aren’t used.

My point here is that **different people in different corners of the community program Swift differently and use different styles**. I can definitely empathize with folks like the author who use extensions to group functions and are annoyed that their favorite visibility modifier grew four extra characters. Perhaps we can come up with a keyword that is more succint.

However, that is no reason to take away features from working codebases. A scoped access modifier is perhaps my favorite feature in Swift 3. Let’s not throw stuff away because it adds extra characters to one programming style.

Finally, SE-0025 establishes clear motivation for the scoped access modifier:

> Currently, the only reliable way to hide implementation details of a class is to put the code in a separate file and mark it as private. This is not ideal for the following reasons:

> It is not clear whether the implementation details are meant to be completely hidden or can be shared with some related code without the danger of misusing the APIs marked as private. If a file already has multiple classes, it is not clear if a particular API is meant to be hidden completely or can be shared with the other classes.

> It forces a one class per file structure, which is very limiting. Putting related APIs and/or related implementations in the same file helps ensure consistency and reduces the time to find a particular API or implementation. This does not mean that the classes in the same file need to share otherwise hidden APIs, but there is no way to express such sharability with the current access levels.

Concerning the one-class-per-file argument, I would suggest this counter-argument: when working in large projects, I believe it's a good thing if the language encourages (forces is too strong a word for my taste) a one class per file structure, it's good practice. And in small projects, which can hold in a file or two, I don't think that scope-based private provides a worthwhile distinction.

···

On 21 Mar 2017, at 02:26, Drew Crawford via swift-evolution <swift-evolution@swift.org> wrote:
As far as I can see, the proposal does not actually address or acknowledge these problems at all, but cheerfully returns us to them. It would be a mistake to deprecate this feature without examining at all why we introduced it. And realistically we need new solutions to those problems before removing the existing one.

Drew

On March 20, 2017 at 6:54:55 PM, Douglas Gregor (dgregor@apple.com) wrote:

Hello Swift community,

The review of SE–0159 “Fix Private Access Levels” begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md Reply text Other replies What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

What is your evaluation of the proposal? Is the problem being addressed significant enough to warrant a change to Swift? Does this proposal fit well with the feel and direction of Swift? If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those? How much effort did you put into your review? A glance, a quick reading, or an in-depth study? More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md Thank you,

-Doug

Review Manager

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

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

Sent from my iPhone

+1

  • What is your evaluation of the proposal?

Makes the language easier to understand, lowers cognitive load during coding.

Is it really a problem for cognitive load during coding? In a world where protocol extensions defined default methods introducing back the nice and easy to understand concept of polymorphism by reference type where casting an instances class that overrides the method declared in the protocol extensions decides which method is actually executed... well, having to juggle file and scope based access levels breaks the camel's back?

It does not break the camel’s back, but it does lower the load.
I fully well realize that this issue is not a big one and highly personal, and if “fileprivate” remains in use, well, I won’t give up on Swift ;-)

I remain unconvinced of this, no offense meant Rien.

None taken

Regards,
Rien.

···

On 21 Mar 2017, at 08:55, Goffredo Marocchi <panajev@gmail.com> wrote:

On 21 Mar 2017, at 07:05, Rien via swift-evolution <swift-evolution@swift.org> wrote:

I also hope this will pave the way for a overhaul of the access level system including modularization.

  • Is the problem being addressed significant enough to warrant a change to Swift?

yes.

  • Does this proposal fit well with the feel and direction of Swift?

Yes

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

private vs fileprivate seems swift-only, as such I have no comparison.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Followed and participated in the discussions.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: Balancingrock (Rien) · GitHub
Project: http://swiftfire.nl

On 21 Mar 2017, at 00:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md
Thank you,

-Doug

Review Manager

_______________________________________________
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

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md

-1. I yield the remainder of my time to Drew Crawford who satisfactorily explained my concerns.

I am also -1.

I think there are two issues to be considered. One is scoped access itself and the other is the names of the access levels.

I think a reasonable case can be made that changing the meaning of private and introducing fileprivate was a mistake. We probably should have left private alone and chosen a new name for scoped access. There was abundant bikeshedding over this at the time, but now we have the benefit of experience. I believe we should have simply called scoped access control `scoped`. It’s clear that some people would still oppose scoped access but I also don’t think we’d be revisiting this topic if we hadn’t changed the meaning of `private`. The passionate dislike of the feature seems to me mostly related to stealing the `private` keyword.

I support correcting the naming mistake eventually. I’m neutral as to whether Swift 4 is the right time to do that. We just introduced a lot of churn in Swift 3. There is still inconsistency in Swift’s access control system as well as unmet needs (especially around submodules). It may be better to leave things alone for a release and make the change as part of a larger set of changes when access control and submodules are part of a release “theme”.

I am extremely unconvinced that having a scoped access level is actively harmful. It introduces another choice in the language but no individual programmers or teams are forced to use the additional flexibility if they don’t want to. It would be very easy for linters to prohibit scoped access if there are teams that don’t want to use it. It is one extra degree of control for new programmers to learn but properly taught it helps programmers learn to think about encapsulation. This is a good thing.

On the other hand, I believe removing scoped access is active harmful. It reduces our ability to properly encapsulate mutable state. For example, I like to use scoped access to create small state machine types which are used as part of the implementation of another type. These are usually structs with a private enum. The struct exposes methods which encapsulate state transitions. Without scoped access there is no way to encapsulate the state of the state machine and force all changes to go through one of the methods on the struct. This is just one example of how this feature can be very useful, there are many others. Small helper types like this are very idiomatic in Swift. It would be a big step backward to lose the ability to have proper encapsulation of small helper types.

One common argument agains scoped access is that “you’re only protecting yourself from yourself”. I find this to be a bit of a straw man. It isn’t about “protection”. It is about compiler verified encapsulation. This prevents inadvertent changes that violate the intent of the design. For example, it is not out of the question that without scoped access a new member of a large team writes directly to the internal storage of the state machine in the above example. It is also possible that they do so in a way that represents an invalid state transition. The compiler would not catch this mistake. Hopefully it would be caught in a code review but I can imagine it getting missed for many different reasons. On the other hand, with scoped access the new team member would be unlikely to prefer changing access control to using the intended methods. If they did change access control this would be very likely to be caught in code review.

Access control also provides compiler verified documentation of our code. This facilitates reasoning about our code. It also communicates design intent from the original author to future maintainers. Removing a tool that many people find useful in facilitating reasoning about code is actively harmful. Teams that don’t find this tool useful should use a linter and ban its use on their team. This approach would let those of us who do find this tool useful continue to use it.

My observation thus far has been that people seem to be preferring private over fileprivate in many cases. I don’t think this preference is solely about typing four less characters. I think many people really do value the tighter encapsulation it provides.

I do think changes to access control are necessary but I also think this proposal is not the right answer. The right answer should consider access control more holistically. Access control is not a theme for Swift 4. We shouldn't cause more churn around it until we’re ready to look at all of the issues with the current design. And we certainly should not make an actively harmful change to the language.

···

On Mar 20, 2017, at 9:33 PM, Greg Parker via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 20, 2017, at 4:54 PM, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

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

Yes. To cite some evidence, here are codebases I actively maintain:

> codebase | private # | fileprivate # | ratio |

>--------------------------------------------------------|-----------|---------------|-------|

> "M" (proprietary) | 486 | 249 | 2x |

> "N"(proprietary) | 179 | 59 | 3x |

> NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | 1 | 15x |

> atbuild GitHub - AnarchyTools/atbuild: The Anarchy Tools build tool | 54 | 5 | 11x |

So from my chair, not only is the distinction useful, but scoped access control (private) is overwhelmingly (2-15x) more useful than fileprivate.

I don't question your numbers, but it's once again a statistic that has to be taken with a grain of salt:
The only claim that is backed by the table is that private is used more often in your sample — nothing less, but nothing more.
If private is really more useful, should we remove fileprivate instead?
When you do a survey among car owners how often they have used their airbag, and how often the cigar lighter socket, I guess the latter number would be much higher — but still, I'd rather keep something that will hopefully never be used, but could save my life when it does its job.

Fact is, you can replace every occurrence of "private" with "fileprivate", and your source would compile as before, whereas fileprivate saves us from a "friend"-keyword.

Afaics, the only real argument for private/fileprivate hasn't been brought up at all:
Current private is the only level that can be used to demonstrate access control in playgrounds — but I doubt this justifies the confusion caused by it.

-1

I second Drew Crawford's opinion. Although I agree with some of the
critiques about the current state of access levels in swift, I don't
believe that this would be the right way to proceed.

···

On 21 March 2017 at 06:56, Drew Crawford via swift-evolution < swift-evolution@swift.org> wrote:

I disagree quite strongly with the proposal.

First, the document draws conclusions without apparent supporting
evidence, e.g.

> Since the release of Swift 3, the access level change of SE–0025 was met
with dissatisfaction by a substantial proportion of the general Swift
community. Those changes can be viewed as actively harmful, the new
requirement for syntax/API changes.

   - What is “dissatisfaction by a substantial proportion of the general
   Swift community”? How was this measured/determined?
   - What was done to control for the population happy with SE-0025 who
   would e.g. not be likely to take up pitchforks?
   - Who argues these changes are “actively harmful” and where were they
   during SE-0025?

> subtly encourages overuse of scoped access control and discourages the
more reasonable default

   - Who claims that scoped access is “overused” and what is their
   argument for doing so?
   - Why is “fileprivate” the “more reasonable default”? In fact neither
   fileprivate **nor** private are default (reasonable or not!). Internal
   is the default. Nor does this proposal suggest we change that. So this
   seems a very strange statement.

> But is that distinction between private and fileprivate actively used by
the larger community of Swift developers?

Yes. To cite some evidence, here are codebases I actively maintain:

> codebase | private # |
fileprivate # | ratio |

>--------------------------------------------------------|--
---------|---------------|-------|

> "M" (proprietary) | 486 | 249
          > 2x |

> "N"(proprietary) | 179 | 59
           > 3x |

> NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | 1
            > 15x |

> atbuild GitHub - AnarchyTools/atbuild: The Anarchy Tools build tool | 54 | 5
            > 11x |

So from my chair, not only is the distinction useful, but scoped access
control (private) is overwhelmingly (2-15x) more useful than fileprivate.

> And if it were used pervasively, would it be worth the cognitive load
and complexity of keeping two very similar access levels in the language?
This proposal argues that answer to both questions is no

This proposal does not make any later argument about “cognitive load” or
“complexity” I can identify. Did the proposal get truncated?

What is stated (without evidence) is that "it is extremely common to use
several extensions within a file” and that use of “private” is annoying in
that case. I now extend the above table

> codebase | private # |
fileprivate # | ratio | # of extensions (>=3 extensions in file) |

>--------------------------------------------------------|--
---------|---------------|-------|--------------------------
----------------|

> "M" (proprietary) | 486 | 249
          > 2x | 48 |

> "N"(proprietary) | 179 | 59
           > 3x | 84 |

> NaOH https://code.sealedabstract.com/drewcrawford/NaOH | 15 | 1
            > 15x | 3 |

> atbuild GitHub - AnarchyTools/atbuild: The Anarchy Tools build tool | 54 | 5
            > 11x | 6 |

in order to demonstrate in my corner of Swift this is not “extremely
common”, and is actually less popular than language features the proposal
alleges aren’t used.

My point here is that ***different people in different corners of the
community program Swift differently and use different styles***. I can
definitely empathize with folks like the author who use extensions to group
functions and are annoyed that their favorite visibility modifier grew four
extra characters. Perhaps we can come up with a keyword that is more
succint.

However, that is no reason to take away features from working codebases.
A scoped access modifier is perhaps my favorite feature in Swift 3. Let’s
not throw stuff away because it adds extra characters to one programming
style.

Finally, SE-0025 establishes clear motivation for the scoped access
modifier:

> Currently, the only reliable way to hide implementation details of a
class is to put the code in a separate file and mark it as private. This is
not ideal for the following reasons:

> It is not clear whether the implementation details are meant to be
completely hidden or can be shared with some related code without the
danger of misusing the APIs marked as private. If a file already has
multiple classes, it is not clear if a particular API is meant to be hidden
completely or can be shared with the other classes.

> It forces a one class per file structure, which is very limiting.
Putting related APIs and/or related implementations in the same file helps
ensure consistency and reduces the time to find a particular API or
implementation. This does not mean that the classes in the same file need
to share otherwise hidden APIs, but there is no way to express such
sharability with the current access levels.

As far as I can see, the proposal does not actually address or acknowledge
these problems at all, but cheerfully returns us to them. It would be a
mistake to deprecate this feature without examining at all why we
introduced it. And realistically we need new solutions to those problems
before removing the existing one.

Drew

On March 20, 2017 at 6:54:55 PM, Douglas Gregor (dgregor@apple.com) wrote:

Hello Swift community,

The review of SE–0159 “Fix Private Access Levels” begins now and runs
through March 27, 2017. The proposal is available here:

GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0159-fix-private-access-levels.md Reviews are an important part
of the Swift evolution process. All reviews should be sent to the
swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution or, if you would
like to keep your feedback private, directly to the review manager. When
replying, please try to keep the proposal link at the top of the message:

Proposal link:

GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0159-fix-private-access-levels.md Reply text Other replies What
goes into a review?

The goal of the review process is to improve the proposal under review
through constructive criticism and, eventually, determine the direction of
Swift. When writing your review, here are some questions you might want to
answer in your review:

What is your evaluation of the proposal? Is the problem being addressed
significant enough to warrant a change to Swift? Does this proposal fit
well with the feel and direction of Swift? If you have used other languages
or libraries with a similar feature, how do you feel that this proposal
compares to those? How much effort did you put into your review? A glance,
a quick reading, or an in-depth study? More information about the Swift
evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md Thank you,

-Doug

Review Manager
------------------------------

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

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

--
*Pranshu Goyal*
*iOS Developer*
*tlkn*

For what it's worth, I don't really agree with Jonathan Hull on this. If we're going to remove the band-aid, we might as well rip it off now; there's no reason to wait for people to write more code for us to break.

My point was simply that the burden of proof is now on those proposing to revert SE-0025, and the core team shouldn't accept this proposal unless they are satisfied that the burden has clearly been met.

···

On Mar 21, 2017, at 11:29 PM, Matt Whiteside via swift-evolution <swift-evolution@swift.org> wrote:

One point which was raised by a couple of different people on this thread (Brent Royal-Gordon, Jonathan Hull), which gave me some hesitation in voting in favor of this proposal, is that it might make more sense to leave things alone for the time being, with the understanding that scoped access will be solved in some more general way via submodules in the future.

--
Brent Royal-Gordon
Architechies

My apologies, Drew. It's Drew Crawford.

-Kevin Ballard

···

On Wed, Mar 22, 2017, at 01:58 PM, Kevin Ballard wrote:

On Mon, Mar 20, 2017, at 04:54 PM, Douglas Gregor wrote:

* What is your evaluation of the proposal?

Huge -1, and I agree strongly with Drew Crockford's emails on
this topic.

Very much in favour of this
- access modifiers in swift became way to confusing.. and the usefulness is limited. Keep it simple I say. THAT benefits swift the most in the long run

Kind Regards
Dominik

Web: https://pich.info
Twitter: @DaijDjan
Facebook: Dominik.Pich

···

On 22 Mar 2017, at 21:20, David Beck via swift-evolution <swift-evolution@swift.org> wrote:

What is your evaluation of the proposal?
Definitely in favor of this. About halfway through the Swift 3 migration I gave up trying to think through where to use fileprivate and where to use private and just did a project level find and replace to use fileprivate everywhere. So far over the last year I haven't found a case where I want to use private instead of fileprivate. The one time I thought it came up, when I looked at it again I realized I really should be using 2 files anyway.

Is the problem being addressed significant enough to warrant a change to Swift?
Maybe. It certainly would remove confusion.

Does this proposal fit well with the feel and direction of Swift?
Yes.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
I don't think I've ever seen a language distinguish private and fileprivate. It seems like all other languages choose one behavior or the other, and stick with it. Adding fileprivate seemed like Swift's attempt to make everyone happy, when it wasn't needed.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Read through the proposal.

On Mon, Mar 20, 2017 at 4:54 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reply text
Other replies
<https://github.com/apple/swift-evolution/blob/master/process.md#what-goes-into-a-review-1&gt;What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

What is your evaluation of the proposal?
Is the problem being addressed significant enough to warrant a change to Swift?
Does this proposal fit well with the feel and direction of Swift?
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md
Thank you,

-Doug

Review Manager

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

Hi Drew Crawford,

I understand that scoped private can be of value, and that code is a good example. But I never argued that private was useless (it would never have been proposed and accepted in the first case if it was). I just argue that the advantage is not worth its presence in the language. Here’s my take:

3. This file cannot be made an entire module, because it's actually used as part of several projects that are shipped as frameworks, and apparently some developers get really annoyed when they have to drag too many frameworks into their Xcode project.

This fails to convince me. If this piece of code is really used in several projects, I think it belongs in its own module and I would have implemented it by moving ThreadsafeWrapper to its own file, thus keeping the same thread-safety guarantees and hiding of your current example. The feels to me like this piece of code is using private only because it is shying away from using module-scope. Once we gain submodules in the future, it would be even easier to move both classes to their own sub-module.

David.

···

On 23 Mar 2017, at 06:17, Drew Crawford via swift-evolution <swift-evolution@swift.org> wrote:

It has been expressed in various ways "does anybody actually use scoped visibility in the wild" and "what real benefit does it provide to production code".

The below file or some estranged stepchild of it appears at least 5 repositories (that I know of; this is practically a samizdat around here). The scoped access modifier is a significant improvement to the safety of this code and by extension the many projects that contain it.

Apologies if this listing is rather tiring. Many of the "solutions" proposed by the anti-private camp sound great in a sentence but fall apart at scale. But it is not obvious why this is so to people who do not use the keyword, so I can understand why they keep suggesting poor solutions. Perhaps with a more involved listing, it will become more obvious why many of these suggestions do not work. The original is a lot longer; I did reduce it to only the parts that seem relevant to this thread.

import Foundation

/**
This code demonstrates one of the usecases for 'private'. Adapted from real production code, this file exports a threading primitive to the rest of the program.

To state it briefly, private is necessary here because we need the following visibility nesting to achieve our objective:

┌───────────────────────────────────────────┐
│PROGRAM/internal │
│ │
│ │
│ ┌───────────────────────────────────┐ │
│ │ ThreadsafeWrapperNotifyChanged │ │
│ │ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ ThreadsafeWrapper │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ │ value │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ └──────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────┘ │
└───────────────────────────────────────────┘

In particular:

1. value a.k.a. "t" must be protected against all potential unsafe access. This file is hundreds of lines, auditing the whole thing is very tedious.
2. ThreadsafeWrapper is an implementation detail of ThreadsafeWrapperNotifyChanged which is not intended for use by other callers. To avoid exposing the class to other callers, it must appear in this file.
3. This file cannot be made an entire module, because it's actually used as part of several projects that are shipped as frameworks, and apparently some developers get really annoyed when they have to drag too many frameworks into their Xcode project.
4. The use of `private` here reduces the "maybe not threadsafe" part of the code from 196 lines to 47 lines (a reduction of buggy code of 76%). In the production file from which this example is derived, the reduction is from 423 lines to 33 lines, or 92%. A scoped access variable significantly improves the threadsafety of this code.

*/

//Define an interface common to both major components
private protocol Threadsafe : class {
    ///the type of the value we are protecting
    associatedtype T
    ///Access the underlying value.
    ///- parameter block: The block that will be passed the protected value. The block acts as an exclusive lock; while you're in it, no other consumers will be accessing the value.
    ///- complexity: Coalescing multiple operations into a single block improves performance.
    func accessT<K>(_ block: @escaping (T) throws -> K) throws -> K
    ///Mutate the underlying value.
    ///- parameter block: The block that will be passed the protected value. The block acts as an exclusive lock; while you're in it, no other consumers will be accessing the value.
    ///- complexity: Coalescing multiple operations into a single block improves performance.
    func mutateT<K>(_ block: @escaping (inout T) throws -> K) throws -> K
}

///Some convenience accessors for callers that do not need a block-based API to get lock semantics / operation coalescing
extension Threadsafe {
    var value : T {
        get {
            var t: T! = nil
            try! accessT({ lt in
                t = lt
            })
            return t
        }
        set {
            try! mutateT({ (lt:inout T) -> () in
                lt = newValue
            })
        }
    }
}

///The core synchronization primitive. This is a private implementation detail of ThreadsafeWrapperNotifyChanged.
//MARK: audit this area begin
private final class ThreadsafeWrapper<T> : Threadsafe {
    /**The value we are protecting. This value needs to be protected against unsafe access from
    1. This type, if a scoped keyword is available (as shown)
    2. The entire file, if a scoped keyword is removed.
     Only access this value on the synchronizationQueue.
     */
    private var t: T
    ///The queue that is used to synchronize the value, only access the value from the queue.
    ///- note: fileprivate is used here to allow the wrapped object to access the queue. Demonstrating that both are legitimately useful modifiers.
    fileprivate let synchronizationQueue: DispatchQueue
    
    internal init (t: T, queueDescription: String) {
        self.synchronizationQueue = DispatchQueue(label: "foo")
        self.t = t
    }
    
    //MARK: implement our Threadsafe protocol
    func accessT<K>(_ block: @escaping (T) throws -> K) throws -> K {
        var k : K!
        var err: Error?
        synchronizationQueue.sync() {[unowned self] () -> Void in
            do { try k = block(self.t) }
            catch { err = error }
        }
        if let err = err { throw err }
        return k
    }
    
    func mutateT<K>(_ block: @escaping (inout T) throws -> K) throws -> K {
        var k : K!
        var err: Error?
        synchronizationQueue.sync() {[unowned self] () -> Void in
            do { k = try self.fastMutateT(block) }
            catch { err = error }
        }
        if let err = err { throw err }
        return k
    }
    
    ///An alternate mutation function that can only be used when inside a block already.
    ///- note: Calling this function from the wrong queue is NOT thread-unsafe, it will merely crash the program. So exposing this API to the file may introduce bugs, but none of them are a threadsafety concern.
    func fastMutateT<K>(_ block: @escaping (inout T) throws -> K) throws -> K {
        dispatchPrecondition(condition: .onQueue(synchronizationQueue))
        return try block(&t)
    }
}
//MARK: audit area end

/**Like ThreadsafeWrapper, but also allows us to find out when the wrapped object changes.
For that reason, it has a little more overhead than ThreadsafeWrapper, and requires the wrapped type to be equatable */
final class ThreadsafeWrapperNotifyChanged<T: Equatable> : Threadsafe {
    
    ///Hold the value and a list of semaphores
    private let tsw: ThreadsafeWrapper<(T, [DispatchSemaphore])>
    
    internal init (t: T, queueDescription: String) {
        self.tsw = ThreadsafeWrapper(t: (t, ), queueDescription: "foo")
    }
    
    //MARK: implement our Threadsafe protocol
    func mutateT<K>(_ block: @escaping (inout T) throws -> K) throws -> K {
        var k : K!
        try tsw.mutateT { v in
            defer {
                for sema in v.1 {
                    sema.signal()
                }
            }
            try self.tsw.fastMutateT({ v in
                try block(&v.0)
            })
        }
        return k
    }
    func accessT<K>(_ block: @escaping (T) throws -> K) throws -> K {
        return try tsw.accessT({ v -> K in
            return try block(v.0)
        })
    }
    
    /**Notify when the value passed in has changed or the timeout has expired.
     By passing a particular value, we can avoid many race conditions.*/
    func waitForChange(oldValue: T, timeOut: TimeInterval) throws {
        var sema : DispatchSemaphore! = nil
        if oldValue != tsw.value.0 { return } //fastpath
        
        //slowpath
        try accessT {[unowned self] (tee) -> () in
            if oldValue != tee { return }
            sema = DispatchSemaphore(value: 0)
            try self.tsw.fastMutateT({ v in
                v.1.append(sema)
            })
        }
        if sema == nil { return }
        //clean up semaphore again
        defer {
            try! tsw.mutateT { v in
                v.1.removeItemMatchingReference(sema)
            }
        }
        let time = DispatchTime.now() + timeOut
        if sema.wait(timeout: time) == .timedOut { throw Errors.DeadlineExceeded }
        //now, did we change?
        let changed = try accessT { (val) -> Bool in
            return val != oldValue
        }
        if changed { return }
        try waitForChange(oldValue: oldValue, timeOut: timeOut) //:lady_beetle:
    }
}

//MARK: utility
enum Errors: Error {
    case DeadlineExceeded
}

extension RangeReplaceableCollection where Iterator.Element : AnyObject {
    /// Remove first colleciton element that matches the given reference
    mutating func removeItemMatchingReference(_ object : Iterator.Element) {
        if let index = self.index(where: {$0 === object}) {
            self.remove(at: index)
        }
    }
}

On March 20, 2017 at 6:54:55 PM, Douglas Gregor (dgregor@apple.com <mailto:dgregor@apple.com>) wrote:

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reply text
Other replies
<https://github.com/apple/swift-evolution/blob/master/process.md#what-goes-into-a-review-1&gt;What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

What is your evaluation of the proposal?
Is the problem being addressed significant enough to warrant a change to Swift?
Does this proposal fit well with the feel and direction of Swift?
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md
Thank you,

-Doug

Review Manager

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

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

Given that this is such a divisive issue, I'd like to see a revised version of this proposal that renames fileprivate back to private but maintains scoped access control under a different name like "scoped", as has been suggested. That seems like the best compromise -- those that want scoped access control can continue to use it, and those that don't can go back to using private.

Jarod

···

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reply text
Other replies
<https://github.com/apple/swift-evolution/blob/master/process.md#what-goes-into-a-review-1&gt;What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

What is your evaluation of the proposal?
Is the problem being addressed significant enough to warrant a change to Swift?
Does this proposal fit well with the feel and direction of Swift?
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md
Thank you,

-Doug

Review Manager

+1

-1: I have revised my opinion.

  • What is your evaluation of the proposal?

Makes the language easier to understand, lowers cognitive load during coding.
I also hope this will pave the way for a overhaul of the access level system including modularization.

I still hope that fileprivate will be dumped one day. Presumably when a better proposal is on the table.
However it is clear that for some people the disadvantage of dropping it now is bigger than the advantage to the proponents together.
Regardless of wether the need is only perceived or not.

  • Is the problem being addressed significant enough to warrant a change to Swift?

yes.

yes, but not without an alternative solution in place at the time fileprivate is dropped.

  • Does this proposal fit well with the feel and direction of Swift?

Yes

Yes

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

private vs fileprivate seems swift-only, as such I have no comparison.

Same

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Followed and participated in the discussions.

Same.

···

On 21 Mar 2017, at 08:05, Rien <rien@balancingrock.nl> wrote:

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: Balancingrock (Rien) · GitHub
Project: http://swiftfire.nl

On 21 Mar 2017, at 00:54, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift community,

The review of SE-0159 "Fix Private Access Levels" begins now and runs through March 27, 2017. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0159-fix-private-access-levels.md
Reply text
Other replies
What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md
Thank you,

-Doug

Review Manager

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

Several people have asked: What is the harm it causes?

I would like to provide a (hopefully) clear answer to that.

There are a couple of problems with the design which are causing Cognitive Dissonance:

1) Private & fileprivate require very different mental models to operate them
2) They are named very similarly to each other
3) There is a third concept of “private to the type” which requires a third mental model, but is spelled the same way in other languages

Any one of these would cause confusion. All of them together mean that even those of us who understand how they work are bothered by them on a subconscious level (similar to how misaligned graphics will give everyone a subconscious feeling that a graphic design is “off” even if they can’t discern why consciously). Even many of those who are arguing to keep private have argued to rename things or to make it work in a more type-based way by extending visibility to extensions. I don’t think anyone is denying there is a problem here with the status quo.

There is a general rule in design that things that look similar (or in this case are named similarly) need to behave similarly to avoid causing confusion (and conversely things that behave differently *need* to look different).

**This is not something that will go away simply by learning the behavior. It will continue to be a rough spot in the language that causes discomfort until the underlying design issue is fixed.**

The ideal solution here would be to choose a single model and make everything coherent under that. We choose either file-based, scope-based, or type-based access control and unify under that.

All of Swift's access modifiers are already scope-based. Files and modules form scopes. Maybe this concept is new to a lot of people, but it is not internally inconsistent and does not make it a bad design. I do agree that the current names are not great.

···

Sent from my iPad

On Mar 24, 2017, at 4:59 AM, Jonathan Hull <jhull@gbis.com> wrote:

For file-based, that means that our sub-modules, when we add them, would need to be file-based as well.

If we choose Scope-based, then it really cries out for some sort of parameterized private. That is you only have private and public, but for private you would be able to name a scope to widen the visibility to the named scope. Submodules would then need to be scope based, and you would probably use the parameterized private with the submodule name to share data within it.

Type-based is very common in other languages, but I fear it would not play nicely with the way Swift has grown to work. The pros are that you could access private variables from extensions, but getting types to work together with the ease they do now would require a lot of design work (and may not even be quite possible). You also have additional complexities around subtypes, etc...

We really need to choose a single direction and not mix and match.

Of the three, I am personally most supportive of file-based because it is the closest to where we are now, and it seems to simplify many of the concerns about “friend” types by having visibility be dependent on proximity… which seems very intuitive to me.

As I said before, my preference would be to tentatively accept the change, but delay implementation until we design submodules for Swift 5. That way the design can be more cohesive as we can tackle it all at once. If submodules won’t be in scope until after Swift 5, then we should implement the change now.

I hope that explanation was at least a bit helpful…

Thanks,
Jon

Technical note: For the curious, basically we have made a design which is "locally consistent, but globally inconsistent". That is why the effect doesn’t go away after learning the concepts involved. Basically we have made the programming equivalent of the following image:
<Impossible.png>
https://upload.wikimedia.org/wikipedia/commons/7/7f/Impossible.png

I want to keep repeating this statement from Jonathan until someone
actually pays attention to it. The impedance mismatch between the access
levels is not simply programmer flavor. It taints the basic nature of
learning Swift, and learning those different styles.

I want to be open to other programming styles, and would be interested
in using the one that so desperately "needs" scope private as people on
this thread claim. Except I'm turned off it immediately by having to
accommodate this jagged, ugly, bleeding edge of the language.

Best,

  Zachary Waldowski

  zach@waldowski.me

···

On Fri, Mar 24, 2017, at 05:59 AM, Jonathan Hull via swift-evolution wrote:

**This is not something that will go away simply by learning the
behavior. It will continue to be a rough spot in the language that
causes discomfort until the underlying design issue is fixed.**