Solid-based API template for agile development of various Acades systems, providing essential features for faster and more efficient construction.
View Repository
Β»
- About the Template π
- Key Concepts π
- Standards π
- General Architecture and Development Flow π°
- Class and Folder Naming π
- About Projects in the Solution π
- Project Packages π¦
- Configuration and Deployment π©βπ»
- Best Practices and Considerations π§Ή
API of a to-do list system that offers a modern and scalable solution for managing personal tasks. Users can create, update, and delete lists (CRUD), as well as add and manipulate individual tasks.
The API architecture incorporates concepts such as CQRS, Event Sourcing, MediatR, SAGA, TDD, DDD, and Clean Code, ensuring a solid and efficient structure.
The main goal is to provide users with an intuitive and effective experience for managing their daily activities.
Below are explanations of the key concepts mentioned above that underpin the to-do list system API:
-
CQRS (Command Query Responsibility Segregation):
It is an architectural pattern used in the API to separate read operations (queries) from write operations (commands). This allows better separation of concerns and performance optimization when dealing with different types of operations. -
Event Sourcing:
The API uses the concept of events to notify and react to changes in the state of entities. Events are emitted whenever a significant action occurs, such as creating a new to-do list or completing a task. These events can be consumed by other system components to perform additional actions, such as sending notifications or updating other related entities. -
MediatR:
It is a design pattern that enables communication and management of commands/queries and events among different components of the API. It facilitates the use of the CQRS pattern, allowing separation and proper handling of command/query and event requests. -
SAGA Orchestration Pattern:
Used to orchestrate and manage complex transactions and business processes involving multiple steps and components. In the API, SAGAs can be used to handle workflows involving multiple operations related to tasks and to-do lists, ensuring that these operations are executed consistently and reliably. -
DDD (Domain-Driven Design):
A software design approach that aims at efficient and cohesive modeling of the business domain. The API follows DDD principles to organize entities, aggregates, services, and events in a clear and understandable domain structure, allowing for flexible and scalable design. -
Clean Code:
The API adopts Clean Code principles to promote readable, concise, and easily maintainable code. This includes the use of meaningful naming for classes and methods, creating small and well-defined functions, eliminating code duplication, and adopting good programming practices. -
TDD (Test-Driven Development):
A development approach that emphasizes creating unit tests before implementing the code. In the API, unit tests are used to verify the correctness and robustness of implemented features. Tests ensure that the API is working as expected, providing greater reliability and facilitating code maintenance.
The API adopts the following standards:
-
Document Standardization:
The API uses masks, sizes, and regular expressions to format document-related fields in a standardized way. This ensures that documents are inserted and displayed in a standardized manner. -
Type, Date, and Number Standardization:
It uses the ISO/GNT format to standardize types, dates, and numbers. Additionally, the UTC standard is used for storing dates and times, ensuring consistency and interoperability. -
Screen Template:
The API provides templates for screens that include data validation, formatting, and other user interface-related functionalities. This helps ensure a consistent and user-friendly experience for API users. -
API Template:
The API uses standardized templates to ensure security, data validation, and other essential functionalities in its programming interfaces. This facilitates the development of new features and ensures API consistency. -
Database Access:
EntityFramework is used to facilitate access and manipulation of data in the database. This allows efficient abstraction of database operations and improves development productivity. -
Log Handling:
The API uses NLog for log and exception handling. This allows recording relevant information and identifying the origin of queries and operations performed in the API. -
Multi-language:
Supports Portuguese, English, and Spanish languages, enabling application internationalization and catering to different audiences. -
LGPD (General Data Protection Law):
The API complies with LGPD. It implements mechanisms to ensure data privacy and security, such as searching by name and document, which can be performed in parts, ensuring the protection of personal data.
The solution's architecture follows a modular approach, divided into different layers and components that fit together to provide the complete functionality of the API.
- Layer 0 - AcadesArchitecturePattern.Tests
- Will be developed and implemented as the progress of all solution projects.
- Contains unit tests for all entities, commands, queries, and handlers of the project.
-
Layer 1 - AcadesArchitecturePattern.Shared
-
Entities: Contains the definition of base entities (Base) that can be extended by other entities.
-
Commands: Defines API commands, such as GenericCommandResult, ICommand, and ICommandResult, used to perform create, update, and delete operations.
-
Queries: Defines API queries, such as GenericQueryResult, IQuery, and IQueryResult, used to retrieve information from data.
-
Handlers: Defines contracts for command (IHandlerCommand) and query (IHandlerQuery) handlers.
-
Events: Defines base events (BaseEvent) that can be used to notify and react to changes in the system.
-
Enums: Defines enumerations, such as EnColor, EnStatusTask, and EnTaskPriorityLevel, used to represent different properties and states.
-
Utils: Contains utility implementations, such as PasswordEncryption, used for encrypting passwords.
-
-
Layer 2 - AcadesArchitecturePattern.Domain
-
Entities: Defines domain-specific entities, such as User, ToDoList, and Task, representing the main objects of the system.
-
Commands: Defines commands related to each entity, such as CreateUserCommand, CreateToDoListCommand, etc.
-
Queries: Defines queries related to each entity, such as ListUserQuery, ListToDoListQuery, etc.
-
Events: Defines specific events for each entity, such as UserEvent, ToDoListEvent, etc.
-
Interfaces: Defines service interfaces (ITaskService, IToDoListService, IUserService) for entity manipulation.
-
-
Layer 3 - AcadesArchitecturePattern.Infra.Data
-
Mappings: Contains mapping classes (TaskMapping, ToDoListMapping, UserMapping) to map domain entities to the database.
-
Contexts: Represents the desired database context (AcadesArchitecturePatternSqlServerContext) allowing data access.
-
Services: Provides implementation of services related to each entity, such as TaskService, ToDoListService, UserService.
-
- Layer 4 - AcadesArchitecturePattern.Application
-
Handlers: Implements handlers that deal with domain-specific commands and queries.
-
Security: Contains JwtTokenGenerator, responsible for generating JWT tokens for authentication.
-
Services: Provides implementation of specific services, such as UserMappingService.
-
- Layer 5 - AcadesArchitecturePattern.Api
- Controllers: Contains controllers providing API endpoints for entity manipulation.
The naming convention follows guidelines to make the code structure more understandable and consistent. Here are some examples of naming with their meanings:
- Classes:
- ClassName: Classes are named using the PascalCase pattern in the singular form, following the convention of starting each word with an uppercase letter. Also, it is important to use names in English to adhere to the correct naming convention.
- Examples: User, ToDoList, Task, CreateUserCommand, IToDoListService, SearchTaskByIdQuery.
- ClassName: Classes are named using the PascalCase pattern in the singular form, following the convention of starting each word with an uppercase letter. Also, it is important to use names in English to adhere to the correct naming convention.
- Folders:
- FolderNames: Folders are named using the PascalCase pattern in the plural form, following the convention of starting each word with an uppercase letter. Also, it is important to use names in English to adhere to the correct naming convention.
- Examples: Entities, Commands, Queries, Controllers, Services, Contexts.
- FolderNames: Folders are named using the PascalCase pattern in the plural form, following the convention of starting each word with an uppercase letter. Also, it is important to use names in English to adhere to the correct naming convention.
-
Specific Class Naming:
- [Action][Entity]Command: Follows the pattern where [Action] is replaced by the action the Command will perform and where [Entity] is replaced by the related entity.
- Examples: CreateTaskCommand, DeleteUserCommand, UpdateToDoListCommand.
- List[Entity]Query: Follows the pattern where [Entity] is replaced by the related entity.
- Examples: ListTaskQuery, ListUserQuery, ListToDoListQuery.
- Search[Entity]By[Parameter]Query: Follows the pattern where [Entity] is replaced by the related entity and where [Parameter] is replaced by the name of the query parameter.
- Examples: SearchTaskByIdQuery, SearchUserByUserNameQuery, SearchUserByEmailQuery.
- [Action][Entity]Handle: Follows the pattern where [Action] is replaced by the action the Handler will perform and where [Entity] is replaced by the related entity. Finally, the word Handle is added, WITHOUT the letter "r" as it is written Handler.
- Examples: CreateTaskHandle, DeleteUserHandle, UpdateToDoListHandle.
- Search[Entity]By[Parameter]Handle: Follows the pattern where [Entity] is replaced by the related entity and where [Parameter] is replaced by the name of the parameter. Finally, the word Handle is added, WITHOUT the letter "r" as it is written Handler.
- Examples: SearchTaskByIdHandle, SearchUserByUserNameHandle, SearchUserByEmailHandle.
- I[Entity]Service: Follows the pattern where accompanied by the letter "I" at the beginning and where [Entity] is replaced by the entity.
- Examples: ITaskService, IToDoListService, IUserService.
- [SolutionName][DatabaseName]Context: Follows the pattern where [SolutionName] is replaced by the solution name and where [DatabaseName] is replaced by the name of the database to be used.
- Examples: AcadesArchitecturePatternSqlServerContext, AcadesArchitecturePatternOracleContext, AcadesArchitecturePatternMySqlContext.
- [Entity]Mapping: Follows the pattern where [Entity] is replaced by the entity.
- Examples:
- [Action][Entity]Command: Follows the pattern where [Action] is replaced by the action the Command will perform and where [Entity] is replaced by the related entity.
- [Entities]Controller: Follows the pattern, where [Entities] is replaced by the entity in the plural form.
- Examples: TasksController, ToDoListsController, UsersController.
- Examples: TasksController, ToDoListsController, UsersController.
- [Entity]Test: Follows the pattern, where [Entity] is replaced by the entity.
- Examples: TaskTest, ToDoListTest, UserTest.
- Examples: TaskTest, ToDoListTest, UserTest.
- [CommandName]Test: Follows the pattern, where [CommandName] is replaced by the full name of the command related to the entity.
- Examples: CreateTaskCommandTest, DeleteUserCommandTest, UpdateToDoListCommandTest.
- Examples: CreateTaskCommandTest, DeleteUserCommandTest, UpdateToDoListCommandTest.
- [QueryName]Test: Follows the pattern, where [QueryName] is replaced by the full name of the query related to the entity.
- Examples: ListTaskQueryTest, SearchUserByIdQueryTest, SearchUserByUserNameQueryTest.
- Examples: ListTaskQueryTest, SearchUserByIdQueryTest, SearchUserByUserNameQueryTest.
- [HandleName]Test: Follows the pattern, where [HandleName] is replaced by the full name of the handle related to the entity.
- Examples: CreateTaskHandleTest, ListToDoListHandleTest, UpdateUserHandleTest.
- Examples: CreateTaskHandleTest, ListToDoListHandleTest, UpdateUserHandleTest.
Projects present in the solution and a brief description of the purpose of each and their types:
- AcadesArchitecturePattern (Blank Solution):
- Description: Empty project solution for scalable systems development.
- Purpose: Provide an organized and modular structure for software application development.
- AcadesArchitecturePattern.Shared (Class Library):
- Description: Contains shared classes and structures used throughout the solution.
- Purpose: Provide common and reusable functionalities for other projects in the solution.
- AcadesArchitecturePattern.Domain (Class Library):
- Description: Contains the system's domain entities, such as User, ToDoList, and Task.
- Purpose: Define domain entities and their business rules, encapsulating domain logic.
- AcadesArchitecturePattern.Infra.Data (Class Library):
- Description: Responsible for data access and persistence, containing mappings and database contexts.
- Purpose: Implement the data access layer, interacting with databases and performing persistence operations.
- AcadesArchitecturePattern.Application (Class Library):
- Description: Implements handlers for commands and queries, as well as other application services.
- Purpose: Manage application business logic, process commands and queries, and provide specific services.
- AcadesArchitecturePattern.Api (Application Project):
- Description: Contains RESTful API controllers, which receive HTTP requests and provide corresponding responses.
- Purpose: Expose API endpoints for interaction with external clients, handling communication and presentation logic.
- AcadesArchitecturePattern.Tests (Test Project):
- Description: Contains unit tests for entities, commands, queries, and handlers of the application.
- Purpose: Verify the correct implementation of functionalities, ensure code quality, and prevent regressions.
Packages present in the projects and a brief description of the purpose of each:
-
Project - AcadesArchitecturePattern.Shared
- BCrypt.Net-Core (version 1.6.0): Library that provides support for password hashing using the BCrypt algorithm.
- Flunt (version 2.0.5): Library that provides support for object validation and error notifications.
- MediatR (version 12.0.1): Library that implements the Mediator pattern for communication between different components of an application.
- BCrypt.Net-Core (version 1.6.0): Library that provides support for password hashing using the BCrypt algorithm.
-
Project - AcadesArchitecturePattern.Domain
- Acades.Abstractions (version 2023.7.3.926-alpha): Library containing common abstractions and interfaces used in CQRS (Command Query Responsibility Segregation) and Event Sourcing-based architectures.
- Acades.Saga (version 2023.7.3.957-alpha): Library that provides support for implementing the Saga design pattern in event-driven architectures.
- MediatR (version 12.0.1): Library that implements the Mediator pattern for communication between different components of an application.
- MediatR.Extensions.Microsoft.DependencyInjection (version 5.1.2): Provides support for dependency injection in ASP.NET Core.
- Microsoft.Extensions.DependencyModel (version 7.0.0): Provides resources for accessing information about runtime dependencies.
- Microsoft.Extensions.Logging (version 7.0.0): Provides logging capabilities in ASP.NET Core.
- Microsoft.Extensions.Logging.Abstractions (version 7.0.1): Contains abstractions for logging features in ASP.NET Core.
- Microsoft.Extensions.Logging.Debug (version 7.0.0): Provides a log provider that writes messages to the debugger during development.
- Scrutor (version 4.2.2): Library that simplifies service registration based on conventions using ASP.NET Core dependency injection.
- Acades.Abstractions (version 2023.7.3.926-alpha): Library containing common abstractions and interfaces used in CQRS (Command Query Responsibility Segregation) and Event Sourcing-based architectures.
-
Project - AcadesArchitecturePattern.Infra.Data
- Microsoft.EntityFrameworkCore (version 7.0.5): Provides data access and object-relational mapping features for Entity Framework Core.
- Microsoft.EntityFrameworkCore.Design (version 7.0.5): Provides support for code generation and design tools for Entity Framework Core.
- Microsoft.EntityFrameworkCore.Relational (version 7.0.5): Provides support for additional relational features in Entity Framework Core.
- Microsoft.EntityFrameworkCore.SqlServer (version 7.0.5): Provides specific support for using SQL Server in Entity Framework Core.
- Microsoft.EntityFrameworkCore.Tools (version 7.0.5): Provides additional tools for Entity Framework Core, such as database migrations.
- Microsoft.EntityFrameworkCore (version 7.0.5): Provides data access and object-relational mapping features for Entity Framework Core.
-
Project - AcadesArchitecturePattern.Application
- FluentValidation.DependencyInjectionExtensions (version 11.5.2): Provides support for integrating FluentValidation with ASP.NET Core dependency injection.
- MediatR (version 12.0.1): Library that implements the Mediator pattern for communication between different components of an application.
- MediatR.Extensions.Microsoft.DependencyInjectionFixed (version 5.1.2): Provides support for integrating MediatR with ASP.NET Core dependency injection.
- Microsoft.AspNetCore.Authentication.JwtBearer (version 7.0.5): Provides support for JWT (JSON Web Token) based authentication in ASP.NET Core.
- FluentValidation.DependencyInjectionExtensions (version 11.5.2): Provides support for integrating FluentValidation with ASP.NET Core dependency injection.
-
Project - AcadesArchitecturePattern.Api
- Microsoft.AspNetCore.Mvc.NewtonsoftJson (version 6.0.19): Provides support for custom serialization and deserialization using the Newtonsoft.Json library in ASP.NET Core MVC.
- Microsoft.EntityFrameworkCore (version 7.0.5): Provides data access and object-relational mapping features for Entity Framework Core.
- Microsoft.EntityFrameworkCore.Design (version 7.0.5): Provides support for code generation and design tools for Entity Framework Core.
- Microsoft.EntityFrameworkCore.Relational (version 7.0.5): Provides support for additional relational features in Entity Framework Core.
- Microsoft.EntityFrameworkCore.SqlServer (version 7.0.5): Provides specific support for using SQL Server in Entity Framework Core.
- Microsoft.EntityFrameworkCore.Tools (version 7.0.5): Provides additional tools for Entity Framework Core, such as database migrations.
- Newtonsoft.Json (version 13.0.3): A popular JSON serialization and deserialization library.
- Swashbuckle.AspNetCore (version 6.5.0): Provides support for generating interactive API documentation using Swagger/OpenAPI in ASP.NET Core.
- Microsoft.AspNetCore.Mvc.NewtonsoftJson (version 6.0.19): Provides support for custom serialization and deserialization using the Newtonsoft.Json library in ASP.NET Core MVC.
-
Project - AcadesArchitecturePattern.Tests
- FluentAssertions (version 6.11.0): Library that provides a fluent API for writing assertions in unit tests.
- Microsoft.NET.Test.Sdk (version 17.5.0): Provides support for running .NET Core tests.
- Moq (version 4.18.4): Library that allows the creation of mock objects for unit testing.
- xUnit (version 2.4.2): Unit testing framework for .NET.
- FluentAssertions (version 6.11.0): Library that provides a fluent API for writing assertions in unit tests.
To set up and deploy the API in different environments, such as development, testing, and production, you can follow the instructions below:
-
General Configuration:
-
Infrastructure: Windows 2016.
-
Databases: SQL Server 2019, Oracle 19G, MySQL 8.0, or 5.7.
-
SDK and Entity Framework Version: Make sure you have the correct versions of .NET 7 SDK and Entity Framework Core 7 installed on your development machine. There will be a migration to version 8 in November 2023, with a deadline until May 2024.
-
Cloud Binary Storage: Amazon S3 or Azure Storage for SaaS and OnPremise.
-
Source Repository: Azure DevOps + Git.
-
Adding Services: Code lines related to adding services (builder.Services.AddControllers, builder.Services.AddSwaggerGen) are part of the general configuration. They set up the necessary services for the application to work, such as route control, JSON serialization, Swagger documentation, among others.
-
Adding services to the container:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; });
-
Connecting to the database:
builder.Services.AddDbContext<AcadesArchitecturePatternSqlServerContext>(x => { x.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")); });
-
Dependency injections:
#region Users builder.Services.AddTransient<IUserService, UserService>(); // Commands: builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(CreateUserHandle).Assembly)); builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(DeleteUserHandle).Assembly)); // Queries: builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(ListUserHandle).Assembly)); builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(SearchUserByIdHandle).Assembly)); builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(SearchUserByEmailHandle).Assembly)); #endregion
-
-
Adding JWT Authorization: Code lines related to JWT authentication (builder.Services.AddAuthentication and builder.Services.AddJwtBearer) are also part of the general configuration. They configure JWT authentication by setting the parameters for JWT token validation.
-
Adding JWT authentication/validation:
builder.Services.AddAuthentication(options => { // Default authentication options.DefaultAuthenticateScheme = "JwtBearer"; options.DefaultChallengeScheme = "JwtBearer"; }) .AddJwtBearer("JwtBearer", options => { options.TokenValidationParameters = new TokenValidationParameters { // Validation parameters ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("AcadesArchitecturePattern-authentication-key")), ClockSkew = TimeSpan.FromMinutes(30), ValidIssuer = "AcadesArchitecturePattern", ValidAudience = "AcadesArchitecturePattern" }; });
-
-
-
Development Environment:
-
Ensure you have a database server available for use in the development environment. This can be SQL Server Express or LocalDB, depending on your choice.
-
Open the appsettings.json or appsettings.Development.json file in the AcadesArchitecturePattern.Api project.
-
Check the connection string named "DefaultConnection". Make sure it is correct for the development environment.
-
Example connection in appsettings.json or appsettings.Development.json for SQL Server Express:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.EntityFrameworkCore.Database.Command": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { // SQL Server Connection "DefaultConnection": "Server=.\\SQLEXPRESS; Database=AcadesArchitecturePatternDb; Integrated Security=True; TrustServerCertificate=True" } }
-
Example connection in appsettings.json or appsettings.Development.json for LocalDB:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.EntityFrameworkCore.Database.Command": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { // SQL Server Connection "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=AcadesArchitecturePatternDb;Trusted_Connection=True;MultipleActiveResultSets=true" } }
-
-
Ensure that other configurations in the appsettings.json or appsettings.Development.json file are adjusted for the development environment.
-
Adding Swagger: Code lines related to Swagger (builder.Services.AddSwaggerGen, app.UseSwagger, app.UseSwaggerUI) are commonly used in the development environment to document and test the API. They provide an interactive interface to explore and test API endpoints.
-
Adding authorization to Swagger:
builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "AcadesArchitecturePattern.Api", Version = "v1" }); // Defining Swagger security definition for Bearer authentication c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() { Name = "Authorization", Type = SecuritySchemeType.ApiKey, Scheme = "Bearer", BearerFormat = "JWT", In = ParameterLocation.Header, Description = "JWT Authorization header using the Bearer scheme.\r\n\r\n Enter 'Bearer'[space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"", }); // Requiring Bearer security for Swagger operations c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new string[] {} } }); });
-
Configuring the HTTP request pipeline:
app.UseSwagger(); app.UseSwaggerUI();
-
-
-
Starting Migration and Creating the Database through Code First:
- Ensure you have a suitable database server configured and available in the production environment, such as a dedicated SQL server or a managed database service.
- Setting Up Cloud Binary Storage:
- If you're using cloud binary storage, ensure you have the necessary credentials and connection strings for the chosen service (Amazon S3 or Azure Storage). Update the relevant settings in the appsettings.json or appsettings.Production.json file.
- Finalizing Deployment:
- Deploy the application to the production environment using the chosen deployment method (Azure DevOps, manual deployment, etc.).
- Monitoring and Maintenance:
- Implement monitoring solutions and regularly check logs to ensure the health and performance of the application in the production environment.
- Updating Environment-Specific Configurations:
- If needed, update environment-specific configurations in the appsettings.json or appsettings.Production.json file.
- Scaling:
- Implement scaling solutions as needed based on the application's demand and usage patterns.
- Securing Production Environment:
- Implement security best practices, including firewall configurations, encryption, and access controls, to secure the production environment.
- Backup and Disaster Recovery:
- Set up regular backups and implement a disaster recovery plan to ensure data integrity and availability in case of unexpected events.
- Updating Dependencies:
- Regularly update dependencies, including libraries, frameworks, and SDKs, to benefit from the latest features and security patches.
- Documentation:
- Keep the documentation up-to-date, including API documentation, infrastructure configurations, and deployment procedures.
- Continuous Improvement:
- Continuously evaluate and improve the application, infrastructure, and deployment processes based on feedback, performance metrics, and evolving requirements.
- Collaboration:
- Foster collaboration between development, operations, and other relevant teams to ensure a smooth and efficient deployment process.
- Training and Knowledge Sharing:
- Provide training and knowledge sharing sessions for the team members involved in the deployment process to enhance their skills and awareness.
- Conclusion:
- By following these guidelines and best practices, you can ensure a successful deployment of the AcadesArchitecturePattern API across different environments. Regularly review and update the deployment process to align with industry standards and evolving technologies.