> Le 3 mars 2017 à 23:21, Matthew Johnson via swift-evolution > <[email protected]> a écrit : > >> >> On Mar 3, 2017, at 9:24 AM, Karim Nassar via swift-evolution >> <[email protected]> wrote: >> >> >> I’ve read through the last couple of Swift (sub)Module proposals put >> forward, and since my particular use-cases for a sub-module solution seemed >> to be under-served by them, I’ve decided to write up my thoughts on the >> matter to prompt discussion. >> >> Perhaps my use-cases are outliers, and my approach will be deemed naive by >> the community… I’m happy to learn better ways of doing things in Swift, and >> welcome any thoughts, criticism, or illumination related to these ideas. >> >> I’m including the write-up below, but it’s also available as a gist: >> https://gist.github.com/anonymous/9806f4274f1e13860670d6e059be5dce >> >> — >> >> # Sub-modules >> >> A sub-module solution in Swift should have the following properties: >> >> * Extremely light-weight >> * Low API surface area >> * Adopt progressive disclosure >> * Integrate with Access Control features to enable a level of encapsulation >> & hiding between the Module and File level >> * Be permeable when desired >> >> ## Discussion >> >> As we get deeper into building real applications & frameworks with Swift, we >> begin to realize that having a way to express relationships between types is >> desireable. Currently, Swift only allows us to express these relationships >> at two levels, the Module and the File. >> >> The Module boundary is acceptable for small, focused frameworks, while the >> File boundary is acceptable for small, focused Types, but both levels can be >> unweildy when dealing with certain cases where a cluster of internally >> related types needs to know about each other but may only want to publish a >> narrow set of APIs to the surrounding code, or in large complex applications >> which are necessarily structured as a single Module. In these cases, we wind >> up with large monolithic Modules or (even worse) large monolithic Files. >> >> I have seen this proliferation of Huge Sprawling Files (HSFs) in my own >> code, and seek a way to combat this rising tide. >> >> ## Goals >> >> It is a goal of this proposal to: >> >> * Suggest a mechanism for organizing code between the Module and File levels >> that is as lightweight and low-friction as possible >> * Provide mechanisms for authors to create both "hard" and "soft" API >> boundaries between the Module and File levels of their code >> >> ## Anti-Goals >> >> It is not a goal of this proposal to: >> >> * Move Swift away from filesystem-based organization >> * Significantly alter the current Access Control philosophy of Swift >> >> ## Proposal Notes >> >> Please take the following proposal wholely as a Straw-Man... I would be >> equally satisfied with any solution which meets the critera described at the >> top of this document. >> >> Unless specified otherwise, all spellings proposed below are to be >> considered straw-men, and merely illustrative of the concepts. >> >> ## Proposed Solution >> >> Two things are clear to me after using Swift and following the Swift >> Evolution list since their respective publications: >> >> 1. Swift has a preference for file-based organization >> 2. Vocal Swift Users dislike `fileprivate` and want to revert to >> Swift2-style `private` >> >> Because of #1, this proposal does not seek to change Swift's inherent >> file-system organization, and instead will expand on it. >> >> Since I personally fall into the camp described by #2, and most of the >> community response to this has been "Lets wait to deal with that until >> sub-modules", I'm making this proposal assuming that solving that quagmire >> is in-scope for this propsoal. >> >> ### Changes to Access Control Modifiers >> >> As part of this proposal, I suggest the following changes to Swift 3's >> Access Control modifiers: >> >> * Revert `private` to Swift 2's meaning: "hidden outside the file" >> * Remove `fileprivate` as redundant >> >> This is potentially a source-breaking change. However, it is interesting to >> note that this change is **not** required for the following proposal to >> function. >> >> Changes that *are* necessary are: >> >> * Change the spelling of `internal` to `module` (making `module` the new >> default) >> * Introduce a new modifier `internal` to mean "Internal to the current >> sub-module and its child-sub-modules” > > Can you give concrete examples of use cases where a descendent submodule > needs access to symbols declared by an ancestor? I gave some thought to this > when drafting my proposal and came to the conclusion that this runs against > the grain of layering and is likely to be a bad idea in practice. If there > are use cases I didn’t consider I am very interested in learning about them. > >> >> These changes are *not* source-breaking because the new `internal` modifier >> acts exactly as the old `internal` modifier unless it is used within a >> sub-module. The specific spelling of this new `internal` modifier is >> necessary to maintain backwards source compatibility. >> >> The new `module` modifier allows authors to make APIs permeable between >> sub-modules while still hidden outside the owning Module if desired. >> >> All other Access Control modifiers behave the same as they currently do >> irrespective of sub-module boundaries, so: >> >> * `public` => Visible outside the Module >> * `open` => Sub-classable outside the Module >> >> ### Making a Sub-module >> >> To create a sub-module within a Module (or sub-module) is simple: The author >> creates a directory, and places a "sub-module declaration file" within the >> directory: >> >> ``` >> // __submodule.swift > > Why the double underscore prefix? To make it sort to the top in a file > browser? > > Is this file allowed to have any Swift code? Or is it limited to > submodule-related declarations only? If the latter, why not use an extension > such as `.submodule` or `.swiftmodule` to differentiate it from ordinary > Swift files and allow the submodule to be named by the name of this file? > >> // MyModule >> >> submodule SubA >> >> ``` >> >> Then any files within that directory are part of the sub-module: >> >> ``` >> // Foo.swift >> // MyModule.SubA >> >> struct Foo { >> private var mine: Bool >> internal var sub: Bool >> module var mod: Bool >> } >> >> public struct Bar { >> module var mod: Bool >> public var pub: Bool >> } >> >> ``` >> >> This creates a sub-module called "SubA" within the module "MyModule". All >> files within the directory in which this file appears are understood to be >> contained by this sub-module. >> >> If in the future we choose to add additional complexity (versioning, >> #availability, etc) to the sub-module syntax, the sub-module declaration >> gives a natural home for this configuration. >> >> It's important to note some benefits of this approach: >> >> * Using the "special file" means that not all Directories are automatically >> submodules >> * Any given source file may only be a member of 1 submodule at a time >> * Use of filesystem structure to denote sub-modules plays nicely with source >> control >> * The sub-module structure is instantly clear whether using an IDE (which >> can be taught to parse the `__submodule.swift` files to decorate the UI), or >> simple text-editor (assuming a convention of naming the Directory the same >> as the sub-module, which is a linter problem) > > If we’re going to use the file system to organize submodules this seems like > a reasonable approach. It allows larger submodules to have folder > hierarchies within them and also creates a central location for > submodule-related declarations. > > A primary flaw I see in this approach is that Xcode is the dominant IDE for > Swift and the way Xcode handles files is not conducive to file-system > organization. I really detest the way Xcode handles this and would vastly > prefer that it simply reflected the physical file system hierarchy but I > don’t think that will change any time soon. On the other hand maybe a file > system based submodule system in Swift would motivate the Xcode team to > better reflect the physical file system organization.
I quite love how Xcode allow me to group my source files as I want without having to move them around. This is specially useful when working with languages that support relative #include "". Moving an header in an other group don’t break the code. Moreover, if you want to create a folder for each group in Xcode, you can perfectly do that too as Xcode allows you to define a different path for each group. So I don’t see how it would prevent using submodule.
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
