

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Padrão da camada anticorrupção
<a name="acl"></a>

## Intenção
<a name="acl-intent"></a>

O padrão de camada anticorrupção (ACL) atua como uma camada de mediação que converte a semântica do modelo de domínio de um sistema para outro. Ele converte o modelo do contexto limitado upstream (monólito) em um modelo adequado ao contexto limitado downstream (microsserviço) antes de consumir o contrato de comunicação estabelecido pela equipe ascendente. Esse padrão pode ser aplicável quando o contexto limitado downstream contém um subdomínio principal ou o modelo upstream é um sistema legado não modificável. Também reduz o risco de transformação e a interrupção dos negócios, evitando alterações nos chamadores quando suas chamadas precisam ser redirecionadas de forma transparente para o sistema de destino.

## Motivação
<a name="acl-motivation"></a>

Durante o processo de migração, quando uma aplicação monolítica é migrada para microsserviços, pode haver mudanças na semântica do modelo de domínio do serviço recém-migrado. Quando os recursos do monólito são necessários para chamar esses microsserviços, as chamadas devem ser roteadas para o serviço migrado sem exigir nenhuma alteração nos serviços de chamada. O padrão da ACL permite que o monólito chame os microsserviços de forma transparente, atuando como um adaptador ou uma camada de fachada que converte as chamadas para a semântica mais recente.

## Aplicabilidade
<a name="acl-applicability"></a>

Considere usar esse padrão quando:
+ Sua aplicação monolítica existente precisa se comunicar com uma função que foi migrada para um microsserviço, e o modelo e a semântica do domínio de serviço migrado diferem do recurso original.
+ Dois sistemas têm semânticas diferentes e precisam trocar dados, mas não é prático modificar um sistema para ser compatível com o outro sistema.
+ Você quer usar uma abordagem rápida e simplificada para adaptar um sistema a outro com o mínimo impacto.
+ Sua aplicação está se comunicando com um sistema externo.

## Problemas e considerações
<a name="acl-issues"></a>
+ **Dependências da equipe:** quando diferentes serviços em um sistema pertencem a equipes diferentes, a nova semântica do modelo de domínio nos serviços migrados pode levar a mudanças nos sistemas de chamada. No entanto, as equipes podem não conseguir fazer essas mudanças de forma coordenada, pois podem ter outras prioridades. A ACL separa os receptores e converte as chamadas para corresponder à semântica dos novos serviços, evitando assim a necessidade de os chamadores fazerem alterações no sistema atual.
+ **Sobrecarga operacional:** o padrão da ACL exige esforço adicional para operar e manter. Esse trabalho inclui a integração da ACL com ferramentas de monitoramento e alerta, o processo de lançamento e os processos de integração e entrega contínuas (CI/CD).
+ **Ponto único de falha:** qualquer falha na ACL pode tornar o serviço de destino inacessível, causando problemas na aplicação. Para mitigar esse problema, você deve incorporar recursos de repetição e disjuntores. Consulte a nova [tentativa com os padrões de recuo](retry-backoff.md) e [disjuntor](circuit-breaker.md) para entender mais sobre essas opções. A configuração de alertas e registros apropriados melhorará o tempo médio de resolução (MTTR).
+ **Dívida técnica:** como parte de sua estratégia de migração ou modernização, considere se a ACL será uma solução transitória ou provisória ou uma solução de longo prazo. Se for uma solução provisória, você deve registrar a ACL como uma dívida técnica e desativá-la depois que todos os chamadores dependentes tiverem sido migrados.
+ **Latência:** a camada adicional pode introduzir latência devido à conversão de solicitações de uma interface para outra. Recomendamos que você defina e teste a tolerância de performance em aplicações sensíveis ao tempo de resposta antes de implantar a ACL em ambientes de produção.
+ **Gargalo de escalabilidade:** em aplicações de alta carga em que os serviços podem ser escalados até o pico de carga, a ACL pode se tornar um gargalo e causar problemas de escalabilidade. Se o serviço de destino for escalado sob demanda, você deverá projetar a ACL para escalar adequadamente.
+ **Implementação compartilhada ou específica do serviço:** você pode criar a ACL como um objeto compartilhado para converter e redirecionar chamadas para vários serviços ou classes específicas de serviços. Leve em consideração a latência, a escalabilidade e a tolerância a falhas ao determinar o tipo de implementação da ACL.

## Implementação
<a name="acl-implementation"></a>

Você pode implementar a ACL dentro da sua aplicação monolítica como uma classe específica para o serviço que está sendo migrado ou como um serviço independente. A ACL deve ser desativada após a migração de todos os serviços dependentes para a arquitetura de microsserviços.

### Arquitetura de alto nível
<a name="acl-high-level-arch"></a>

No exemplo de arquitetura a seguir, uma aplicação monolítica tem três serviços: serviço de usuário, serviço de carrinho e serviço de conta. O serviço de carrinho depende do serviço do usuário, e a aplicação usa um banco de dados relacional monolítico.

![\[Aplicação monolítica com três serviços.\]](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/cloud-design-patterns/images/acl-1.png)


Na arquitetura a seguir, o serviço do usuário foi migrado para um novo microsserviço. O serviço de carrinho chama o serviço de usuário, mas a implementação não está mais disponível no monólito.  Também é provável que a interface do serviço recém-migrado não corresponda à interface anterior, quando estava dentro da aplicação monolítica.

![\[Aplicação monolítica em que um serviço é transferido para um microsserviço.\]](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/cloud-design-patterns/images/acl-2.png)


Se o serviço de carrinho precisar ligar diretamente para o serviço de usuário recém-migrado, isso exigirá alterações no serviço de carrinho e um teste completo da aplicação monolítica. Isso pode aumentar o risco de transformação e a interrupção dos negócios. O objetivo deve ser minimizar as alterações na funcionalidade existente da aplicação monolítica.

Nesse caso, recomendamos que você introduza uma ACL entre o serviço de usuário antigo e o serviço de usuário recém-migrado. A ACL funciona como um adaptador ou uma fachada que converte as chamadas na interface mais recente. A ACL pode ser implementada dentro da aplicação monolítica como uma classe (por exemplo, `UserServiceFacade` ou `UserServiceAdapter`) específica do serviço que foi migrado. A camada anticorrupção deverá ser desativada depois que todos os serviços dependentes tiverem sido migrados para a arquitetura de microsserviços.

![\[Adição de uma camada anticorrupção.\]](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/cloud-design-patterns/images/acl-3.png)


### Implementação usando serviços AWS
<a name="acl-aws-services"></a>

O diagrama a seguir mostra como você pode implementar esse exemplo de ACL usando serviços da AWS.

![\[Implementação do padrão da ACL com serviços da AWS.\]](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/cloud-design-patterns/images/acl-4.png)


O microsserviço do usuário é migrado da aplicação ASP.NET monolítica e implantado como uma função do [AWS Lambda](https://aws.amazon.com/lambda/) na AWS. As chamadas para a função do Lambda são roteadas pelo [Amazon API Gateway](https://aws.amazon.com/api-gateway/). A ACL é implantada no monólito para converter a chamada e se adaptar à semântica do microsserviço do usuário.

Quando `Program.cs` chama o serviço do usuário (`UserInMonolith.cs`) dentro do monólito, a chamada é roteada para a ACL (`UserServiceACL.cs`). A ACL converte a chamada para a nova semântica e interface e chama o microsserviço por meio do endpoint do API Gateway. O chamador (`Program.cs`) não está ciente da conversão e do roteamento que ocorrem no serviço ao usuário e na ACL. Como o chamador não está ciente das mudanças no código, há menos interrupções nos negócios e menor risco de transformação.

### Código de exemplo
<a name="acl-sample-code"></a>

O trecho de código a seguir fornece as alterações no serviço original e a implementação de `UserServiceACL.cs`. Quando uma solicitação é recebida, o serviço de usuário original chama a ACL. A ACL converte o objeto de origem para corresponder à interface do serviço recém-migrado, chama o serviço e retorna a resposta ao chamador.

```
public class UserInMonolith: IUserInMonolith
{
    private readonly IACL _userServiceACL;
    public UserInMonolith(IACL userServiceACL) => (_userServiceACL) = (userServiceACL);
    public async Task<HttpStatusCode> UpdateAddress(UserDetails userDetails)
    {
        //Wrap the original object in the derived class 
        var destUserDetails = new UserDetailsWrapped("user", userDetails);
        //Logic for updating address has been moved to a microservice
        return await _userServiceACL.CallMicroservice(destUserDetails);
    }
}

public class UserServiceACL: IACL
{
    static HttpClient _client = new HttpClient();
    private static string _apiGatewayDev = string.Empty;

    public UserServiceACL()
    {
        IConfiguration config = new ConfigurationBuilder().AddJsonFile(AppContext.BaseDirectory + "../../../config.json").Build();
        _apiGatewayDev = config["APIGatewayURL:Dev"];
        _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }
    public async Task<HttpStatusCode> CallMicroservice(ISourceObject details)
    {
        _apiGatewayDev +=  "/" + details.ServiceName;
        Console.WriteLine(_apiGatewayDev);

        var userDetails = details as UserDetails;
        var userMicroserviceModel = new UserMicroserviceModel();
        userMicroserviceModel.UserId = userDetails.UserId;
        userMicroserviceModel.Address = userDetails.AddressLine1 + ", " + userDetails.AddressLine2;
        userMicroserviceModel.City = userDetails.City;
        userMicroserviceModel.State = userDetails.State;
        userMicroserviceModel.Country = userDetails.Country;

        if (Int32.TryParse(userDetails.ZipCode, out int zipCode))
        {
            userMicroserviceModel.ZipCode = zipCode;
            Console.WriteLine("Updated zip code");
        }
        else
        {
            Console.WriteLine("String could not be parsed.");
            return HttpStatusCode.BadRequest;
        }

        var jsonString = JsonSerializer.Serialize<UserMicroserviceModel>(userMicroserviceModel);
        var payload = JsonSerializer.Serialize(userMicroserviceModel);
        var content = new StringContent(payload, Encoding.UTF8, "application/json");

        var response = await _client.PostAsync(_apiGatewayDev, content);
        return response.StatusCode;
    }  
}
```

### Repositório GitHub
<a name="acl-github-repo"></a>

****

Para uma implementação completa da arquitetura de amostra desse padrão, consulte o repositório do GitHub em [https://github.com/aws-samples/anti-corruption-layer-pattern](https://github.com/aws-samples/anti-corruption-layer-pattern).

## Conteúdo relacionado
<a name="acl-resources"></a>
+ [padrão strangler fig](strangler-fig.md)
+ [Padrão de disjuntor](circuit-breaker.md)
+ [Tente novamente com o padrão de recuo](retry-backoff.md)