Microsserviço 2
Definir uma boa fronteira em um microsserviço é extremamente importante já que ter a capacidade de alterá-lo isoladamente é essencial. Basicamente, os microsserviços são apenas outra forma de decomposição modular.
Conceitos essenciais para uma boa fronteira
Três conceitos essenciais que precisam ser analisados quando se trata de definir uma boa fronteira de um microsserviço:
- ocultação de informações: a ideia é ocultar o máximo possível de detalhes, expondo somente o necessário.
- coesão: "códigos que mudam juntos devem permanecer juntos", queremos alta coesão, ou seja, fazer bem feita uma coisa, somente uma coisa. Comportamentos relacionados devem estar juntos para que possamos fazer alterações no menor número possível de lugares. Já comportamentos não relacionados devem estar em outro lugar. Fazer alterações em vários lugares e ter que implantar vários serviços é arriscado.
- acoplamento: queremos baixo acoplamento para que uma mudança em um serviço não exija que outro serviço seja alterado. Um serviço deve saber o mínimo possível de outro serviço.
Assim, queremos abaixo acoplamento (baixa dependência) e alta coesão (domine um contexto de negócio), pois os dois conceitos estão estritamente relacionados.
Uma boa fronteira de microsserviço deve ser algo estável e confiável pois um contrato exposto por um microsserviço que altere constantemente, de modo a se tornar incompatível com versões anteriores, fará com que consumidores upstream também tenham que mudar constantemente, e é exatamente isso que devemos evitar.
Claro que acoplamento não é algo totalmente ruim e haverá situações em que será necessário e facilitará a construção do serviço, por exemplo, acoplamento com um framework. O que queremos é reduzir o volume de acoplamento que teremos.
Os tipos de acoplamento são:
- acoplamento de domínio: ocorre quanto um microsserviço interage com outro microsserviço porque precisa utilizar uma funcionalidade que o outro oferece. Por exemplo, Pedido chama o serviço de Estoque e depois chama o serviço de Pagamento. É considerado um acoplamento abaixo.
- acoplamento de passagem: ocorre quando um microsserviço passa dados para outro microsserviço somente porque esses dados são necessários para um terceiro microsserviço. Mudanças devem ser feitas no menor número possível de serviços.
- acoplamento de dados em comum: ocorre quando dois ou mais microsserviços usam o mesmo conjunto de dados, ou seja, estão usando, por exemplo, o mesmo banco de dados, o mesmo sistema de arquivo compartilhado. O problema é que qualquer mudança na estrutura de dados em comum, impactará vários outros microsserviços ao mesmo tempo.
- acoplamento de conteúdo: ocorre quando um serviço upstream acessa um dado interno de um serviço downstream e modifica seu estado interno. Por exemplo, um serviço externo acessa o banco de dados de outro serviço e o altera. Por isso as fronteiras entre serviços devem ser respeitadas.
Ao considerar as fronteiras dos microsserviços, pensemos em contextos maiores, mais amplos, e quando necessário, divida em contextos menores. Isso ajuda a não exposição dos detalhes ao mundo externo.
Design orientado a domínio
O principal método para identificar fronteiras de microsserviços é o próprio domínio. Alguns conceitos básicos são:
- linguagem ubíqua: termos de negócio usados pelos usuários deve refletir no código.
- agregado: duas ou mais entidades sendo tratadas como uma só, por exemplo, Pedido e Itens do Pedido. Itens do Pedido só faz sentido quando houver um Pedido. Neste caso, um agregado deve ser gerenciado por um único microsserviço, ou seja, não queremos que o mesmo agregado seja gerenciado por mais de um microsserviço. Podemos facilmente ver esse relacionamento em chaves estrangeiras em banco de dados. Agora, caso esse relacionamento ultrapasse a fronteira do microsserviço, uma abordagem interessante seria registrar uma URI do serviço que contém a informação, já que assim teremos o relacionamento entre os serviços mais explícito. Armazenar somente o ID faz com que o relacionamento com o cliente remoto fique totalmente implícito. A SoundCloud adotou um conceito chamado
pURI
. - contexto delimitado: setores diferentes com contextos diferentes compartilham entre sí somente os dados necessários.
DDD no caso dos microsserviços
O que faz o DDD ser tão eficaz está relacionado à ocultar as informações e a complexidade interna de modo que mudanças não causem impactos em outras partes do sistema. Além disso, a definição de uma linguagem comum e ubíqua ajuda na definição de endpoints para os microsserviços. Com esse vocabulário compartilhado, itens, API's e eventos do sistema serão de fácil entendimento tanto pelo negócio, quanto pela área técnica, aumentando a expertise sobre o domínio, além de aprimorar a comunicação entre as áreas.
Isso deixa claro do porque, em muitos casos, não se deve desenvolver o código em inglês quando o produto e o négocio que se está atuanto está no contexto em português.
Alternativas na definição de fronteiras
Outros fatores que podem ser considerados ao identificar fronteiras são:
- volatilidade: partes do sistema que são alteradas com mais frequência poderiam ser extraídas em seu próprio serviço.
- dados: a natureza dos dados pode direcionar a decomposição, por exemplo, um cenário onde uma empresa queira separar a parte do sistema que lida com dados de cartão de crédito por a fim de facilitar uma auditoria, já que somente parte de um subconjunto do sistema seria auditado.
- tecnologia: a necessidade de fazer uso de diferentes tecnologias, por exemplo, escrever uma funcionalidade de Go ou Rust por questões de performance adicional.
- estrutura organizacional: considerando a interação entre a estrutura organizacional e a arquitetura de sistema.
Assim, não existe uma forma certa de determinar as fronteiras dos microsserviços. Ótimos balizadores são ocultação de informação, baixo acoplamento e alta coesão. Isso já evita muitos problemas que poderiam vir a existir. Outro ponto extremamente importante é essa interação e definição da linguagem ubíqua entre área técnica e área de negócio, já que facilitará muito a comunicação utilizando um vocabulário comum a todos.