.NET - Camada anti-corrupção (Anti-Corruption Layer)


  Hoje vou apresentar o padrão ACL - Anti-Corruption Layer - ou camada anti-corrupção.

A camada anti-corrupção (ACL) é um padrão de arquitetura de software que é usado para proteger um sistema de software de ser corrompido por um outro sistema de software. A ACL é geralmente implementada como uma camada entre os dois sistemas de software, e é responsável por traduzir as chamadas entre os dois sistemas de software.

Refinando um pouco mais podemos dizer que uma camada anticorrupção (ACL) é um conjunto de padrões colocados entre o modelo de domínio e outros contextos limitados ou dependências de terceiros. A intenção dessa camada é evitar a intrusão de conceitos e modelos estranhos no modelo de domínio.

A ACL é usada para proteger o sistema de software de ser corrompido de várias maneiras. Por exemplo, a ACL pode ser usada para:

A ACL pode ser usada em qualquer plataforma de software, incluindo a plataforma .NET. Na plataforma .NET, a ACL pode ser implementada usando o .NET Framework ou o .NET Core. A seguir veremos dois cenários para ilustrar o uso deste recurso:

1- Suponha que você esteja desenvolvendo uma aplicação que precise interagir com um serviço externo de autenticação para validar as credenciais dos usuários.

Em vez de fazer chamadas diretas a esse serviço em toda a sua aplicação, você pode criar uma camada anti-corrupção para encapsular a lógica de interação com o serviço externo.

A seguir temos um esboço de implementação para uma camada anti-corrupção :

public interface IAuthService
{
 
bool AuthenticateUser(string username, string password);
}

public class ExternalAuthService : IAuthService
{
 
public bool AuthenticateUser(string username, string password)
  {
   
// Lógica de chamada ao serviço externo de autenticação
    // Retorna true se o usuário for autenticado com sucesso, caso contrário, false

  }
}

public class AntiCorruptionAuthService : IAuthService
{
  
private readonly IAuthService _externalAuthService;
  
public AntiCorruptionAuthService(IAuthService externalAuthService)
   {
     _externalAuthService = externalAuthService;
   }

  
public bool AuthenticateUser(string username, string password)
   {
    
// Adaptar e traduzir os dados recebidos pela aplicação para
     // o formato esperado pelo serviço externo, se necessário.
     // Chamar o serviço externo através da instância de IAuthService
     // Adaptar e traduzir a resposta do serviço externo para o formato
     // esperado pela aplicação, se necessário.
     // Retornar o resultado da autenticação para a aplicação
     // Exemplo simplificado, apenas repassa a chamada para o serviço externo
    
return _externalAuthService.AuthenticateUser(username, password);
   }
}

Nesse exemplo, a interface IAuthService define um contrato para a autenticação de usuários, e, a classe ExternalAuthService é a implementação concreta dessa interface, que lida diretamente com a interação com o serviço externo de autenticação.

A classe AntiCorruptionAuthService é a camada anti-corrupção. Ela recebe uma instância de IAuthService (no caso, ExternalAuthService) por meio de injeção de dependência no construtor, e, , no interior do método AuthenticateUser, ela pode realizar qualquer adaptação, tradução ou mapeamento necessários entre a aplicação e o serviço externo antes de fazer a chamada real para autenticar o usuário.

Dessa forma, a aplicação principal pode depender apenas da interface IAuthService e não precisa conhecer os detalhes de implementação do serviço externo. Isso facilita a substituição ou a troca da implementação do serviço sem afetar a lógica da aplicação.

2- Suponha que você esteja desenvolvendo uma API ASP.NET Core que precisa consumir dados de um serviço externo. Vamos criar uma camada anti-corrupção para encapsular a lógica de chamada e adaptação dos dados desse serviço.

Neste esboço, vamos usar uma API que busca informações de usuários em um serviço externo:

// Classe de modelo para representar um usuário
using
System.Runtime.InteropServices;

public class User
{
 
public string Name { get; set; }
 
public string Email { get; set; }
}

// Interface para a camada anti-corrupção
public
interface IUserService
{
  User GetUser(
string userId);
}

// Implementação da camada anti-corrupção
public
class ExternalUserService : IUserService
{
 
public User GetUser(string userId)
  {
   
// Lógica de chamada ao serviço externo para buscar
    // o usuário com o ID fornecido
    // Retorna um objeto User com os dados do usuário
    // encontrado no serviço externo
    // Exemplo simplificado, retornando um objeto User vazio
   
return new User();
  }
}

// Controller da API
[ApiController]
[Route(
"api/users")]
public
class UsersController : ControllerBase
{
 
private readonly IUserService _userService;
 
public UsersController(IUserService userService)
  {
    _userService = userService;
  }

  [HttpGet(
"{userId}")]
 
public IActionResult GetUser(string userId)
  {
    User user = _userService.GetUser(userId);
   
if (user == null)
    {
     
return NotFound();
    }
   
return Ok(user);
  }
}

// Configuração da injeção de dependência na classe Program
...
   builder.Services.AddScoped<IUserService, ExternalUserService>();
   builder.Services.AddControllers();
...
 

Neste exemplo, a classe User representa um usuário com propriedades como nome e e-mail. A interface IUserService define o contrato para a camada anti-corrupção que busca usuários. A classe ExternalUserService é a implementação concreta dessa interface, que lida com a lógica de chamada ao serviço externo para buscar o usuário desejado.

O controller UsersController é responsável por lidar com as requisições HTTP relacionadas aos usuários. Ele recebe uma instância de IUserService por meio de injeção de dependência no construtor e utiliza o método GetUser para buscar o usuário desejado. Se o usuário não for encontrado, o controller retorna uma resposta de NotFound. Caso contrário, retorna o usuário encontrado na resposta.

Na classe Program configuramos a injeção de dependência usando AddScoped, especificando que a interface IUserService deve ser resolvida através da classe ExternalUserService. Isso permite que o ASP.NET Core forneça automaticamente uma instância de ExternalUserService para o construtor do UsersController.

Esse exemplo demonstra como a camada anti-corrupção pode ser utilizada em uma API ASP.NET Core para encapsular a lógica de integração com um serviço externo, facilitando a manutenção e testabilidade da aplicação.

Padrões usados

Na criação de uma camada anti-corrupção, alguns padrões e princípios de design podem ser aplicados para obter uma implementação eficaz. Aqui estão alguns padrões que são comumente utilizados:
  1. Facade: O padrão Facade é utilizado para fornecer uma interface simplificada e unificada para interagir com sistemas complexos. Na camada anti-corrupção, a classe Facade pode ser usada como uma fachada para expor métodos e funcionalidades específicas dos sistemas externos, simplificando o acesso a eles.
     
  2. Adapter: O padrão Adapter é usado para converter a interface de uma classe em outra interface que seja esperada pelo cliente. Na camada anti-corrupção, o Adapter pode ser aplicado para adaptar os objetos e dados recebidos dos sistemas externos para uma estrutura de dados interna, tornando-os compatíveis com a lógica da aplicação.
     
  3. Mapper: O padrão Mapper é usado para mapear objetos de um tipo para outro tipo, geralmente quando esses objetos têm estruturas diferentes. Na camada anti-corrupção, o Mapper pode ser empregado para mapear objetos recebidos dos sistemas externos para objetos internos, garantindo que a estrutura e os dados sejam corretamente adaptados.
     
  4. Dependency Injection: O princípio de Injeção de Dependência (Dependency Injection) é usado para fornecer dependências externas a uma classe, em vez de criá-las internamente. Na camada anti-corrupção, a Injeção de Dependência é essencial para separar e isolar a lógica de integração com sistemas externos, permitindo a substituição fácil das implementações e facilitando os testes.
     
  5. Interfaces: O uso de interfaces é fundamental na camada anti-corrupção para definir contratos e abstrações que representam as funcionalidades e comportamentos esperados dos sistemas externos. As interfaces permitem que diferentes implementações sejam usadas sem alterar a lógica interna da aplicação.

Esses padrões e princípios são algumas das ferramentas que podem ser aplicadas para criar uma camada anti-corrupção eficiente. No entanto, é importante lembrar que a escolha dos padrões depende do contexto específico do projeto e dos requisitos da aplicação. A combinação adequada desses padrões pode variar de acordo com as necessidades de integração com os sistemas externos.

Assim o desenvolvimento de uma camada anti-corrupção pode ser um processo trabalhoso que vai requerer muita análise e trabalho de desenvolvimento.

E estamos conversados.

"Seja bendito o nome do Senhor, desde agora para sempre."
Salmos 113:1

Referências:


José Carlos Macoratti