# Modularity

### Motivation

Modern-day apps are far from monolith state meaning they are composed of several components. \
These components are loosely-coupled and are often discovered during app startup. This approach allows the developers to substitute the modules easily and encapsulate the required functionality. This greatly aids preserving the Open-Close Principle of S.O.L.I.D. software development.

### Plugin Model

There are all kinds of modules which can range from UI to simple configuration. One of the most frequent use cases for the need of introducing a composition module is to register the private dependencies of an assembly which should be otherwise unknown to the main app. This is actually a plugin case where system can consume any number of plugins by some abstraction without knowing the concrete implementation. (see the similarity to the case of dependency injection where the abstraction is used, too). The composition module would need to simply implement the abstraction:

```csharp
using Solid.Practices.IoC;

class TestCompositionModule : ICompositionModule<IDependencyRegistrator>
{
    public void RegisterModule(IDependencyRegistrator dependencyRegistrator)
    {
        dependencyRegistrator.AddSingleton<IService, Service>();
    }
}
```

These modules are then composed together and executed during app startup thus making sure all related functionality is ready.

### Dependencies

Sometimes modules could depend one on another. These dependencies should be handled by the appropriate class (see **Bootstrapping** for explanation). The information about the dependencies should be  exposed via **IHaveDependencies** interface and the module itself should be identified using **IIdentifiable** interface. Alternatively, the **DependenciesAttribute** and **IdAttribute** can also be used. \
\
Let's see an example of usage:<br>

```csharp
using Solid.Core;
using Solid.Practices.IoC;
using Solid.Practices.Modularity;

class TestCompositionModule : ICompositionModule<IDependencyRegistrator>, IIdentifiable
{
    public void RegisterModule(IDependencyRegistrator dependencyRegistrator)
    {
        //register dependencies
    }

    public string Id => "TestModule";
}

class TestCompositionModule2 : ICompositionModule<IDependencyRegistrator>, IHaveDependencies
{
    public void RegisterModule(IDependencyRegistrator dependencyRegistrator)
    {
        //register dependencies
    }
    
    public string[] Dependencies => new [] {"TestModule"};
}
```

These two modules should be topologically sorted using these dependencies' constraints. This can be achieved using the correspondent extension method

```csharp
var modules = new [] {new TestCompositionModule(), new TestCompositionModule2()};
var sortedModules = modules.SortTopologically();
```

That's it! Now the modules will be invoked in the correct order :)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://godrose.gitbook.io/solid-net-framework/modularity.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
