-1. As was mentioned in replies, many developers find current 'private' very useful and use it not because of its *name*, but because of its *value*.
I can support if we rename 'fileprivate' to 'private' back(and rename current 'private' to something like 'scoped','local' etc; plus probably disallow its usage at file level i.e. we should not have 'scoped class C{}' at top level, we'll have to change to 'private class C{}' to reduce confusions), but not removing of scoped access modifier.
IMO we should keep status quo and defer access modifier changes to the moment, when we'll have submodules and decision on what access modifiers we need exactly.
* Is the problem being addressed significant enough to warrant a change
to Swift?
I don't feel so. Proposal suggests to remove valuable feature(ability to isolate some code without moving it to separate file, model strict compiler-checked access control to some critical code) that is used by many developers, without IMO any significant improvements in it.
* Does this proposal fit well with the feel and direction of Swift?
Don't think so. We need complete proposal which covers submodules and total improvements/re-think for access modifiers.
* If you have used other languages or libraries with a similar feature,
how do you feel that this proposal compares to those?
C#, Delphi. Both have 'private'-like access modifier to isolate/protect code. Moreover, Delphi has 'private' and 'strict private' - first is accessible from inside the same file and second is not.
* How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?
Is the problem being addressed significant enough to warrant a change to Swift?
Yes. Even though I can see how scoped access is occasionally useful, I know that it comes at the cost of implementation complexity, which slows down other features that are, in my opinion, more interesting. Even if it didn’t put a burden on implementors, 4 access levels (or is it 5?) seems like too many.
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. The submodule approach does seem like the way to go, but I still think it’s worth making this change in the present. While the thought of breaking existing codebases is not a pleasant one, I believe that the reduction in compiler complexity gained in comparison to the rarity (and obscurity) of the use cases justifies it.
Does this proposal fit well with the feel and direction of Swift?
Yes. In the sense that elegance decreases as more keywords are added.
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
I’ve not used a language that has extensions that could live in multiple files or has more than 3 access control keywords, so I can’t think of any relevant comparisons.
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Spent about 2 hours, as well as having followed some of the discussion in previous weeks.
···
More information about the Swift evolution process is available at
What is your evaluation of the proposal?
I agree with the proposal. While I acknowledge that a lexically-scoped access modifier can be useful, giving it the name “private” in Swift is unfortunate. Much of the existing Swift training material suggests a common pattern of adding protocol conformances via extensions. For example, this kind of code is very common:
class ToyViewController: UIViewController {
private var toysToDisplay: [Toy]
}
extension ToyViewController: UICollectionViewDataSource {
// Implement the data source protocol here
}
However, this pattern is broken; toysToDisplay cannot be labeled private because then it cannot be accessed within the extension. It needs to be fileprivate instead. But this adds a barrier to learning; while private is a common programming term, fileprivate is not. Most users will try private first. I believe Swift should intentionally be biased toward ease of use, and the use of private to signify scope-level access goes against that principle.
There was an argument earlier in the thread that extensions are intended for augmenting a type from the outside. In my experience, it is equally common to have a type and extensions on that type in the same file. This has been demonstrated in WWDC sessions, in training documents, and is common practice among many of the Swift developers I have worked with.
In Swift 3, there is tension between adding protocol conformances in extensions and having private as the soft default for limiting access. I agree that a lexically-scoped access modifier can be useful, but I think it should be spelled scoped. “private” should revert to its Swift 2 meaning, which is more compatible with the extension- and protocol-oriented nature of Swift. It would be nice if we could make both changes at once, but if that is not possible, it would be better to make the potentially source-breaking change in the Swift 4 timeline, as the bar for source-breaking changes will only increase with each release. "Scoped" access can be added back after Swift 4, if it cannot be part of this release.
Is the problem being addressed significant enough to warrant a change to Swift?
Yes. The requirement to use fileprivate when adding extensions within the same file makes Swift more difficult to learn.
Does this proposal fit well with the feel and direction of Swift?
Yes. Swift is intended to be a language that is both easy to learn and easy to use. The common use of private makes the language more difficult to learn. “scoped” access should be a more advanced feature.
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
Swift is intentionally different here, and I think it’s correct for Swift to be different.
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
I followed the SE-0025 conversation, this conversation, and have used both Swift 2 and Swift 3 extensively. Even though I know that I’m usually going to need fileprivate, it’s such an awkward term that I usually end up writing private anyway, and then regretting it. Ideally, we would continue supporting both scoped and file-level access control, by renaming both of them. But because of the increasing bar for source compatibility, I think it’s better to make this change now, and reintroduce scoped access as soon as possible.
-BJ
···
On Mar 20, 2017, at 5:54 PM, 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:
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
I'm generally a proponent of scoped access control and have been torn over
this proposal. What finally pushed me over the edge has been the time I've
taken to review others code. I've got a team of about 32 iOS developers and
their code shows a heavy lean toward using 'fileprivate' over 'private'.
When I dig into it to determine why, the most common response has been
something along the lines of "I'm not sure what the difference is". In at
least one case, the developer said "well, I usually try 'private' until it
won't compile, then I just change things to 'fileprivate'". Granted this is
an education and training issue, but with other languages the primary
access modifiers are pretty easy to understand. Intermixing scoped access
vs file based protections seems to cause unneeded confusion that I suspect
was increased after running the migrator.
I like elegance and I like the compiler catching things for me, but at the
end of the day I'd rather see things simple and easy to understand and
explain. To that end, I'd prefer to revert to the previous behavior while
we decide on a comprehensive solution based on the learnings from this
effort.
- 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. Increased simplicity reduces overall cognitive load on the developer.
- If you have used other languages or libraries with a similar feature,
how do you feel that this proposal compares to those?
The access control modifiers in Swift are somewhat different than most
other languages I've used, so a comparison between C# or Java seems forced.
- How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?
Several hours, both reviewing internal affected code, the proposal, and
these discussions.
rob.
···
On Mon, Mar 20, 2017 at 7: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:
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:
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
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> 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:
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:
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
–1 However I do support the reverting meaning of the keyword, but I’m against obliterating the powerful scoped access modifier. That said, I’m against the breaking change for Swift–4, which only fixes a tiny peace of the access control system.
Is the problem being addressed significant enough to warrant a change to Swift?
It is not, because a personal preference of a naming convention should not be enough for a breaking change that obliterates flexibility of the language. We also could make everything public (and open), to completely remove the complexity from the language and blame the client for misunderstanding the intentional design of our libraries. However this would be simply ridiculous and complete nonsense if we’d go that route.
Does this proposal fit well with the feel and direction of Swift?
Yes and no. I think that most of us do agree that fileprivate was a bad naming choice, but the need of flexible access modifiers which contains a stricter version of the private keyword is undeniable. Even though not all of us do need it and may see that modifier as more complexity for the language, others do need that much flexibility. If we’re going ever to fix access control in Swift again then it should be deferred to post Swift–4 where we tackle it as a whole, but not simply one access modifier after an other. We already made a mistake with fileprivate, but so we did with open and public with a separate proposal.
Matthew Johnson had a far superior proposal on how to fix this mess, which is apparently out of scope of Swift–4.
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
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:
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\) //🐞
\}
}
//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) 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:
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at
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
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
What is your evaluation of the proposal?
Strongly in favor: +1
Is the problem being addressed significant enough to warrant a change to Swift?
Having to deal with the fallout from the original proposal every day, I would say yes.
Does this proposal fit well with the feel and direction of Swift?
For the long term evolution and philosophy of the language, I believe this is a positive change.
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
I’m not sure a comparison is apt in this case, the point of Swift is to be better, you can’t be better and be the same.
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Merely personal anecdotal experience with some large codebases that have taken to de facto writing `fileprivate` for everything as the current `private` appears to be too persnickety to use in the general case.
Big -1 from me. While I don't like fileprivate at all, removing private as it presently exists is not the answer. For details on my thoughts, please refer to Drew Crawford's excellent responses to this proposal; he states it far better than I ever could :)
-- Gwynne Raskind
···
On Mar 20, 2017, at 18:54, 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:
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
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.
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:
-1 as this is just another keyword change and removing the keyword does not
bring more benefit to Swift as the fileprivate keyword gives currently.
Fileprivate makes sense because creating extensions on objects in the same
file is a heavily used feature in Swift. It is very common for
implementing protocol adherence. Sometimes those properties in the original
class you don't want to give to those extensions in the same file or other
objects in the same file. Maybe proposing a rename can be beneficial to
help with the "cognitive load" but it will be the same argument as renaming
the guard keyword, it just doesn't bring enough benefit. Also Private and
fileprivate makes sense. Not much to think about. Private is completely
closed off and fileprivate is private to others outside the file so other
classes, structs, or objects may reside it in it as well and the properties
can be shared among (which is common to do).
···
On Mon, Mar 20, 2017 at 5:54 PM, 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:
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:
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
Is the problem being addressed significant enough to warrant a change to Swift?
Here lies the core reason for my down vote. There are currently 3541 occurrences of 'private' and 635 'fileprivate' in the code base I work on regularly. Without commenting on the merits and shortcomings of Swift 3's access control, these stats tells us 2 things:
1. This proposal is going to affect projects greatly. Not just in the sense of source incompatibility, but also the existing organization of code units given 'private' exists as of today.
2. The "complexity" many has mentioned here is largely a non-problem (we managed to use a lot of both, and I submit they are used appropriately).
The barrier for breaking change at this scale for Swift 4 should be *very* high. The proposal as-is doesn't include enough convincing argument to meet such standard.
Does this proposal fit well with the feel and direction of Swift?
Perhaps.
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
I'm familiar with at least Swift 2 :)
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Read the text of proposal, all discussions on list (current and past), and a bunch of exchanges on Twitter.
···
---
IMHO, access control, modules (or any type of compiler enforced namespacing), and a more advanced importing syntax are closely interconnected. Whoever proposes to change one of these should have a clear picture of how the change would affect the other two area and include it in the text. In fact, I would like to see one proposal or manifesto that address them all together. The approach of "fix it now and think about the rest later" just puts more constraints on design of "the rest", in addition to making it possible that access control needs to be tweaked even more in future versions of Swift.
More information about the Swift evolution process is available at
While I believe that "fileprivate is the one true private" and was opposed to how SE-0025 turned out, this doesn’t fix access control. It introduces language churn without a replacement solution during a time when source compatibility is very important. The cognitive retraining price was paid in Swift 3, and even if that was a mistake it doesn’t justify forcing everyone to pay it again, especially those who are now adopting a more stable and mature language compared to Swift 2. That price is better paid when there’s a replacement, e.g. some comprehensive redesign or submodules.
···
On Mar 20, 2017, at 4:54 PM, 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:
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
Is the problem being addressed significant enough to warrant a change to Swift?
No, I also think it is not the _correct_ answer to the actual issues with access control in Swift right now.
Does this proposal fit well with the feel and direction of Swift?
With the feel of the proposal, yes. Simplicity is good, less is more and I love that Swift seems to value succinctness where it makes sense.
Does the proposal fit with the direction?
I would have to say no.
Using files as an axis of access control seems wrong to me - ultimately, people seem to be using `fileprivate` as a workaround for the lack of an access level that allows extensions in other files to see members/functions (and some for keeping everything in one file - which seems like quite bad practice to me). `private` (as it is defined right now in Swift 3) actually seems to me to be logical to keep in light of discussions around future work toward submodules.
My considered feeling is that if we’re not going to solve the issue of access control holistically - whether by adding other access levels, or by something else like submodules — the change being proposed in SE-0159 seems like shuffling deck chairs on the Titanic.
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
Not applicable. My use of other languages is old, out-of-date and not relevant to Swift or this situation. I bring only my Objective-C/Cocoa and Swift knowledge/experience with me this time.
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
A fair bit of reading both of the posts to the list, some investigation of features in other languages, then a lot of consternation around actually participating in this conversation.
* If you split a class into a bunch of extensions, chances are it's a
large class, and fileprivate keyword provides crucial *documentation*
on which methods and fields are accessed from outside the scope. Even
if someone blindly uses private until compiler complains, then
switches to fileprivate without thinking, there's still value when
reading the code. (This has been mentioned as one of the points
against scoped private.)
* Encapsulation is in the spirit of Swift's safety goals, we want to
encourage it.
* // MARK is perfectly fine for tightly-coupled class bodies, so if you
find yourself using tons of fileprivate, consider switching to a
single body with marks
* I really like the point that we should uphold the original decision
unless we find new compelling arguments that were not considered
initially.
Is the problem being addressed significant enough to warrant a change
to Swift?
No. I haven't personally seen any complains about this feature in my
circles; everyone is happy about tighter access controls.
Does this proposal fit well with the feel and direction of Swift?
It feels actively against the safety and readability goals of Swift.
If you have used other languages or libraries with a similar feature,
how do you feel that this proposal compares to those?
This has been beaten to death in the original proposal.
How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?
Thorough reading of the first half of this discussion, and active
participation in the original discussion (as well as writing and
shipping lots of Swift code since Swift 0.x).
I admit feeling great dismay at finally posting "MY REVIEW", given the
generally sour nature of the discourse of the thread. However, I feel
like it was a mistake to not have voiced my concern in the SE-0025
fight, so here we are.
* What is your evaluation of the proposal?
Overwhelmingly vehement +1 for any implementation this idea can take. I
personally prefer reverting to Swift 2 behavior, full-stop.
As others have noted, the text of the proposal leaves a little to be
desired on some of the context. However, I do not believe this prevents
making a decision on the matter. ("To post a proposal to Swift
Evolution, one must first invent the universe…)
* Is the problem being addressed significant enough to warrant a
change to Swift?
The lack of proper consideration, caution, or even solid
implementation of the scoped access modifier is the biggest mistake
the Evolution community has made yet. It is a non-trivially broken
feature with no plans to fix it. If I had to choose between the 15-ish
implemented proposals created wholly by the community and not having
ever had SE-0025 be a twinkle in anyone's eye, I'm honestly not sure
which I'd choose.
* Does this proposal fit well with the feel and direction of Swift?
In the most literal sense, it does not, but that's the point: Swift's
thought on access control is in need of a course correction, for reasons
I lay out in the next question.
* If you have used other languages or libraries with a similar
feature, how do you feel that this proposal compares to those?
I've had plenty of experience in other languages both with and without
access control.
This specific smell in Swift's access control is a sign of a simply
untenable direction. I find C++ access control similarly untenable due
to its confusing variations and edge cases. Swift is heading down a
similar path.
Swift has the laudable goal of being a multi-modal and multi-paradigm
language. That does not mean it cannot be opinionated. Inspecting access
control in a single file is trivial, and if it's not, that's your
problem. I don't care at this point to hear the gospel of all the magic
I can accomplish in unmaintainable large files.
I keep thinking of SE-0009, which was rejected quite plainly for
"introduc[ing] a significant amount of verbosity that does not justify
itself with added clarity". After being immersed in this topic for what
feels like eons, and having my own opinions explained to me several
times, I truly cannot see how scope-private/the fileprivate change was
any different.
Nowadays, my codebases are littered with chains of attributes like
`@IBOutlet fileprivate private(set) weak var`. It look less like working
in a language of sane defaults and look more like I had a stroke while
typing it out. This change has been the antithesis of clarity, and the
inability of +1-ers to see it any other way than theirs is an upsetting
application of, "F*** you, got mine." I'm glad you all understand the
change and have incorporated it into your work, I really am. I haven't;
I still don't.
* How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?
I have followed the thread(s) closely, and done much follow-up and
discussion about this issue off the mailing lists.
I beseech the Core Team to act decisively to restore sanity to this part
of the language. I don't care if that means being for or against this
particular proposal. I don't care if it's a spelling change, hinting at
a future plan for submodules, or explaining what the happy path will be
for creating modules in Xcode 9. I just ask that they think of the
developers who are being underrepresented in this discussion out of
inexperience, lack of understanding, or, worse, having stopped using
Swift in frustration.
I am now absolutely thrilled to create a filter to Mark As Read anything
else arising from this thread. Good luck.
Sincerely,
Zachary Waldowski
zach@waldowski.me
···
On Mon, Mar 20, 2017, at 07:54 PM, Douglas Gregor via swift-evolution wrote:
+1 for me too. The distinction always felt too nitpicky to me. File level access as the most limited form of access for the private keyword seems to me to be the simplest and easiest concept to understand.
The example provided of code that would break after this change feels like an anti pattern to me as well. Defining the same method twice in the same type opens the door to a lot of confusion for beginners that may have to read code written this way. The benefits provided don't outweigh the drawbacks in my opinion. Even though it's a breaking change, preventing that pattern could be seen as an additional benefit to this proposal.
···
--
Kevin Lundberg
On Mar 20, 2017, at 8:03 PM, Riley Testut via swift-evolution <swift-evolution@swift.org> wrote:
What is your evaluation of the proposal?
A huge +1. I separate the implementation of all my types into extensions, and this practice resulted in me almost always having to use the fileprivate keyword. Personally, I also have never needed any further access controls than those available in Swift 2, even after writing Swift 3 code since its release.
Additionally, it’s a weird inconsistency that top-level “private” declarations are treated like fileprivate, so happy that this will fix that as well.
Is the problem being addressed significant enough to warrant a change to Swift?
100%.
Does this proposal fit well with the feel and direction of Swift?
Yes. Simplifies the access control model by removing a fringe feature (in my opinion).
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
Private still doesn’t match the definition of other languages after this change, but I don’t think that’s a bad thing.
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Followed the discussion, and read through the final proposal.
On Mar 20, 2017, at 4:54 PM, 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:
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