# Mediator

## Por que usar Mediator?

Pense em um grande restaurante. **Sem Mediator**, cada cliente precisa conhecer pessoalmente cada cozinheiro e ligar diretamente para ele: "João, faz uma pizza para mim". **Com Mediator**, há um **garçom central** (o Mediator) que recebe todos os pedidos e os entrega ao cozinheiro correto.

### **Vantagem principal**

Se o cozinheiro João tirar férias, o cliente não precisa saber - o garçom simplesmente entrega o pedido ao cozinheiro Pedro.

***

## Instalação do MediatR

Para instalar o MediatR, deve-se acessar o terminal na pasta do projeto Application e executar o seguinte comando:

```
dotnet add package MediatR
```

Como resultado, o arquivo `Aviator.Application.csproj` será modificado, sendo adicionada a seguinte referência:

```xml
<PackageReference Include="MediatR" Version="12.2.0" />
```

O MediatR é uma biblioteca que implementa o padrão Mediator para a plataforma .NET. Atua como um mecanismo de intermediação inteligente entre os emissores de comandos (Commands) e seus respectivos manipuladores (Handlers). Amplamente adotado pela comunidade .NET, o pacote é mantido por Jimmy Bogard.

***

## Análise Arquivo por Arquivo

Cada arquivo de código-fonte será examinado individualmente, apresentando-se as alterações necessárias para a implementação do padrão Mediator.

***

### Response.cs

**Localização:** `Aviator.Application/Planes/UseCases/Create/Response.cs`

#### Implementação Anterior (sem Mediator)

```csharp
using Aviator.Application.Shared.UseCases.Abstractions;

namespace Aviator.Application.Planes.UseCases.Create;

public record Response(string Message) : IResponse;
```

#### Implementação Atual (com Mediator)

```csharp
namespace Aviator.Application.Planes.UseCases.Create;

// Agora é um simples record, não implementa nada
// O MediatR não exige interfaces específicas para Responses
public record Response(string Message);

// Explicação: O MediatR trabalha com qualquer tipo como Response
// Não precisa de interfaces marcadoras
```

#### Análise das Alterações

**Modificação Realizada:** A implementação da interface `IResponse` foi removida, transformando a classe em um *record* simples sem vínculos com interfaces específicas.

**Motivação Técnica:** O MediatR adota uma abordagem mais flexível em relação aos tipos de retorno, não exigindo que as classes de resposta implementem interfaces pré-definidas. Esta característica reduz a quantidade de código *boilerplate* (repetitivo) necessário para a estruturação do sistema.

#### Comparação Conceitual

<table data-full-width="false"><thead><tr><th>Aspecto</th><th>Abordagem Anterior (sem Mediator)</th><th>Abordagem Atual (com Mediator)</th></tr></thead><tbody><tr><td><strong>Estrutura de Resposta</strong></td><td>Exigia implementação de <code>IResponse</code> (formulário oficial)</td><td>Aceita qualquer tipo como resposta (formato livre)</td></tr><tr><td><strong>Flexibilidade</strong></td><td>Rígida - interface obrigatória</td><td>Flexível - sem interfaces específicas</td></tr><tr><td><strong>Complexidade</strong></td><td>Maior - código <em>boilerplate</em> adicional</td><td>Menor - estrutura simplificada</td></tr><tr><td><strong>Requisitos</strong></td><td>Conformidade com contrato de interface</td><td>Conteúdo informativo adequado</td></tr></tbody></table>

#### Benefício Principal

**Redução da complexidade** e **eliminação de código redundante**, mantendo a **funcionalidade essencial** do sistema.

***

### Command.cs

**Localização:** `Aviator.Application/Planes/UseCases/Create/Command.cs`

#### Implementação Anterior (sem Mediator)

```csharp
using Aviator.Application.Shared.UseCases.Abstractions;

namespace Aviator.Application.Planes.UseCases.Create;

// Implementava nossa interface ICommand
public record Command(string Name) : ICommand;
```

#### Implementação Atual (com Mediator)

```csharp
using MediatR;  // Nova referência

namespace Aviator.Application.Planes.UseCases.Create;

// Agora implementa IRequest<TResponse> do MediatR
// IRequest<Response> = "Eu sou um request que retorna um Response"
public record Command(string Name) : IRequest<Response>;

// Explicação:
// IRequest<T> = interface do MediatR para commands/queries
// O generic <Response> especifica o tipo de retorno
```

#### Análise das Alterações

**Modificação Principal**

A interface `ICommand` foi substituída por `IRequest<Response>`, estabelecendo um vínculo explícito entre o comando e seu tipo de retorno.

**Decodificação da Estrutura**

* `IRequest`: Define a natureza de solicitação/requisição
* `<Response>`: Especifica o tipo de objeto retornado após o processamento

**Tradução Funcional**

A classe `Command` passa a representar formalmente: "Uma solicitação que, quando processada, produz uma resposta do tipo `Response`"

#### Comparação Conceitual

| Aspecto            | Abordagem Anterior                  | Abordagem Atual                                           |
| ------------------ | ----------------------------------- | --------------------------------------------------------- |
| **Interface**      | `ICommand` (genérica)               | `IRequest<Response>` (específica)                         |
| **Definição**      | "Sou um pedido de comida"           | "Sou um pedido de pizza que resultará em uma nota fiscal" |
| **Vínculo**        | Sem associação explícita de retorno | Associação explícita com tipo de resposta                 |
| **Especificidade** | Genérica                            | Tipada com retorno definido                               |

#### Consideração Importante

O tipo especificado entre os delimitadores angulares (`<Response>`) deve corresponder **exatamente** ao tipo retornado pelo *Handler* correspondente, garantindo a consistência de tipos em tempo de compilação.

***

### Handler.cs

**Localização:** `Aviator.Application/Planes/UseCases/Create/Handler.cs`

#### Implementação Anterior (sem Mediator)

```csharp
using Aviator.Application.Shared.UseCases.Abstractions;

namespace Aviator.Application.Planes.UseCases.Create;

// Implementava interface IHandler
public class Handler : IHandler<Command, Response>
{
    // Método personalizado
    public async Task<Response> HandleAsync(Command command)
    {
        await Task.Delay(10);
        return new Response("Plane Created");
    }
}
```

#### Implementação Atual (com Mediator)

```csharp
using MediatR;  // Nova referência

namespace Aviator.Application.Planes.UseCases.Create;

// Agora implementa IRequestHandler<TRequest, TResponse>
public class Handler : IRequestHandler<Command, Response>
{
    // Método padrão do MediatR (não é Async no nome)
    public async Task<Response> Handle(
        Command request, 
        CancellationToken cancellationToken = default)
    {
        // cancellationToken é importante para operações assíncronas
        // Permite cancelar a operação se o cliente desconectar
        
        await Task.Delay(10, cancellationToken); // Passa o cancellationToken
        
        return new Response("Plane Created");
    }
}

// Diferenças importantes:
// 1. Método chama-se Handle (não HandleAsync)
// 2. Recebe CancellationToken (boas práticas de async)
// 3. Implementa IRequestHandler (interface do MediatR)
```

#### Análise das Alterações

**Mudança 1**

* `IHandler<Command, Response>` → `IRequestHandler<Command, Response>`\
  \&#xNAN;***Justificativa**:* Padronização com MediatR, substituindo interface personalizada pela padrão da biblioteca.

**Mudança 2**

* `HandleAsync(Command command)` → `Handle(Command request, CancellationToken)`

**Parâmetros atualizados**

* `Command request` solicitação a ser processada
* `CancellationToken`  mecanismo de "botão de emergência" que interrompe processamento quando cliente cancela requisição ou fecha conexão

**Definição de CancellationToken**

Mecanismo que atua como um "botão de emergência" em operações assíncronas, permitindo a interrupção do processamento quando o cliente cancela a requisição ou fecha a conexão.

#### Comparação de Segurança em Operações Assíncronas

| Cenário                   | Implementação                                 | Comportamento                                          |
| ------------------------- | --------------------------------------------- | ------------------------------------------------------ |
| **Sem CancellationToken** | `await Task.Delay(30000);`                    | Aguarda 30 segundos mesmo após cancelamento do cliente |
| **Com CancellationToken** | `await Task.Delay(30000, cancellationToken);` | Interrompe imediatamente ao detectar cancelamento      |

#### Alterações Adicionais

| Alteração             | Descrição                                              | Impacto                                |
| --------------------- | ------------------------------------------------------ | -------------------------------------- |
| **Nome do Método**    | `HandleAsync` → `Handle`                               | Padronização com convenção MediatR     |
| **Parâmetro Nomeado** | `command` → `request`                                  | Convenção de nomenclatura (opcional)   |
| **Passagem de Token** | `Task.Delay(10)` → `Task.Delay(10, cancellationToken)` | Boa prática para operações assíncronas |

#### Importância do CancellationToken

O `CancellationToken` representa uma melhoria significativa na **resiliência** do sistema, prevenindo o consumo desnecessário de recursos quando operações são abandonadas pelos clientes, contribuindo para a **eficiência** e **estabilidade** da aplicação.

***

### DependencyInjection.cs (NOVO)

**Localização:** `Aviator.Application/DependencyInjection.cs`

```csharp
using Microsoft.Extensions.DependencyInjection;

namespace Aviator.Application;

/// <summary>
/// Classe estática responsável pelos métodos de extensão 
/// para configuração de injeção de dependência.
/// </summary>
public static class DependencyInjection
{
    /// <summary>
    /// Método de extensão para IServiceCollection que configura os serviços 
    /// da camada de aplicação.
    /// O uso do parâmetro <c>this IServiceCollection</c> permite a invocação 
    /// via <c>services.AddApplication()</c>.
    /// </summary>
    /// <param name="services">Coleção de serviços do container 
    /// de injeção de dependência.</param>
    /// <returns>A mesma instância de IServiceCollection 
    /// para permitir encadeamento de métodos.</returns>
    public static IServiceCollection AddApplication(this IServiceCollection services)
    {
        // Configuração do MediatR
        services.AddMediatR(configuration =>
        {
            // Especifica o assembly no qual o MediatR deve localizar os handlers
            configuration.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly);
        });

        return services;
    }
}
```

#### **Funcionalidade implementada**

1. O MediatR realiza a varredura do assembly `Aviator.Application`.
2. Identifica automaticamente todas as classes que implementam `IRequestHandler<TRequest, TResponse>`.
3. Efetua o registro dessas classes no container de injeção de dependência.
4. Estabelece o mapeamento entre comandos (ou queries) e seus respectivos handlers.

#### **Explicação do método de extensão**

Um método de extensão consiste em uma funcionalidade que é adicionada a um tipo existente sem a necessidade de modificá-lo diretamente.

**Exemplo de uso**

* **Sem extensão:** `services.???` (não existe um método nativo `AddApplication()`).
* **Com extensão:** `services.AddApplication();` (o método passa a estar disponível para `IServiceCollection`).

#### **Funcionamento do `RegisterServicesFromAssembly`**&#x20;

A operação pode ser compreendida por meio da seguinte analogia:

* O MediatR atua como um **detetive** que entra em um prédio (o assembly referenciado por `typeof(DependencyInjection).Assembly`).
* O detetive examina cada apartamento (cada classe definida no projeto).
* Identifica os **chefs** (classes que implementam `IRequestHandler<,>`).
* Registra suas especialidades (qual comando cada handler processa).
* Constrói uma **agenda de contatos** (mapeamento interno utilizado pelo MediatR para rotear solicitações).

#### **Definição de Assembly**

Um assembly corresponde ao arquivo compilado (`.dll`) que contém o código intermediário (IL), metadados e recursos de um projeto.

A expressão `typeof(DependencyInjection).Assembly` retorna uma referência ao assembly no qual a classe `DependencyInjection` está definida — neste caso, o projeto `Aviator.Application`.

***

### Program.cs (API)

**Localização:** `Aviator.Api/Program.cs`

#### **Implementação Anterior (sem MediatR)**

```csharp
using AviatorHandler = Aviator.Application.Planes.UseCases.Create.Handler;
using CreatePlaneCommand = Aviator.Application.Planes.UseCases.Create.Command;

var builder = WebApplication.CreateBuilder(args);

// Registro manual e explícito do Handler
builder.Services.AddTransient<AviatorHandler>();

var app = builder.Build();

// Endpoint acoplado diretamente à implementação do Handler
app.MapPost("/v1/planes", async (AviatorHandler handler, CreatePlaneCommand command) 
    => await handler.HandleAsync(command));

app.Run();
```

#### **Implementação Atual (com MediatR)**

```csharp
using Aviator.Application; // Para acessar o método de extensão AddApplication()
using CreatePlaneCommand = Aviator.Application.Planes.UseCases.Create.Command;

var builder = WebApplication.CreateBuilder(args);

// Configuração centralizada da camada de aplicação
// Registra automaticamente TODOS os handlers do projeto
builder.Services.AddApplication();

var app = builder.Build();

// Endpoint desacoplado - conhece apenas a abstração ISender
app.MapPost("/v1/planes", async (ISender sender, CreatePlaneCommand command) 
    => await sender.Send(command));

app.Run();
```

#### **Análise das Alterações**

| Aspecto                        | Implementação Anterior                                 | Implementação Atual                                |
| ------------------------------ | ------------------------------------------------------ | -------------------------------------------------- |
| **Registro de Handlers**       | Manual (`AddTransient<AviatorHandler>()`)              | Automático (`AddApplication()`)                    |
| **Acoplamento do Endpoint**    | Direto ao `Handler` concreto                           | À abstração `ISender`                              |
| **Invocação do Processamento** | `handler.HandleAsync(command)`                         | `sender.Send(command)`                             |
| **Conhecimento da API**        | Conhecia a implementação específica (`AviatorHandler`) | Conhece apenas a interface do mediador (`ISender`) |

#### **Explicação da Implementação**

**Mudança 1 (Registro Manual → Automático)**

Na abordagem anterior, cada *handler* precisava ser registrado individualmente no container de DI, resultando em código repetitivo e propenso a erros de omissão. Com o MediatR e o método `AddApplication()`, todos os *handlers* são descobertos e registrados automaticamente através de *scanning* de *assembly*.

**Mudança 2 (Handler Concreto → ISender)**

O endpoint anterior estava fortemente acoplado a uma implementação específica (`AviatorHandler`), violando o princípio de Inversão de Dependência. Na nova abordagem, o endpoint depende apenas da abstração `ISender` do MediatR, que atua como um *mediador* responsável por rotear o comando para o *handler* apropriado.

**Mudança 3 (HandleAsync() → Send())**

A invocação direta do método do *handler* (`HandleAsync`) foi substituída pela chamada ao método `Send()` do mediador. Esta mudança encapsula a lógica de roteamento e execução, centralizando-a no MediatR.

#### **Comparação Conceitual**

**Benefício Principal**

Redução drástica do acoplamento entre a camada de API e a camada de aplicação. A API não precisa mais conhecer detalhes de implementação dos *handlers*, tornando o sistema mais modular, testável e fácil de manter. A adição de novos casos de uso não requer mais modificações no ponto de entrada da API.

***

## Fluxo de Funcionamento do MediatR

### **Fluxo de Execução**

Quando `sender.Send(command)` é chamado, nesta ordem:

1. **Endpoint:** Invoca `sender.Send(createPlaneCommand)`
2. **MediatR:** Identifica o tipo da requisição (`CreatePlaneCommand`)
3. **MediatR:** Consulta seu mapeamento interno para localizar o *handler* correspondente
4. **Localização:** Encontra que `CreatePlaneHandler` processa `CreatePlaneCommand`
5. **Resolução:** Solicita ao container de DI uma instância de `CreatePlaneHandler`
6. **Execução:** Invoca `handler.Handle(createPlaneCommand, cancellationToken)`
7. **Retorno:** A `Response` é devolvida ao endpoint original

***

### **Mapeamento Interno (Visão Simplificada)**

```csharp
// Representação interna simplificada do funcionamento do MediatR
public class Mediator : ISender
{
    private readonly Dictionary<Type, Type> _handlerMappings;
    
    public async Task<TResponse> Send<TResponse>(IRequest<TResponse> request, 
                                                 CancellationToken cancellationToken)
    {
        // 1. Identifica o tipo da requisição recebida
        var requestType = request.GetType();
        
        // 2. Consulta o mapeamento para encontrar o handler correspondente
        var handlerType = _handlerMappings[requestType];
        
        // 3. Obtém uma instância do handler do container de DI
        var handler = _serviceProvider.GetService(handlerType);
        
        // 4. Executa o método Handle do handler
        return await ((dynamic)handler).Handle((dynamic)request, cancellationToken);
    }
}
```

***

### **Exemplo de Mapeamentos Internos**

* `CreatePlaneCommand` → `CreatePlaneHandler`
* `UpdatePlaneCommand` → `UpdatePlaneHandler`
* `GetPlaneQuery` → `GetPlaneHandler`&#x20;

***

### **Registro Automático&#x20;*****versus*****&#x20;Manual**

#### **Registro Automático (com MediatR)**

```csharp
// Configuração única - MediatR descobre e registra todos os handlers automaticamente
services.AddMediatR(cfg => 
    cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));
```

#### **Registro Manual (sem MediatR)**

```csharp
// Registro explícito e repetitivo para cada handler do sistema
services.AddTransient<CreatePlaneHandler>();
services.AddTransient<UpdatePlaneHandler>();
services.AddTransient<DeletePlaneHandler>();
services.AddTransient<GetPlaneHandler>();
// ... continuação para todos os handlers existentes
```

***

### **Análise Comparativa**

#### **Benefício do Abordagem Automática**

Eliminação de código repetitivo e propenso a erros. A adição de novos casos de uso não requer modificações na configuração de DI, tornando o sistema mais escalável e de mais fácil manutenção.&#x20;

O MediatR atua como um *service locator* inteligente que gerencia automaticamente o roteamento entre comandos/queries e seus respectivos handlers.

***

## Testando a Implementação

### **Execução da Aplicação**

```bash
cd Aviator.Api
dotnet run
```

#### **Saída esperada**

```
Now listening on: http://localhost:5070
Application started. Press Ctrl+C to shut down.
```

***

### **Teste da Funcionalidade**

* **Método:** `POST`
* **URL:** `http://localhost:5070/v1/planes`
* **Headers:** `Content-Type: application/json`
* **Body:**

```json
{
    "name": "Boeing 747"
}
```

#### **Resposta esperada**

```json
{
    "message": "Plane Created"
}
```

***

### **Sequência do Fluxo da Requisição**

1. **CLIENTE** (Postman, cURL ou Frontend)\
   \&#xNAN;*Envia requisição HTTP POST com payload JSON*
2. **ENDPOINT API** (.NET `MapPost`)\
   \&#xNAN;*Recebe a requisição, desserializa o JSON para o objeto `CreatePlaneCommand`*
3. **`ISender.Send(createPlaneCommand)`**\
   \&#xNAN;*Invoca o mediador passando o comando para processamento*
4. **MEDIATR** (Roteamento interno)\
   \&#xNAN;*Identifica automaticamente qual `Handler` corresponde ao tipo `CreatePlaneCommand`*
5. **HANDLER** (`CreatePlaneHandler`)\
   \&#xNAN;*Executa a lógica de negócio contida no método `Handle`*
6. **RESPONSE** (Record de retorno)\
   \&#xNAN;*Cria o objeto de resposta (`Response` record)*
7. **JSON** (Serialização automática)\
   \&#xNAN;*Serializa o objeto `Response` para JSON e retorna ao cliente*

***

### **Verificação dos Registros (Depuração)**

Para confirmar o correto registro dos handlers no container de DI:

```csharp
// Adicione temporariamente para verificação (apenas desenvolvimento)
var serviceProvider = builder.Services.BuildServiceProvider();
var sender = serviceProvider.GetService<ISender>();

// O objeto 'sender' contém todos os mapeamentos configurados
// Command → Handler registrados automaticamente pelo MediatR
```

#### **Observação**

Esta verificação é recomendada apenas para **ambientes de desenvolvimento**, com o objetivo de validar a configuração do MediatR e o registro automático dos handlers.&#x20;

Em **produção**, o MediatR gerencia esses mapeamentos internamente sem necessidade de intervenção manual.

***

## Análise Crítica: Adoção do Padrão Mediator

### **Cenário Atual (3 Handlers)**

| Aspecto            | Sem MediatR                                                  | Com MediatR                                                    | Impacto                                               |
| ------------------ | ------------------------------------------------------------ | -------------------------------------------------------------- | ----------------------------------------------------- |
| **Registro no DI** | 3 registros manuais (`AddTransient<>` para cada handler)     | 1 registro automático via `AddApplication()`                   | **Redução:** 3 linhas → 1 linha                       |
| **Acoplamento**    | Endpoint conhece e depende diretamente do Handler específico | Endpoint conhece apenas a abstração `ISender`                  | **Desacoplamento:** API não sabe qual handler executa |
| **Complexidade**   | Código simples e direto, mas com acoplamento forte           | Introduz overhead do MediatR (biblioteca + roteamento interno) | **Trade-off** Simplicidade *versus* Flexibilidade     |
| **Manutenção**     | Fácil de entender para sistemas pequenos                     | Requer aprendizado do padrão MediatR                           | **Curva de aprendizado** inicial                      |

Para 3 handlers, o benefício é **moderado**. Em sistemas pequenos e com pouca probabilidade de crescimento, a simplicidade da solução manual pode ser preferível.

***

### **Cenário Futuro (50 Handlers)**

| Aspecto                    | Sem MediatR                                                   | Com MediatR                                                                     | Impacto                                                                              |
| -------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| **Registro no DI**         | 50 registros manuais (código repetitivo e propenso a erros)   | 1 registro automático (configuração única)                                      | <p><strong>Eficiência</strong></p><p>Elimina código boilerplate</p>                  |
| **Acoplamento**            | Endpoints fortemente acoplados aos handlers específicos       | Endpoints completamente desacoplados                                            | <p><strong>Flexibilidade</strong></p><p>Troca de handlers sem afetar APIs</p>        |
| **Cross-cutting Concerns** | Logging, validação, etc. repetidos em cada handler            | <p><strong>Pipeline Behaviors</strong></p><p>Implementação única para todos</p> | <p><strong>Consistência</strong></p><p>Comportamentos transversais centralizados</p> |
| **Manutenção**             | Mudar um handler pode exigir alteração em múltiplos endpoints | Endpoints não precisam ser modificados quando handlers mudam                    | <p><strong>Escalabilidade</strong></p><p>Crescimento controlado do sistema</p>       |
| **Novas Funcionalidades**  | Cada novo caso de uso exige modificação na configuração DI    | Novos handlers são descobertos automaticamente                                  | <p><strong>Produtividade</strong></p><p>Desenvolvimento mais ágil</p>                |

Para 50+ handlers, o benefício é **enorme**. O MediatR se torna essencial para gerenciar complexidade, promover desacoplamento e habilitar padrões arquiteturais avançados.

***

### **Análise de Custo-Benefício**

| Fator                    | Impacto em Sistema Pequeno    | Impacto em Sistema Grande                | Explicação                                        |
| ------------------------ | ----------------------------- | ---------------------------------------- | ------------------------------------------------- |
| **Complexidade Inicial** | Alta (aprendizado do MediatR) | Baixa (custo diluído)                    | Curva de aprendizado se paga com crescimento      |
| **Código Boilerplate**   | Pouca redução                 | Redução drástica (50+ linhas eliminadas) | Benefício acumulativo com escala                  |
| **Desacoplamento**       | Benefício limitado            | Benefício crítico para manutenção        | Sistemas grandes exigem modularidade              |
| **Cross-cutting**        | Pode ser excessivo            | Essencial para consistência              | Comportamentos transversais tornam-se necessários |
| **Testabilidade**        | Melhora moderada              | Melhora significativa                    | Handlers isolados são mais fáceis de testar       |

O MediatR oferece **retorno sobre investimento crescente** - quanto maior e mais complexo o sistema, maior o valor proporcionado pela padronização, desacoplamento e recursos como Pipeline Behaviors.

***

## Diretrizes para Adoção do MediatR

Utilizar:

| Contexto                                                      | Justificativa                                                                                             |
| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Projeto com perspectiva de crescimento (> 10-20 handlers)     | O custo inicial é diluído pelo benefício de escalabilidade e manutenção a longo prazo                     |
| Necessidade de funcionalidades avançadas (Pipeline Behaviors) | Implementação centralizada de logging, validação, caching, autorização e outras preocupações transversais |
| Sistema requer Pub/Sub (múltiplos handlers para um evento)    | Suporte nativo a notificações e processamento paralelo de eventos                                         |
| Equipe numerosa trabalhando em paralelo                       | Padronização que facilita a colaboração e reduz conflitos de integração                                   |
| Sistema complexo com muitas cross-cutting concerns            | Pipeline Behaviors eliminam duplicação de código em funcionalidades transversais                          |
| Aversão a dependências externas                               | Projetos que minimizam dependências de terceiros                                                          |
| Uso limitado ao roteamento básico                             | Se não aproveitará features avançadas, a solução manual pode ser mais adequada                            |

Não utilizar:

| Contexto                                              | Justificativa                                                                  |
| ----------------------------------------------------- | ------------------------------------------------------------------------------ |
| Projeto muito simples (3-5 handlers básicos)          | Overhead da biblioteca não compensa o benefício em sistemas pequenos           |
| Performance crítica extrema (microssegundos importam) | Roteamento interno do MediatR adiciona latência mensurável                     |
| Aversão a dependências externas                       | Projetos que minimizam dependências de terceiros                               |
| Uso limitado ao roteamento básico                     | Se não aproveitará features avançadas, a solução manual pode ser mais adequada |

***

### **Análise de Decisão por Tamanho de Projeto**

<table data-full-width="false"><thead><tr><th>Tamanho do Projeto</th><th>Handlers</th><th>Recomendação</th><th>Razão Principal</th></tr></thead><tbody><tr><td><strong>Pequeno/Prova de Conceito</strong></td><td>1-5</td><td>Avaliar necessidade</td><td>Overhead pode superar benefícios</td></tr><tr><td><strong>Médio</strong></td><td>6-15</td><td>Considerar uso</td><td>Começa a valer a pena para organização</td></tr><tr><td><strong>Grande/Enterprise</strong></td><td>16-50</td><td>Altamente recomendado</td><td>Benefícios de escalabilidade são críticos</td></tr><tr><td><strong>Muito Grande</strong></td><td>50+</td><td>Essencial</td><td>Gerenciamento manual se torna impraticável</td></tr></tbody></table>

***

### **Considerações Técnicas Específicas**

| Característica  | Favorece MediatR                            | Desfavorece MediatR                       |
| --------------- | ------------------------------------------- | ----------------------------------------- |
| **Arquitetura** | Clean Architecture, DDD, CQRS               | Monolito simples, CRUD básico             |
| **Time**        | Múltiplos desenvolvedores, squads           | Desenvolvedor único ou time muito pequeno |
| **Manutenção**  | Longo prazo, evolução constante             | Curto prazo, baixa manutenção             |
| **Testes**      | Testabilidade importante, TDD               | Testes não são prioridade                 |
| **Performance** | Latência aceitável na casa de milissegundos | Micro-otimização crítica (microssegundos) |

A decisão deve considerar não apenas o tamanho atual, mas a **trajetória de crescimento** do projeto.&#x20;

MediatR oferece maior valor em sistemas que evoluirão em complexidade e exigirão padronização para sustentabilidade a longo prazo.

***

## **Transição para MediatR: Guia de Migração**

Se o projeto foi iniciado sem MediatR e agora requer sua adoção, a transição é direta e segue um padrão consistente.

### **Alterações por Componente**

#### **Comando (Request)**

```diff
- public record Command(string Name) : ICommand;
+ public record Command(string Name) : IRequest<Response>;
```

#### **Handler**

```diff
- public class Handler : IHandler<Command, Response>
+ public class Handler : IRequestHandler<Command, Response>
  
- public async Task<Response> HandleAsync(Command command)
+ public async Task<Response> Handle(Command request, CancellationToken cancellationToken)
```

***

### **Mudanças Principais**

| O que mudou                 | Antes                   | Depois                          |
| --------------------------- | ----------------------- | ------------------------------- |
| **Contrato do Handler**     | Interface personalizada | Interface padrão do MediatR     |
| **Método de processamento** | `HandleAsync`           | `Handle`                        |
| **Parâmetros**              | Apenas o comando        | Comando + token de cancelamento |

**Tempo estimado por handler:** 2-5 minutos

***

### **Etapas Adicionais da Migração**

1. **Adicionar pacote** `MediatR` ao projeto
2. **Configurar** injeção de dependência
3. **Atualizar** endpoints para usar `ISender`
4. **Remover** registros manuais de handlers

A migração pode ser realizada de forma **progressiva**, permitindo convivência temporária entre handlers antigos e novos durante a transição.

***

## Comparação Detalhada

| Aspecto           | Sem MediatR             | Com MediatR              |
| ----------------- | ----------------------- | ------------------------ |
| **Acoplamento**   | Alto (Endpoint→Handler) | Baixo (Endpoint→ISender) |
| **Registro**      | Manual (cada handler)   | Automático (scanning)    |
| **Manutenção**    | Mais trabalho           | Menos trabalho           |
| **Performance**   | Máxima                  | Pequeno overhead         |
| **Complexidade**  | Baixa                   | Média                    |
| **Flexibilidade** | Baixa                   | Alta                     |
| **Cross-cutting** | Em cada handler         | Pipeline behaviors       |
| **Testabilidade** | Igual                   | Igual                    |

***

## Próximos Passos (se usar MediatR)

### Pipeline Behaviors (Middleware)

```csharp
// Logging automático para TODOS handlers
public class LoggingBehavior<TRequest, TResponse> 
    : IPipelineBehavior<TRequest, TResponse>
{
    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        // Log antes
        Console.WriteLine($"Handling {typeof(TRequest).Name}");
        
        var response = await next();
        
        // Log depois
        Console.WriteLine($"Handled {typeof(TRequest).Name}");
        
        return response;
    }
}

// Registro (uma vez, vale para todos handlers)
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
```

***

### Validação Centralizada

```csharp
// Validação automática para todos os requests
public class ValidationBehavior<TRequest, TResponse> 
    : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IValidatable
{
    // Valida TUDO automaticamente
}
```

***

### Eventos (Pub/Sub)

```csharp
// Múltiplos handlers para um evento
public class PlaneCreatedEvent : INotification
{
    public int PlaneId { get; set; }
}

public class SendEmailHandler : INotificationHandler<PlaneCreatedEvent>
{
    public Task Handle(PlaneCreatedEvent notification, CancellationToken ct)
    {
        // Envia email
    }
}

public class UpdateAuditHandler : INotificationHandler<PlaneCreatedEvent>  
{
    public Task Handle(PlaneCreatedEvent notification, CancellationToken ct)
    {
        // Atualiza auditoria
    }
}

// Ambos são executados quando o evento é publicado
```

***

### Evoluindo a Implementação

```csharp
// Aviator.Application/DependencyInjection.cs (atualizado)
public static IServiceCollection AddApplication(this IServiceCollection services)
{
    services.AddMediatR(cfg =>
    {
        cfg.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly);
    });
    
    // Registra behaviors na ordem desejada
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(TransactionBehavior<,>));
    
    return services;
}

// Fluxo com behaviors:
// Request → Logging → Validation → Transaction → Handler → Response
```

***

### Adicionando Validação com FluentValidation

```csharp
// Command com validação
public record Command(string Name) : IRequest<Response>, IValidatable;

// Behavior de validação
public class ValidationBehavior<TRequest, TResponse> 
    : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IValidatable
{
    private readonly IEnumerable<IValidator<TRequest>> _validators;
    
    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        if (_validators.Any())
        {
            var context = new ValidationContext<TRequest>(request);
            var results = await Task.WhenAll(
                _validators.Select(v => v.ValidateAsync(context, cancellationToken)));
            
            var failures = results.SelectMany(r => r.Errors).Where(f => f != null).ToList();
            
            if (failures.Count != 0)
                throw new ValidationException(failures);
        }
        
        return await next();
    }
}
```

***

## Perguntas Frequentes

#### 1. O MediatR substitui minha lógica de negócio?

**Não!** Apenas o **roteamento** Command→Handler. Sua lógica continua igual.

#### 2. Posso migrar gradualmente?

**Sim!** Alguns handlers com MediatR, outros sem. O sistema funciona misturado.

#### 3. E se dois Handlers processarem mesmo Command?

**Erro em tempo de execução.** MediatR não permite (um Command = um Handler).

#### 4. Funciona com controllers MVC tradicionais?

**Sim perfeitamente!** Não é exclusivo para Minimal APIs.

#### 5. O CancellationToken é obrigatório?

**Não, mas recomendado.** Use `= default` se não quiser lidar com cancelamento.

***

## Resumo

Análise de Adoção do MediatR

### **Benefícios**

| Vantagem                               | Efeito Concreto                                                                                                 |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| **Desacoplamento alcançado**           | Separação estabelecida entre endpoints e implementações de handlers                                             |
| **Registro automatizado**              | Eliminada a necessidade de configuração manual de cada handler no container de DI                               |
| **Pipeline integrado disponibilizado** | Infraestrutura provida para implementação centralizada de logging, validação e outras preocupações transversais |
| **Escalabilidade habilitada**          | Suporte estruturado implementado para crescimento progressivo do número de casos de uso                         |
| **Convenções padronizadas adotadas**   | Alinhamento realizado com práticas consolidadas pela comunidade .NET                                            |

#### **Contrapontos**

| Aspecto                                | Implicação                                                         |
| -------------------------------------- | ------------------------------------------------------------------ |
| **Dependência externa introduzida**    | Biblioteca de terceiros adicionada ao ecossistema do projeto       |
| **Overhead de performance adicionado** | Latência incremental incorporada ao processo de roteamento         |
| **Curva de aprendizado requerida**     | Período de adaptação necessário para assimilação dos novos padrões |

A adoção do **MediatR** é **recomendada** para sistemas que apresentam as seguintes características:

* Volume significativo de casos de uso existentes ou planejados
* Necessidade comprovada de separação clara entre camadas arquiteturais
* Requisitos identificados para funcionalidades transversais centralizadas

Para **protótipos** ou **sistemas de escopo reduzido**, a complexidade introduzida pode ser **desproporcional** aos benefícios obtidos. Em **contextos empresariais** ou **arquiteturas em evolução**, o investimento é **justificado** pelos ganhos em **manutenibilidade**, **capacidade de expansão** e **uniformidade** da base de código.

***

## Recomendações

### **Diretrizes para Decisão**

| Contexto                | Recomendação                                                                         | Critério Decisório                                 |
| ----------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------- |
| **Novos Projetos**      | Inicie com MediatR se projetar >10 handlers ou necessitar de features avançadas      | Análise prospectiva da complexidade arquitetural   |
| **Projetos Existentes** | Considere migração ao ultrapassar 15 handlers com cross-cutting concerns repetitivos | Avaliação quantitativa e qualitativa da base atual |

### **Princípio Orientador**

O MediatR constitui uma ferramenta especializada para problemas específicos de mediação e desacoplamento. Sua adoção não é obrigatória, mas demonstra elevada utilidade quando aplicada ao contexto apropriado.

#### **Indicador Prático**

Se identificada a repetição de código transversal (ex: logging, validação) em múltiplos handlers, configura-se o momento adequado para avaliação do MediatR.

***

### **Implementação Realizada**

#### **Alterações Efetuadas**

```csharp
// Command: ICommand → IRequest<Response>
// Handler: IHandler → IRequestHandler  
// Endpoint: Referência direta → ISender
// Registro DI: Manual → Automático
```

#### **Benefícios Concretizados**

* Desacoplamento estabelecido entre endpoints e handlers
* Infraestrutura preparada para pipeline behaviors
* Base arquitetural escalável para crescimento futuro

#### **Custos Inerentes**

* Introdução de dependência externa
* Overhead mínimo de performance
* Período necessário para aprendizado

***

### **Estratégia de Adoção Progressiva**

#### **Fase Inicial**

Projetos de complexidade reduzida podem ser implementados sem MediatR.

#### **Ponto de Transição**

Migre para MediatR quando identificar:

* Proliferação significativa de handlers (>15)
* Duplicação de cross-cutting concerns
* Necessidade de eventos de domínio
* Requisito de desacoplamento forte entre camadas

#### **Observação**

A migração apresenta complexidade moderada (2-5 minutos por handler), com retorno justificado para sistemas em expansão arquitetural.
