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.