Naming Conventions¶
All naming conventions building Suite Modules and Services for the Suite Framework are located here.
- .NET Naming Guidelines apply. This document extends it.
- Guidelines that are covered by analyzers are not explained here. This document must be followed manually.
Projects, Assemblies & Namespaces¶
Let's define some terms first.
Projects¶
When we say Project in this context, we refer to any MSBuild project, mostly
it means .csproj
projects, but we may include other MSBuild project files in
the future.
Assemblies¶
An assembly is just the means to package the code, it is the output of building
a project, usually a .dll
or .exe
file. An assembly may be composed of
multiple Namespaces.
Namespaces¶
The Suite Framework utilizes namespaces for grouping symbols that together compose a functionality, module, or enhance other modules or other framework namespaces. These symbols may or may not be defined in the same assembly.
.NET applies a similar concept so it's natural that we follow a similar path.
By giving Namespaces a proper meaning we can use them to lead consumers into our symbols in a better way. This will also provide consumers the same experience across different modules.
As a general rule, when naming namespaces don't let the name of the folder determine the namespace, this will usually be incorrect. Instead we group symbols in grouping folders, but these don't necessarily determine the namespace name.
The Suite Framework, like the rest of the .NET ecosystem, adheres to this behavior. It is very convenient that services do so too, so that we all know how to browse the monorepo, where to find symbols, and what to expect from a symbol, namespace or assembly.
Naming Projects & Assemblies¶
- Project Name and Assembly Name must match. (don't customize assembly name)
- Project containing folder must match the name of the project.
- Do not name your projects with a "type" prefix:
- Do not
ITsynch.Suite.Framework.Abstractions
- Do not
ITsynch.Suite.Modules.Localization
- Do not
ITsynch.Suite.Services.Identity
- Do not
- Do name your project according to its type. (keep reading)
- The name of the project does not necessarily determines the Namespace.
Naming Framework Modules¶
Framework Modules, meaning the modules that are provided in the Suite Framework
and developed by the Suite Team, are located inside the dotnet/src/modules
directory.
- Naming conventions for projects apply.
- The project containing the module must be named in the form of
ITsynch.Suite.[ModuleName]Module
. i.eITsynch.Suite.LocalizationModule
ITsynch.Suite.SomeLibraryModule
Modules may implement the Module Provider Pattern, in which case the following conventions apply:
- Implementation for different providers are located at a separate project,
which must be named in the form of
ITsynch.Suite.[ModuleName].[ProviderName]Provider
. i.e:ITsynch.Suite.Persistence.EntityFrameworkCoreProvider
ITsynch.Suite.Persistence.NHibernateProvider
Module Directory Structure¶
A reference directory structure for Framework Modules:
-
ITsynch.Suite.[ModuleName]Module
includes abstractions and default implementations for these.Abstractions
andExceptions
are grouping folders only, not namespaces.
-
ITsynch.Suite.[ModuleName].[ThirdParty]Provider
is only used when the module has multiple implementations, implementing the Module Provider Pattern
Module Namespace Conventions¶
When developing Framework Modules it is crucial that we stick to these naming conventions. Guiding users to discover symbols in an easy manner is key.
ISuiteModule
implementations for Framework Modules must be on theITsynch.Suite.App.Modules
namespace.- Options classes for Framework Modules must be on the
ITsynch.Suite.App.Modules
namespace. - All symbols, except the aforementioned ones, should be on the
ITsynch.Suite.[ModuleName]
namespace. Only use other namespaces to separate by functionality. Usually sticking to the root namespace is enough. - All symbols for Provider modules must be on the
ITsynch.Suite.[ModuleName].[ThirdParty]Provider
namespace.
Naming Suite Services¶
When we say "Service", we mean an executable Suite ASP.NET or Console Application, that runs a long-lived process and exposes an HTTP or Messaging API.
When naming Services, it is important to have done some brainstorming about its domain boundaries. Specifically, it's bounded context must be well defined and named. This process usually involves inquiring with the rest other teams / PMs in order to figure it out together.
Services are located inside the dotnet/src/services/{bounded-context}
directory, where {bounded-context}
is the name of its bounded context.
It may be common to have a single Service per bounded context, however it is also common that a single Service spans multiple projects in order to have a clear separation of concerns.
Something to note though, is that since we are building microservices, the code for each service should be quite small. Actually, I should be able to explain "what a service does" to a developer in an hour time. Hence, we recommend not splitting your Service into multiple projects until you really need to, mostly so that the Service can expose it's Messaging or HTTP DTOs/symbols for other Services to use. Keep the separation at directory and namespace level, and enforce it through PR reviews.
- Naming conventions for projects apply.
- Project names are prefixes by the name of it's bounded context. i.e:
ITsynch.Suite.ServiceOrders.Issues
ITsynch.Suite.DataSync.CoreServices
- Services that have multiple layers are suffixed by it's Clean Architecture
layer. i.e:
ITsynch.Suite.ServiceOrders.Application
ITsynch.Suite.ServiceOrders.Application.Contracts
ITsynch.Suite.ServiceOrders.Domain
ITsynch.Suite.ServiceOrders.Persistence
Multiple Services may be contained inside a single bounded context, in which case the following conventions apply:
- Services must have a clear name identifying it's purpose. i.e:
ITsynch.Suite.DataSync.Http.Application
ITsynch.Suite.DataSync.Messaging.Application
ITsynch.Suite.DataSync.Cli
(We are considering a sub directorytools
for these)
- Clean Architecture suffixes still applies when the project has multiple layers.
Service Directory Structure¶
This is a proposed project structure for services that require a clean project separation.
Service Namespace Conventions¶
- The Root Namespace of a Service must be in the form of
ITsynch.Suite.[ServiceName]
. i.e:ITsynch.Suite.ServiceOrders
ITsynch.Suite.Users.Identity
-
The Root Namespace of a Clean Architecture layer of a service must be in the form of
ITsynch.Suite.[ServiceName].[LayerName]
. i.e:ITsynch.Suite.ServiceOrders.Application
ITsynch.Suite.ServiceOrders.Domain
-
All symbols must be in the Root Namespace or in a layer namespace.
- Modules that compose a service (like its Persistence layer), may implement the provider pattern (or others) in which case, their conventions apply.
Service Client Module Conventions¶
It is useful for services to provide developers who wants to interact with the service, a module for them to install where they have whatever tools we can provide them to improve their experience. This is what we call the "Client Module" of a Service.
Say for example we have a service that keeps track of Positions. Users of this service may want to keep a copy of a materialized representation of a Position in their own service.
In order to provide a quick getting started way to do that, the Position Service may also include a Position Client Module that will do just that: listen to the Position related messages and keep a materialized copy of the entity up to date.
When creating this kind of modules, this conventions apply:
- All module conventions apply.
- The project is located next to the
.Application
of the Service, usually in theservices/{BoundedContextName}
directory. - The name of the project should be in the form of
ITsynch.Suite.[ServiceName].ClientModule
. i.eITsynch.Suite.Positions.ClientModule
ITsynch.Suite.ServiceOrder.ClientModule
- The root namespace should be in the form of
ITsynch.Suite.[ServiceName].Client
. i.eITsynch.Suite.Positions.Client
- A Suite Module must be included, in the
ITsynch.Suite.App.Modules
namespace, which includes whatever configuration is needed.- Module must be named in the form of
[ServiceName]ClientModule
. i.ePositionClientModule
- Module must be named in the form of
- An
ITsynch.Suite.[ServiceName].Abstractions
Assembly may be provided which includes the entities or other symbols that the ClientModule uses which may be required from the Domain layer.
Naming Tests Projects¶
Test projects may include Unit and Integration Tests. Ideally these should be split into two projects, so that eventually we can run them separately, i.e run unit tests on each PR and integration tests nightly.
- Naming conventions for projects apply.
- The name of the test project is the project name with the
.Tests
suffix. i.e:ITsynch.Suite.MassTransitModule.Tests
ITsynch.Suite.DataSync.Domain.Tests
- Add the
.UnitTests
suffix when separating unit tests, and the.IntegrationTests
suffix for integration tests. i.e:ITsynch.Suite.MassTransitModule.UnitTests
ITsynch.Suite.MassTransitModule.IntegrationTests
ITsynch.Suite.DataSync.Application.UnitTests
ITsynch.Suite.DataSync.Application.IntegrationTests
Names of Data Transfer Objects¶
Data Transfer Objects (DTOs) being used in the an HTTP API context, like
AppServices should be named in a manner we can identify them just by reading
them. To achieve this and to maintain consistency across all services, we
recommend calling them with Dto
at the end, i.e.:
PositionDto
PositionCreationDto
ServiceOrderDto
Names of GQL Objects¶
GQL Objects are a kind of data transfer object, since it is a representation of the DB model that we use to expose to the outside world. In order to make queries cleaner, the convention is to use the same name as the entity without any suffix.
Always use the namespace when referring to GQL entities. i.e Graphql.MyEntity
.
Names of Properties¶
DO name Boolean properties with an affirmative phrase always prefixed with "Is", "Can", or "Has". i.e:
IsMandatory
CanBeTakenOver
HasEmail