Suite Services¶
The Suite Framework's main purpose is to provide everything you need for you to focus on building your business and application logic.
Suite Services are building blocks for the Suite 3.0. They follow the microservices pattern and implement a single autonomous functionality.
For better understanding of the concepts used in this section please make sure you have read the Fundamentals first.
Suite's application modules are built following the concepts and guidelines of Clean Architecture and Domain-Driven Design.
It is important to keep a clean design of our services, and to follow common practices between them in order to be able to keep them up to date by possibly different teams.
Projects Structure¶
Services are composed of multiple projects in order to provide a clear set of contracts and multi-db provider support. We can decompose a service, by following clean architecture, into an Application, Domain and Infrastructure Layer. Where the Infrastructure usually means persistence.
Please do read the Naming Conventions for detailed information on naming your service, its projects and namespaces.
Application Layer¶
The Application Layer contains logic specifically designed for the application
purposes. Application
and Application.Contracts
projects holds the
application specific logic and abstractions respectively.
The Application.Contracts
includes interfaces which extend from IAppService
and it's corresponding DTO; these are used for Dynamic HTTP Client generation.
Note
The recommendation for defining DTOs is to use C# Records. There's no need to use interfaces.
Application.Contracts
also includes AMQP Message Contracts, which are required
by services that consume our service's events, or for services that produce our
events.
The Application Layer is also responsible of converting Domain Entities to DTOs and vice versa. Basically, the Application Layer exposes an application use case, which receives DTOs and returns DTOs.
It never receives nor return Domain Entities, since these are implementation
details of the Domain Layer; and besides, they are usually not serializable.
See Application Layer section for more details.
Domain Layer¶
Domain
project contains business entities, aggregate roots, repositories and
domain service objects.
We do not recommend creating a separate project to hold domain entities unless it's required.
Inside the Domain layer, avoid using attribute decorators. When using any Suite Module, or third party library, prefer conventions over configurations. Inversion of control is key.
See Domain Layer section for more details.
Infrastructure Layer¶
Infrastructure Layer is usually split into multiple projects depending on the functionality or external service they integrate with.
A clear example of Infrastructure is the Persistence
project, where common
symbols like class mappings, data seeding, and other non DB provider symbols are
held.
The Persistence.SqlServer
includes symbols specific for running against a
particular DB Engine, and the packages or dependencies required for doing so.
The way to toggle between which provider is chosen can be done by depending on
all of your Persistence.{DbProvider}
projects in your Application
project.
Then, we can select a provider using the Entity Framework Module ProviderKey
configuration.
Tip
In order to produce smaller deliverables, Applications are encouraged to use the External Module Discovery in order to depend on these their DB Provider modules.
Support for other DB Providers will be added in the form of
Persistence.Oracle
, implementing the
Module Provider Pattern.
See Infrastructure Layer section for more details.
Recommendations¶
- Isolate as much as possible from implementation details
- Use DDD concepts as much as possible (Entities, AggregateRoots, etc)
- Avoid business logic in application Layer