> On Feb 21, 2017, at 10:41 PM, Robert Widmann <devteam.cod...@gmail.com> wrote:
> 
> By API boundaries I mean both the one internal to MyModule.Foo and the one 
> defined by MyModule.  Here “the API boundary” is explicitly about the 
> submodule MyModule.Foo, whose internal state may have been “unsealed” in the 
> top level by the extension, but has not been re-exported.

I’m sorry, but I just don’t understand how modules form an API boundary in this 
system.  To me a boundary means something that blocks access.  In this system 
`internal` ranges over the entire module and all submodules.  The only 
boundaries I can see besides the module itself are files and lexical scopes 
(with `fileprivate` and `private`).  

This means that it is trivial to put code anywhere within the module that 
extends the submodule and wraps a symbol in a new name and declares it 
`public`.  They can also trivially add a `public import MyModule.Foo` anywhere 
at the top level of their file because every file is forced to include top 
level scope.

In my opinion, we need to identify what goals we have for a submodule system - 
what problems are we trying to solve and what use cases do we intend to enable. 
 

There are quite a few of us who want the ability to form solid API boundaries 
inside a module and view this as one of the fundamental features of a submodule 
system.  It’s reasonable to ask why we view this capability as essential.

I can’t speak for anyone else, but here are a few reasons why it’s important to 
me:

* Solid API boundaries are essential to good design.  
* Having access to an entire code base does not reduce the benefits of #1.  
Some code bases are substantial in size and hard boundaries are important to 
keeping them manageable.
* Using full-fledged modules to do this is possible, but also involves a bit of 
ceremony that is incidental, not essential complexity in many cases.  It would 
be better to have a lighter weight mechanism to do this.
* Swift currently only has whole module optimization, not whole program 
optimization.  There is a performance penalty to using full-fledged modules.

> 
> ~Robert Widmann
> 
>> On Feb 21, 2017, at 11:38 PM, Matthew Johnson <matt...@anandabits.com> wrote:
>> 
>> 
>>> On Feb 21, 2017, at 10:29 PM, Robert Widmann <devteam.cod...@gmail.com> 
>>> wrote:
>>> 
>>> This level of access, the “private to this submodule except to the select 
>>> set of interfaces I want to see it” level, is the equivalent of friend 
>>> classes in C++.  I don’t consider leaving this out to be a hole, nor is it 
>>> an "encapsulation-related problem” because at no point can you break the 
>>> API boundary and re-export anything here with a higher level of access than 
>>> it had previously.
>> 
>> By API boundary you mean the top-level module, right?
>> 
>>> 
>>>> On Feb 21, 2017, at 11:13 PM, Matthew Johnson <matt...@anandabits.com> 
>>>> wrote:
>>>> 
>>>> 
>>>>> On Feb 21, 2017, at 10:11 PM, Matthew Johnson <matt...@anandabits.com> 
>>>>> wrote:
>>>>> 
>>>>> 
>>>>>> On Feb 21, 2017, at 9:47 PM, Brent Royal-Gordon via swift-evolution 
>>>>>> <swift-evolution@swift.org> wrote:
>>>>>> 
>>>>>>> On Feb 21, 2017, at 7:38 PM, Robert Widmann <devteam.cod...@gmail.com> 
>>>>>>> wrote:
>>>>>>> 
>>>>>>> Correct.  Because, in dividing the submodule across an extension, you 
>>>>>>> have placed what should be a private API into a differently-scoped 
>>>>>>> location.
>>>>>> 
>>>>>> Okay. So is your submodule design not intended to address the "I want to 
>>>>>> encapsulate implementation details so they're only visible to several 
>>>>>> units of code in different files, but not the entire module" use case? 
>>>>>> Because if there's no way to scope a symbol to "everything inside this 
>>>>>> submodule, but nothing outside this submodule", I think it leaves that 
>>>>>> use case unserved.
>>>>> 
>>>>> Unless I’m missing something there is also another encapsulation-related 
>>>>> problem with the proposed design.  Let’s suppose for the sake of 
>>>>> discussion there was a `submoduleprivate` access modifier (intentionally 
>>>>> ungainly and not realistic).
>>>>> 
>>>>> // File 1
>>>>> module Foo {
>>>>> // internal, visible to the whole module
>>>>> class Bar { submoduleprivate var protectedState: Int = 0 }
>>>>> }
>>>>> 
>>>>> // File 2 - Has nothing to do with Foo at all
>>>>> import MyModule.Foo
>>>>> 
>>>>> module NotFoo {
>>>>> // Hey, I need to see Bar.protectedState!!!
>>>>> func totallyNotFoo() {
>>>>>   var bar = Bar()
>>>>>   bar.foosExposedPrivates = 42
>>>>> }
>>>>> }
>>>>> 
>>>>> // ok, I’ll just add an extension to Foo so I can see submoduleprivate 
>>>>> and wrap what I need
>>>>> module Foo {
>>>> 
>>>> Oops, this should have been `extension Foo`, but otherwise I believe it is 
>>>> valid under this proposal.
>>>> 
>>>>> // Hey, I’ll be nice and keep it fileprivate, but I could make it public 
>>>>> if I wanted to.
>>>>> extension Foo {
>>>>>     fileprivate var foosExposedPrivates: Int {
>>>>>        // Yep, I’m inside Foo so I can see it’s submoduleprivate stuff
>>>>>        get { return protectedState }
>>>>>        set  { protectedState = newValue }
>>>>>     }
>>>>> }
>>>>> }
>>>>> 
>>>>>> 
>>>>>> -- 
>>>>>> Brent Royal-Gordon
>>>>>> Architechies
>>>>>> 
>>>>>> _______________________________________________
>>>>>> 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

Reply via email to