Skip to content

Latest commit

 

History

History
173 lines (127 loc) · 12.5 KB

Anti-corruption Layer.md

File metadata and controls

173 lines (127 loc) · 12.5 KB

Anti-corruption Layer

tags: acl ddd anti corruption layer camada anticorrupção
Esse conteúdo é baseado na abordagem de ACL de Vaughn Vernon do livro Domain-Driven Design Distilled também conhecido como Green Book.
Esse conteúdo também é baseado na abordagem de ACL de Neal Ford do livro Building Evolutionary Architectures (cap. 6 e cap. 7).

Sumário

O que é a Anti-corruption Layer (ACL)

Anti-corruption Layer (ACL) é um padrão de arquitetura de abordagem defensiva que tem como proposta isolar um modelo de domínio de todas as suas respectivas integrações (microsserviços de terceiros, monólitos, aplicações de semântica diferentes etc.) movendo todos os recursos destinados a essa integração para uma camada de responsabilidade única que agrupa e gerencia todas as requisições entre as partes, reduzindo ou eliminando o alto acoplamento e dependências desnecessárias existente. É importante ressaltar que esse desacoplamento também deve ser interpretado a nível de negócio. Na grande maioria das integrações intersistêmicas existentes atualmente, independente se são internas ou externas a organização não há a necessidade dos negócios estarem atrelados.

Contexto e possíveis problemas

Rotineiramente nos deparamos com cenários onde aplicações dependem de outras, seja para enriquecimento de informação ou funcionalidade e por esse motivo estão integradas e consequentemente acopladas, essa dependência pode gerar diversos problemas, alguns deles estão listados abaixo:

  • Uma API sem versionamento é atualizada pelo fornecedor quebrando o contrato e a compatibilidade.
  • Um serviço de um terceiro de um terceiro fica indisponível.
  • Bibliotecas utilizadas mudam sua interface pública quebrando a compatibilidade.
  • Sistemas modernos precisam se comunicar com sistemas legados ou monólitos, necessitando assim de adaptações, traduções ou ajustes no transporte da informação trocada.
  • Alta dependência entre contextos exigindo sincronização de comunicação que pode gerar gargalos e custos para o alinhamento.

Entendendo a solução

Para lidar com os problemas exemplificados anteriormente, posicionamos uma camada anticorrupção entre os domínios, essa camada move as comunicações entre as partes, isolando o domínio e permitindo que ele permaneça inalterado, evitando assim comprometer seu comportamento, design e sua abordagem tecnológica, em resumo, impedindo sua corrupção.

ACL-2022-06-21-1103

O desenho acima mostra uma representação simplificada da ACL em uma comunicação entre dois domínios, um deles (Domínio B) sendo de uma fonte terceira.

Note

A proposta do pattern da ACL é agrupar toda a lógica de comunicação entre os domínios (Adapters, Façades, Translators etc.) e a camada pode ser implementada como um componente da aplicação ou como um serviço independente.

Cuidados e considerações

Ao implementar uma camada anticorrupção é preciso estar ciente e tomar alguns cuidados, os mais relevantes estão listados a seguir:

  • Considere como a camada anticorrupção será dimensionada.
  • A camada anticorrupção, se não for corretamente dimensionada e construída, pode adicionar latência para chamadas feitas entre as partes.
  • A camada anticorrupção adiciona outro serviço ao domínio que deve ser gerenciado e mantido.
  • Considere se você precisa de mais de uma camada anticorrupção. Em alguns casos pode ser interessante decompor a funcionalidade em vários serviços considerando por exemplo a afinidade das tecnologias ou o uso de linguagens diferentes.
  • Considere como a camada anticorrupção será gerenciada em relação a outros aplicativos ou serviços. Por exemplo, como ela será integrada aos processos de monitoramento, versão e configuração da organização.
  • Certifique-se de que a transação e a consistência das informações sejam mantidas e que possam ser monitoradas.
  • Leve em consideração se a camada anticorrupção precisa lidar com toda a comunicação entre diferentes microsserviços ou apenas com alguns recursos.
  • Se a camada anticorrupção fizer parte de uma estratégia de migração, leve em consideração se ela será permanente ou se perderá o sentido depois que todas as funcionalidades herdadas forem migradas.

Quando utilizar esse padrão

Como diversos outros padrões de arquitetura, não existe uma convenção formal sobre a utilização da ACL. Vaughn Vernon ao abordar o tema no livro Domain Driven Design Distilled, diz que sempre que possível devemos utilizar a ACL entre o downstream model e upstream integration model, pois assim podemos produzir conceitos de modelo do nosso lado da integração que são específicos e se encaixam apenas ao nosso negócio, provendo assim um isolamento completo de interferências externas. Já a abordagem da ACL na documentação de padrões de arquiteturas oficial da Microsoft, são citados cenários bem mais específicos como: ¹ Planos de migrações em estágios, onde integrações precisam ser mantidas e herdadas. ² Situações em que dois ou mais microsserviços com semânticas diferentes precisam se comunicar.

EXTRA: Representações visuais

Com o intuito de facilitar o entendimento de alguns dos problemas abordados em Contexto e possíveis problemas, criei representações visuais detalhadas abaixo:

Cenário 1 - Atualização de API sem versionamento

Uma informação consumida pelo nosso domínio está integrada diretamente ao terceiro que a disponibiliza:

scene1_apiupdate-2022-06-21-1504

O fornecedor da informação decide atualizar a API consumida pelo Domínio A, sem versionamento e muda a estrutura do JSON trafegado adicionando informações que não tem relevância para o nosso negócio:

scene1_apiupdate_broken-2022-06-21-1504

Em uma integração direta podemos observar que os Microsserviços do domínio A, que dependem dessa informação param de funcionar como deveriam por estarem altamente acoplados. Além disso, precisaríamos corrigir esse comportamento em dois Microsserviços distintos, alterando a lógica de ambos para passar a entender a nova estrutura trafegada.

A seguir uma representação do mesmo cenário, porém com uma camada de ACL entre a comunicação das partes:

scene1_apiupdate_broken_withACL-2022-06-21-1504 Já nessa situação podemos ver que apenas a camada de ACL é parcialmente afetada, a manutenção fica centralizada em um único ponto, os nossos serviços no Domínio A, permanecem íntegros e conseguimos traduzir ou adaptar essa informação trafegada na ACL para a nossa necessidade interna específica.

⬅️ Voltar para Contexto e possíveis problemas

Cenário 2 - Serviço de terceiros com indisponibilidade

Uma comunicação entre os nossos serviços e o de um terceiro está diretamente integrada:

scene2_broken_thid_part_service-2022-06-22-1048

Agora vamos supor que alguma razão o serviço do terceiro fica indisponível. Observamos que toda a nossa parte que está acoplada àquele serviço será afetada e ficará indisponível:

scene2_broken_thid_part_service_lost_connection-2022-06-22-1048

Vamos observar como seria essa situação caso a arquitetura tivesse a camada de ACL implementada:

scene2_broken_thid_part_service_lost_connection_ACL-2022-06-22-1048

Podemos ver que a ACL isola e protege o nosso lado da integração, assim como no caso anterior a camada é parcialmente afetada, mas nossos serviços no domínio A permanecem de pé.

Implementando uma ACL

  1. Crie uma classe para representar o modelo de dados do sistema externo. Vamos chamar essa classe de ExternalSystemData.
public class ExternalSystemData
{
    public string Data1 { get; set; }
    public string Data2 { get; set; }
    // ... outras propriedades
}
  1. Crie uma classe para representar o modelo de dados de seu aplicativo principal. Vamos chamar essa classe de InternalData.
public class InternalData
{
    public string DataA { get; set; }
    public string DataB { get; set; }
    // ... outras propriedades
}
  1. Crie uma classe para a ACL. Vamos chamar essa classe de AntiCorruptionLayer. Esta classe terá métodos para transformar dados do modelo de dados do sistema externo para o modelo de dados do aplicativo principal e vice-versa.
public class AntiCorruptionLayer
{
    public InternalData MapFromExternalSystemData(ExternalSystemData externalSystemData)
    {
        return new InternalData
        {
            DataA = externalSystemData.Data1,
            DataB = externalSystemData.Data2
            // ... mapeie outras propriedades
        };
    }

    public ExternalSystemData MapToExternalSystemData(InternalData internalData)
    {
        return new ExternalSystemData
        {
            Data1 = internalData.DataA,
            Data2 = internalData.DataB
            // ... mapeie outras propriedades
        };
    }
}
  1. Use a ACL em seu aplicativo principal. Sempre precisar interagir com o sistema externo, use a ACL para transformar os dados entre os dois sistemas.
AntiCorruptionLayer acl = new AntiCorruptionLayer();

// Faça um de para da informação do sistema externo para o principal
ExternalSystemData externalSystemData = GetDataFromExternalSystem();
InternalData internalData = acl.MapFromExternalSystemData(externalSystemData);

// Faça um de para no sentido oposto, do sistema principal para o externo
InternalData updatedInternalData = GetUpdatedInternalData();
ExternalSystemData updatedExternalSystemData = acl.MapToExternalSystemData(updatedInternalData);
SaveDataToExternalSystem(updatedExternalSystemData); }
}

Important

E lembre-se:

Esse é apenas um exemplo simples para demonstrar como você pode criar uma ACL em C#.

Em uma aplicação real, você provavelmente teria modelos de dados e transformações mais complexos.

A ideia principal é usar a ACL para separar o restante do aplicativo das alterações no modelo de dados do sistema externo, facilitando a manutenção do aplicativo e a adaptação às alterações no sistema externo ao longo do tempo.

⬆️ Voltar para o início