"O monólito não é o inimigo" e "os microsserviços não devem ser a escolha padrão". Essas foram as duas mensagens principais elencadas por Sam Newman durante sua apresentação sobre os padrões de decomposição de um monólito (em inglês) no QCon Londres 2020. Destacando alguns dos tópicos do seu livro recém publicado, Monolith to Microservices, Newman aconselhou as pessoas a se concentrarem no resultado e não na tecnologia, além de lembrá-las que o objetivo sempre deve ser a busca por deploys independentes.
Sam Newman durante apresentação no QCon Londres 2020
Nas palavras de Newman, para atingir esse objetivo é preciso adotar uma abordagem incremental à decomposição e não começar pensando que o monólito é o inimigo. É preciso também perguntar a si mesmo:
"Que problemas estamos tentando resolver? E o que nossa arquitetura atual não permite?"
Uma de suas sugestões é a de que técnicas do Design Orientado a Domínio (DDD), como um exercício de modelagem na arquitetura monolítica existente, podem ajudar a encontrar os limites do serviço e quebrar a caixa de pandora.
Um outro ponto apresentado foi o de que as equipes precisam definir padrões para fazer alterações incrementais necessárias. Duas das sugestões abordadas por Newman em detalhes foram o "strangler fig pattern" (padrão de figueiras estranguladoras, no português) e a "branching by abstraction" (algo como uma ramificação por abstração no português). Ele recomendou a leitura do livro Working Effectively With Legacy Code, de Michael Feather, para obter orientações práticas sobre como encontrar abstrações úteis em seu código.
O Strangler Fig Pattern, nome derivado da figueira estranguladora, planta que cresce e eventualmente substitui uma hospedeira, se inicia com a identificação da funcionalidade que será movida para um novo microsserviço. Uma vez identificada a funcionalidade, é possível interceptar chamadas para a funcionalidade antiga e redirecioná-las para o novo serviço. Na melhor das hipóteses, a mudança da funcionalidade pode ser um simples copiar e colar, mas provavelmente envolverá uma reescrita total ou parcial. O uso de um proxy HTTP pode ser interessante para identificar se a adição de uma nova camada, em comparação às chamadas em andamento, será um problema.
A ramificação por abstração, por sua vez, segue o Princípio de Substituição de Liskov (artigo em inglês), o "L" no SOLID, onde criamos uma nova implementação separada que possui exatamente a mesma abstração que a implementação antiga. Em um monólito, isso pode exigir a definição da abstração com uma interface clara e a refatoração, por si só, já irá melhorar a testabilidade, valendo assim o esforço necessário. Como nenhuma funcionalidade será modificada nesse caso, a equipe poderá continuar trabalhando e implantando novos recursos enquanto a nova implementação é desenvolvida. Além disso, como essa nova implementação não estará sendo chamada, poderá ser validada, com testes que comprovem seu funcionamento correto, resultando em um deploy com maior segurança.
Uma vez finalizado o novo código, Sam Newman sugere a utilização de uma feature toggle e de execuções paralelas (as antigas e as novas, funcionando ao mesmo tempo), ao invés de uma substituição direta, fazendo com que seja possível verificar o comportamento da nova implementação. Essa é uma técnica útil para separar o deploy, da disponibilização do novo serviço para o mundo real. A ideia de entrega progressiva vem da ideia oculta de que
"O ato de fazer o deploy de algo na produção não é o mesmo que fazer o deploy de algo para nossos clientes".
Para saber mais sobre a entrega e conceitos como Canárias, testes A/B, deploy azul/verde e lançamento no escuro, Newman recomendou seguir James Governor e o blog RedMonk.
Newman disse que o termo "monólito" acabou se tornando um substituto para o nome "legado" e acredita que isso é bem inapropriado. Um monólito refere-se apenas à unidade de implantação. Ele ressaltou que o "monólito modular" está usando ideias da década de 1970, como programação estruturada. Embora seja necessária uma boa disciplina para respeitar os limites dos módulos e evitar um crescimento irregular, cheio de falhas e repetições, a maioria das empresas resolveria melhor seus problemas com a opção altamente subestimada de um monólito modular ao invés da utilização de microsserviços.
Os limites do módulo definidos "podem facilitar o trabalho cooperativo de diferentes equipes, abordando e endereçando diferentes aspectos do sistema".
"Você não apreciará completamente o puro terror, horror, dor, sofrimento, angústia e despesa de executar os microservices até que estejam realmente em produção".
A opinião de Newman é que "os microservices não são uma boa opção para a maioria das startups". Por isso, ele propõe um monólito modular com vários bancos de dados. Embora possa parecer estranho, isso pode levar a uma eventual possibilidade de dividir o monólito em microsserviços, onde a tarefa mais difícil será separar a camada de dados.
Arquitetura monolítica modular com vários bancos de dados
Newman alertou contra "o pior de todos os monólitos: o monólito distribuído". Um monólito distribuído possui muitos serviços, mas tudo precisa ser implantado ao mesmo tempo e exige muita coordenação entre as equipes para que tudo seja feito no momento e no lugar certo. Um indicador de que temos um monólito distribuído é se alguém da nossa empresa tem um cargo de período integral como "gerente de coordenação dos releases". Um exemplo utilizado para ilustrar esse cenário foi como a BBC re-arquitetou um monólito distribuído. Se estiver interessado, assista à apresentação do QCon feita pela Blanca Garcia Gil.
Um sistema difícil de implantar nem sempre é devido aos limites de serviços mal definidos. Isso pode ser resultado do processo de desenvolvimento de software. Newman mostrou um exemplo com um trem de releases, onde, "regularmente, talvez a cada quatro semanas, todo o software sai pela porta. Se o software não estiver pronto, entrará no próximo trem". Isso normalmente é um trampolim para a entrega contínua, mas muitas vezes se torna o resultado final para entregar o software e levá-lo a um monólito distribuído. Infelizmente, o trem de releases agora está codificado no SAFe (Scaled Agile Framework), para que seja incorporado à prática corporativa.
Newman encerrou sua apresentação, elencando as dificuldades associadas aos problemas de acesso aos dados. Compartilhar bancos de dados causa problemas de acoplamento e sempre deve ser evitado. A solução está na ocultação de informações, uma ideia desenvolvida por David Parnas na década de 1970, onde qualquer solicitação de informações precisa passar por uma interface bem definida, ao invés de ter acesso direto ao banco de dados. Newman reconheceu que, mover os dados de um sistema existente é realmente difícil.
"Quando estamos retirando os dados de um sistema existente, especialmente os bancos de dados relacionais, causamos muita dor, sofrimento e angústia".
A principal mensagem de Sam Newman, ao longo de sua apresentação, foi:
"Os microsserviços não devem ser a escolha padrão. É preciso pensar com muito cuidado se essa é uma abordagem adequada para o seu problema"
A apresentação gravada incluindo slides e transcrição, está disponível no InfoQ neste link. Todo os conteúdos estão disponíveis somente em inglês.