> On Apr 5, 2017, at 3:27 PM, Tony Arnold via swift-evolution 
> <[email protected]> wrote:
> 
> 
>> On 6 Apr 2017, at 02:54, Nevin Brackett-Rozinsky via swift-evolution 
>> <[email protected]> wrote:
>> 
>> The developer adds a free function to the file. Or an extension of another 
>> type. Or another type entirely. And they put it in the same file because it 
>> needs to work with the implementation details of the existing type.
> 
> This is the part of all of these conversations that concerns me deeply. Is 
> the assumption that it is now “best practice” to place all shared 
> implementation into a single file? Aren’t those files going to become quite 
> large in real world use? That’s a terrible thing to encourage!
> 

It depends on what these access control levels mean to the developers, not just 
on how they affect the compiler or symbol exposure.

For instance, my viewpoint is that private is for hiding implementation details 
of a type that someone editing elsewhere within the same module shouldn’t need 
to understand to do their job correctly. That means all unsafe details, and 
safe implementation details to be hidden to decrease coupling.

Fileprivate is used when unsafe details are needed to share implementation 
details outside a type with other types or free functions, by embedding all the 
accesses into a single file. Today, it also used to expose safe and unsafe 
details to extensions of the type within the same file.

Don't fall into the trap of just always using the lowest acceptable level of 
access control, rather than choosing levels below “internal” to reduce coupling 
of implementation details and preventing unsafe access to a type. If you focus 
on using the lowest acceptable access control level, you’ll wind up structuring 
your code around reducing said access controls - which will indeed result in 
all the code getting thrown into a single file ;-)

> My experience working with protocol conformances in Objective-C over the 
> years is that breaking protocol conformances into categories/extensions on 
> the original type *in separate files* is the best way to keep things small, 
> testable and focused.

> Separating protocol conformances into separate files, whilst still being able 
> to access private members of the extended type promotes smaller files, and 
> more focused implementation within those files.

Based on the above, I’d say my viewpoint is:
 - If your extension is based on details that don’t require knowledge of the 
internal workings of the type, then you should be able to expose those details 
of the type to the module, and author the protocol conformance in any file you 
like. All third party conformances of your type to a protocol are necessarily 
of this type, because they don’t have internal knowledge or access.

 - If your extension requires internal knowledge of the type, it should be 
consolidated into a single file with the type so that changes to the internals 
are localized (and also promotes higher cohesion of your code). Implementing 
Encodable/Decodable are likeliy examples of this.

 - there is a grey area where there are details which are safe but that you 
don’t really want to expose due to implementation details, or could be 
potentially be written better with implementation detail access. Then you have 
a trade-off to decide one way or another. Implementing 
CustomDebugStringConvertible or Equatable might be examples of this.

> I know Swift has different purposes for different people here, but ultimately 
> it’s supposed to support great application development for Apple’s platforms, 
> right? To my eyes, `fileprivate` should never have been introduced without 
> some kind of `typeprivate` (similar to how things would be declared back in 
> Objective-C land with a `*+Private.h` header that you could import when it 
> was needed). Right now, there’s no way to duplicate that pattern in Swift - I 
> would need to make anything I wish to access `internal` which exposes it to 
> everything within the application/module - surprisingly, this is a regression 
> from the tooling and access levels I had available in Objective-C. 

I personally fought against the inclusion of scoped private originally because 
I feel that it was sufficient that developers have to understand the code that 
they are working on - they need to understand the public details of dependent 
modules, the internal and public details of the module they are working on, and 
all the details of the file they are working in. I didn’t see the need to go 
smaller than file, to say they have to understand the file private details of 
the file they are in and the private details of the type they are editing. But 
c'est la vie.

The use of a type scoped private independent of a same file restriction would 
be to spread implementation details on a type across multiple files, which 
could be argued to be a bad practice. If nothing else, it means a developer can 
work around your attempt to encapsulate and hide implementation details by 
creating accessor methods in an extension elsewhere in the codebase, and that 
this would not be revealed until something broke.

-DW
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to