MarceloCastelo.IO.OutputEnvelop
2.1.0
dotnet add package MarceloCastelo.IO.OutputEnvelop --version 2.1.0
NuGet\Install-Package MarceloCastelo.IO.OutputEnvelop -Version 2.1.0
<PackageReference Include="MarceloCastelo.IO.OutputEnvelop" Version="2.1.0" />
<PackageVersion Include="MarceloCastelo.IO.OutputEnvelop" Version="2.1.0" />
<PackageReference Include="MarceloCastelo.IO.OutputEnvelop" />
paket add MarceloCastelo.IO.OutputEnvelop --version 2.1.0
#r "nuget: MarceloCastelo.IO.OutputEnvelop, 2.1.0"
#:package MarceloCastelo.IO.OutputEnvelop@2.1.0
#addin nuget:?package=MarceloCastelo.IO.OutputEnvelop&version=2.1.0
#tool nuget:?package=MarceloCastelo.IO.OutputEnvelop&version=2.1.0
MCIO.OutputEnvelop
Um envelope de resposta
que seja leve
, de alto desempenho
e que forneça uma API de alto nível
para ser usado em aplicações LOB (line of business).
📖 Documentos
Status | Nome | PT-BR |
---|---|---|
:green_circle: Finalizado | Benchmarks | BENCHMARKS-PT.md |
⚫ Em construção | Decisões de design | DESIGN-DECISIONS-PT.md |
📦 Pacotes
Nome | Versão | Link | Repository |
---|---|---|---|
MarceloCastelo.IO.OutputEnvelop | Nuget.org | Esse aqui 😃 | |
MarceloCastelo.IO.OutputEnvelop.FluentValidation | Nuget.org | Link |
🏷️ Labels
📄 Introdução
Esse projeto nasceu de uma necessidade pessoal. Quando estamos desenvolvendo um sistema temos que tomar diversas decisões com relação ao design do código e manter o equilíbrio entre legibilidade, manutenabilidade e performance é sempre um desafio pois, no fim das contas, nós escrevemos código para outra pessoa entender e não para o computador.
Como assim? Existem diferentes tipos de sistemas, mas o mais comum são os que chamamos de sistemas LOB (line of business) que são aplicações que tem como o objetivo automatizar processos de negócios em corporações como processos de venda, compras, pedidos, chamados, suportes, processos financeiros etc. Esses sistemas possuem algumas características que costumam se repetir:
- Autenticar o usuário que está tentando realizar a operação.
- Autorizar o usuário autenticado para a operação que está querendo realizar.
- Receber inputs dos usuários.
- Validar os inputs dos usuários.
- Validar os estados dos objetos de negócio.
- Realizar algum processo de negócio que modifique o estado dos objetos de negócio.
- Persistir essas informações.
- Retornar o resultado da solicitação para o usuário.
- Exibir diversos relatórios a partir das informações armazenadas.
Além disso, nesse tipo de sistema, os retornos dos métodos vão além de um único objeto e é comum querermos saber mais informações do que somente se deu erro ou não, por exemplo:
- Queremos saber as notificações que ocorreram durante a execução dos métodos.
- Essas notificações são mais do que simples mensagens de erro, podem ser mensagens de warning (por exemplo: quando um pedido de compra ultrapassa determinado valor), podem ser mensagens informativas (por exemplo: informar a integração com os parceiros foi realizada com sucesso durante o processamento da requisição) etc.
- O processamento nem sempre se resume a sucesso ou falha. Em processamento em lote por exemplo, o resultado da operação pode ser parcial onde parte dos itens do lote são processados e outra parte não.
📖 Conteúdo
- MCIO.OutputEnvelop
- :book: Documentos
- :package: Pacotes
- :label: Labels
- :page_facing_up: Introdução
- :book: Conteúdo
- :package: Dependências
- :computer: Tecnologias
- :star: Funcionalidades-chave
- :star: Roadmap
- :rocket: Executando localmente
- :books: Utilização básica
- :books: Exemplos
- :people_holding_hands: Contribuindo
- :people_holding_hands: Autores
📦 Dependências
💻 Tecnologias
Esse projeto utiliza as seguintes tecnologias:
C#
como linguagem de programação..NET Standard 2.0
para o pacote nuget..NET 8
para os projetos de teste de unidade, benchmark e exemplos.xUnit
como framework de testes de unidade.FluentAssertions
para escrita dos Asserts dos testes de unidade de forma fluída,SonarQube
para ferramenta de análise estática de código (SAST - Static Application Security Testing),Stryker.NET
como framework para testes de mutação.BenchmarkDotNet
como framework para realização dos benchmarks.Github Actions
para as pipelines.Github CodeQL
para análise de vulnerabilidades de segurança.Nuget.org
como repositório de pacotes.
⭐ Funcionalidades-chave
Esse projeto tem como objetivo fornecer um envelope de resposta
que segue os seguintes princípios de design:
- ✅ Seja otimizado para alocação na stack ao invés da heap para
evitar pressão no garbage collector
. - ✅ Tenha a característica da
imutabilidade
para ter a garantia que uma vez criado, não será modificado e que, alterações implicarão na criação de um novo objeto. - ✅ Ter uma
API de alto nível
para que seja flexível para ser utilizado em diversos cenários com pouca necessidade de customização do código. - ✅ Seja otimizado para
não realizar box e unboxing
eevitar criação de closures
nos encapsulamentos para não gerar alocações na heap. - ✅ Evitar o
uso desnecessário
elançamento de exceções
ocasionando problemas de desempenho. - ✅ Ser
Thread-safe
.
⭐ Roadmap
- :green_circle: Versão 1.0.0
- :green_circle: Suporte para mensagens de saída dos tipos
information
,success
,warning
eerror
. - :green_circle: Notificações imutáveis.
- :green_circle: Envelope de resposta com encapsulamento de mensagens de saída, exceções e suporte a processamento parcial.
- :green_circle: Envelope de resposta encapsulando a execução para captura automática de exceções.
- :green_circle: Envelopes de resposta imutáveis.
- :green_circle: Suporte para mensagens de saída dos tipos
- :green_circle: Versão 1.1.0
- :green_circle: Suporte para tipagem da propriedade
Code
do objeto OutputMessage a partir de generics. - :green_circle: Remoção da obrigatoriedade do campo
Code
no objeto OutputMessage.
- :green_circle: Suporte para tipagem da propriedade
- :green_circle: Versão 2.0.0
- :green_circle: Correção do termo
ProcessResult
paraOutputEnvelop
.
- :green_circle: Correção do termo
- :green_circle: Criação do pacote
MarceloCastelo.IO.OutputEnvelop.FluentValidation
para integração com o pacote FluentValidation.
🚀 Executando localmente
Por se tratar de um pacote nuget, não existe uma execução. Porém, existe o script build-local-script que pode ser executado via PowerShell que realizará as seguintes ações:
- Instalará a CLI do ReportGenerator localmente para visualização do relatório de cobertura no formato opencover.
- Instalará a CLI do Stryker localmente para execução e visualização do relatório do teste de mutação.
- Restore do projeto.
- Build do projeto em modo release.
- Execução dos testes de unidade.
- Execução do teste de mutação.
- Abertura do relatório de cobertura no navegador web padrão.
- Abertura do relatório de teste mutante no navegador web padrão.
A partir do diretóio raiz
do repositório, no PowerShell
, execute o comando .\build-local-script.ps1
.
Caso queira limpar todos os arquivos gerados, a partir do diretóio raiz
do repositório, no PowerShell
, execute o comando .\clear-local-script.ps1
.
📚 Utilização básica
O trecho do código abaixo foi extraído da classe Customer] do projeto de exemplo na pasta samples/SampleApi
.
O trecho de código abaixo possui o envelope de resposta no retorno dos métodos e como unir envelopes de resposta em um único envelope de resposta que agrega todos os demais.
// Public Methods
public static OutputEnvelop<Customer?> RegisterNew(string name, string email, DateOnly? birthDate)
{
// Process
var customer = new Customer();
var processOutputEnvelop = OutputEnvelop.Create(
customer.GenerateNewId(),
customer.SetName(name),
customer.SetEmail(email),
customer.SetBirthDate(birthDate)
);
// Return
return OutputEnvelop<Customer?>.Create(
output: processOutputEnvelop.IsSuccess ? customer : null,
processOutputEnvelop
);
}
// Private Methods
private OutputEnvelop SetId(Guid id)
{
// Validate
if (id == Guid.Empty)
return OutputEnvelop.CreateError(IdShouldRequiredMessageCode, IdShouldRequiredMessageDescription);
// Process
Id = id;
// Return
return OutputEnvelop.CreateSuccess();
}
private OutputEnvelop GenerateNewId()
{
return SetId(Guid.NewGuid());
}
private OutputEnvelop SetName(string name)
{
// Validate
if (string.IsNullOrWhiteSpace(name))
return OutputEnvelop.CreateError(NameShouldRequiredMessageCode, NameShouldRequiredMessageDescription);
else if(name.Length > NameMaxLength)
return OutputEnvelop.CreateError(NameShouldLessThanMaxLengthMessageCode, NameShouldLessThanMaxLengthMessageDescription);
// Process
Name = name;
// Return
return OutputEnvelop.CreateSuccess();
}
private OutputEnvelop SetEmail(string email)
{
// Validate
if (string.IsNullOrWhiteSpace(email))
return OutputEnvelop.CreateError(EmailShouldRequiredMessageCode, EmailShouldRequiredMessageDescription);
else if (email.Length > EmailMaxLength)
return OutputEnvelop.CreateError(EmailShouldLessThanMaxLengthMessageCode, EmailShouldLessThanMaxLengthMessageDescription);
// Process
Email = email;
// Return
return OutputEnvelop.CreateSuccess();
}
private OutputEnvelop SetBirthDate(DateOnly? birthDate)
{
// Validate
if (birthDate is not null)
{
var age = DateTime.Now.Date.Year - birthDate.Value.Year;
if (DateTime.Now.Month < birthDate.Value.Month)
age--;
else if (DateTime.Now.Month == birthDate.Value.Month && DateTime.Now.Day < birthDate.Value.Day)
age--;
if (age > BirthDateMaxAge)
return OutputEnvelop.CreateError(BirthDateShouldLessThanMaxAgeMessageCode, BirthDateShouldLessThanMaxAgeMessageDescription);
}
// Process
BirthDate = birthDate;
// Return
return OutputEnvelop.CreateSuccess();
}
📚 Exemplos
Para que possa ver, na prática, a utilização do envelope de resposta nos diferentes cenários para o qual ele foi projetado, criei uma API de exemplo localizando dentro do diretório samples/SampleApi
.
🧑🤝🧑 Contribuindo
Você está mais que convidado para constribuir. Caso tenha interesse e queira participar do projeto, não deixe de ver nosso manual de contribuição.
🧑🤝🧑 Autores
- Marcelo Castelo Branco - @MarceloCas
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|