Folder Structure
The folder structure will adhere to Vertical Slice Architecture focused around the
separation of concerns under a Modulith
solution. Which means:
This isn’t the full folder structure, but a small representation of how it’s logically ordered. |
📂 src 📂 Common (1) 📂 Common.Library (2) 📂 Interfaces (3) 📄 IEndpointDefinition.cs 📄 IModuleInstaller.cs 📄 IServiceInstaller 📄 EndpointDefinitionExtensions.cs (4) 📄 ModuleInstallerExtensions.cs 📄 ServiceInstallerExtensions.cs 📂 Modules (5) 📂 Modules.Authentication (6) 📂 GoogleOAuth (7) 📄 GoogleAuthEndpoints.cs (8) 📄 GoogleAuthRepository.cs (9) 📁 LogIn 📄 LogInEndpoints.cs 📄 LogInRepository.cs 📁 Config (10) 📁 Data (11) 📄 AssemblyReference.cs (12) 📄 AuthenticationModuleInstaller.cs (13) 📁 ServiceInstallers (14) 📄 RepositoryServiceInstaller.cs (15) 📂 Modules.Users (and so on...) 📁 KakeiBro.API (16)
1 | We will have a Common type of Class Library that all modules and apps can reference with base interfaces, extensions and classes that help us adhere to the rules of how all the architecture will be written. |
2 | The shared class library will be denominated Common.Library . |
3 | Inside of it we will have really high level and foundational interfaces that will help us declare the different classes that a module should have in order to declare the composition steps that will register both its endpoints, plus its services. |
4 | All the EndpointDefinitionExtensions , ModuleInstallerExtensions , ServiceInstallerExtensions
are the ones powering assembly scanning, making it possible for us to simply reference the different
AssemblyReference markers on different modules, and from that one target, we can start composing the whole
module by registering its services, its endpoints and so on. |
5 | We will have a Modules folder in which all our module’s will live (as Class
Libraries completely independent of each other). |
6 | Taking the Authentication Module as an example, we will have created a folder for the whole Module Class Library |
7 | And it’s inside nested folders that we will have the slices in the form of use cases. Each Use Case (user flow) for the module will contain all that it’s neccesary to it (from the endpoint all the way to the database specific concerns). |
8 | Each Use case will have generic named files, for example for all endpoints related
to the use case we will be following the pattern <UseCase>Endpoints.cs . |
9 | And just like in the endpoints case we will follow the same idea with a file for
a repository, <UseCase>Repository.cs . It’s worth noting that we chose to use the
name of Repository however this could easily be named something else (such as Service
or BusinessLogic ), we are not leveraging the Repository pattern in its entirety
mainly because we have no use case (at least for now). |
10 | In case we might require any sort of module configuration files, and/or classes, we will
aggregate them under a Config folder. |
11 | Since the module has to deal with its own set of database technical concerns, we will
have a Generic folder named Data under the module, this wil encapsulate both
the Entity objects that map to the database, plus migrations and other database centric
operations. |
12 | Since we will leverage assembly scanning for the registering of many of the components
that make out our whole module, we should always have an AssemblyReference.cs file there,
a marker, WITHOUT ACTUAL FUNCTIONAL CODE. |
13 | An interesting concept that we will also make use of is the concept of a Module Installer, since all of our modules will be class libraries at their core, we need for an actual application to make use of their functionalities, and so, in order to register the module we will use the concept of Install. Which in short means that all the interfaces to which an app can hook into this module and register it, all of its endpoints, services, database concerns should be injected through these interfaces. |
14 | And in the spirit of keeping things simple, clean and organized, we will also separate
by technical concern each registration for each different concern under a ServiceInstallers
folder. |
15 | For example, all repository registration logic should be under a specific RepositoryServiceInstaller.cs
file. |
16 | It’s also at the same level of the Modules folder that we will have the actual
Web API (the app) that will then install of the modules to it through the interfaces that
we have laid out previously. |