Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Components as micro-projects #8391

Closed
bondsbw opened this issue Feb 4, 2016 · 9 comments
Closed

Proposal: Components as micro-projects #8391

bondsbw opened this issue Feb 4, 2016 · 9 comments

Comments

@bondsbw
Copy link

bondsbw commented Feb 4, 2016

This proposal is an alternative to the "module" design proposed in #8302.

Proposal

Implement the concept of a Component in the form a micro-project.

Background

I use the definition of "component" which is the same as that used in NDepend literature:

Assemblies, .exe and .dll files, are physical units. They are units of deployment. By contrast, a component is better understood as logical unit of development and testing. A component is therefore a finer-grained concept than an assembly: An assembly will typically contain several components.

Also:

For this article, we’ll use the concept of a component as being a well-defined aggregate of types, with a reasonable size, and with an acyclic graph of dependencies between components.

Components have some of the same guarantees as assemblies. Components may not form circular references with other components. Anything that is internal to a component may not be viewed from outside the component. Breaking down large assemblies into many small components is good practice for dependency management and encapsulation at a level higher than classes.

Today, components are only conceptual. The assembly is the only level at which a component may be defined and enforced, short of using third-party products. If your goal is to have 1000 tiny, lean components then separating them into projects (assemblies) can make the build process orders of magnitude slower than building a large monolithic assembly. Plus managing all those projects and their configuration options can be overwhelming.

Solution

Components become realized as micro-projects which exist within regular projects. These micro-projects would appear in Visual Studio Solution Explorer inside (underneath) the projects containing them.

Component micro-projects have their own set of "Component References" which are conceptually identical to "Project References" today. Code within one component may only reference members of another component if the first component references the second. This eliminates dependency cycles between components.

Component micro-projects otherwise are no different from folders. They do not have project properties (other than, perhaps, denoting a default namespace). All project properties are defined in the main project.

The main project is also a component. Any code inside the main project is considered part of the main project component. The main project component would need to specify any components it references, including components inside the main project. Components within project A may only reference components in project B if A has a project reference to B.

Component micro-projects cannot be built separately and do not produce a separate assembly.

@bondsbw
Copy link
Author

bondsbw commented Feb 4, 2016

I chose to add this suggestion here even though this is not strictly a language design or Roslyn issue, and would require CLR changes. But a key purpose of this feature is to enhance the semantics of internal across languages, so it seemed appropriate to start here for feedback.

@bondsbw
Copy link
Author

bondsbw commented Feb 4, 2016

Enhancement Consideration 1

Reduce the need to explicitly reference certain components

The main project component automatically references its components without the need to explicitly reference them. (This, in turn, would make it impossible for internal components to reference back to the main project component.)

Alternative:

The main project component is automatically referenced by all its components without the need for explicit references. (This, in turn, would make it impossible for the main project component to reference any internal components.)

@bondsbw
Copy link
Author

bondsbw commented Feb 4, 2016

Enhancement Consideration 2

Remove the need to explicitly reference external project components

Component references are only required for the same project. Any component from project A automatically references all components in project B.

@bondsbw
Copy link
Author

bondsbw commented Feb 4, 2016

Enhancement Consideration 3

Remove explicit references altogether

No explicit referencing is needed. The compiler finds any dependency cycles between components, and creates an error condition when a dependency cycle is detected. Users are forced to fix the cycle before the project will compile.

@alrz
Copy link
Member

alrz commented Feb 5, 2016

So this is some kind of IDE feature? That is what "micro-project" implies. Also, could you give some example and how this differs from #8302?

@bondsbw
Copy link
Author

bondsbw commented Feb 5, 2016

The feature includes IDE updates, but goes beyond that by incorporating components as sub-level containers within the project file.

This proposal is similar to #8302 except it does not contain any direct syntax changes for any language. It is meant to address some of the ideas provided in that thread.

Here's an example. Say you have this existing project structure:

Project AwesomePets
|-- Pets       (folder)
    |-- Cat.cs
    |-- Dog.cs
    |-- Turtle.cs
|-- Store      (folder)
    |-- PetStore.cs

Now say you want to ensure that there is no circular dependencies between the pets and the pet store. Also, say that you don't want the internal members of PetStore to be visible to any of the pets or vice versa. Traditionally this would require splitting this project into two assemblies, but that creates overhead and adds additional configurations to maintain. (Imagine if this were dozens or even hundreds of projects.)

Under this proposal we solve the problem while eliminating that overhead by using components. The compiler creates a single assembly. The existing folder/namespace structure could serve to delineate two new components:

Project AwesomePets
|-- Component Pets
     |-- Cat.cs
     |-- Dog.cs
     |-- Turtle.cs
|-- Component Store
     [References:  Pets]
     |-- PetStore.cs

There we go. Now PetStore can reference Cat, Dog, and Turtle but the opposite isn't true. And PetStore can't see the internals of the pets.

@alrz
Copy link
Member

alrz commented Feb 5, 2016

Rather than explicit components and references, I would like to see top-down dependency of folders (like F#) but it'll be more of an IDE feature for C#, and I'm not sure how it will be better than something like #8302. Also, I don't like to change the meaning of internal based on the context.

@bondsbw
Copy link
Author

bondsbw commented Feb 5, 2016

This isn't changing the meaning of internal. It retains the same meaning that it always has, that internal members are not exposed outside of a component. Except now, component does not necessarily equate to assembly.

Folder dependency sounds like a potential solution (this proposal is a similar concept, and could be nearly identical given Enhancement Consideration 3) but wouldn't that break existing code? You would need to be explicit about separating components, which is what this issue proposes.

@bondsbw bondsbw changed the title Components as micro-projects Proposal: Components as micro-projects Feb 8, 2016
@gafter
Copy link
Member

gafter commented Mar 20, 2017

We are now taking language feature discussion on https://github.com/dotnet/csharplang for C# specific issues, https://github.com/dotnet/vblang for VB-specific features, and https://github.com/dotnet/csharplang for features that affect both languages.

@gafter gafter closed this as completed Mar 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants