Disclaimer
Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de uma live do Dev Eficiente. Se preferir acompanhar por vídeo, é só dar o play.
Introdução
No mundo atual do desenvolvimento de software, as decisões de arquitetura são fundamentais para o sucesso de um projeto. Este post explora as principais reflexões a partir de uma discussão sobre o artigo "Monoliths are not dinosaurs" do CTO da Amazon, Werner Vogels, destacando que não existe uma arquitetura ideal para todos os casos, e que as decisões devem evoluir conforme as necessidades do sistema.
A Arquitetura de Software não é uma Religião
Um dos pontos centrais desta discussão é que a arquitetura de software não deve ser tratada como uma religião. Não existe uma solução única que funcione para todos os casos, e nos apegar cegamente a um único estilo arquitetural pode ser prejudicial ao desenvolvimento. Conforme mencionado no debate, muitas vezes nas empresas temos discussões técnicas onde pessoas defendem suas crenças de maneira mais apaixonada do que baseada em argumentos lógicos.
As decisões de arquitetura devem ser baseadas nas necessidades específicas do projeto, no problema que está sendo resolvido, e devem poder evoluir ao longo do tempo.
Ordem de Magnitude como Gatilho para Reavaliação
Werner Vogels menciona que gosta de revisitar decisões de arquitetura quando algo muda "uma ordem de magnitude". Este é um conceito importante - quando seu sistema passa de 10 para 100 usuários, de 100 para 1.000, ou de 1.000 para 10.000, é um bom momento para reavaliar se a arquitetura atual ainda atende às necessidades.
Esta sistematização ajuda a definir pontos claros de reavaliação. A ordem de magnitude pode se referir a diversos aspectos:
- Número de usuários
- Volume de dados
- Número de funcionários na empresa
- Complexidade do domínio
Quando um desses fatores muda significativamente, é prudente verificar se a arquitetura atual continua sendo adequada.
Monolito vs. Arquitetura Distribuída
Quando falamos de arquitetura monolítica versus distribuída, estamos essencialmente falando de:
- Arquitetura Monolítica: Todo o código roda em um único processo. As funcionalidades estão juntas no mesmo sistema.
- Arquitetura Distribuída: O sistema é dividido em vários processos diferentes que se comunicam entre si, geralmente por APIs.
Coesão como Guia para Distribuição
Um conceito fundamental para decidir quando distribuir um sistema é a coesão. Se um sistema tem alta coesão, significa que suas partes estão fortemente relacionadas e faz sentido mantê-las juntas. Quando elementos começam a ter baixa coesão entre si, pode ser o momento de separar em sistemas diferentes.
No exemplo citado da Amazon Prime Video, uma equipe percebeu que tinha vários microserviços que atuavam sobre o mesmo tipo de problema e eram altamente coesos. A decisão foi transformá-los em um monolito, o que simplificou a manutenção.
Controlando a Complexidade
Quando optamos por uma arquitetura distribuída, um benefício importante é controlar a complexidade. Cada serviço pode crescer de maneira independente, com seu próprio banco de dados e infraestrutura, facilitando:
- Autonomia de deploy
- Testabilidade
- Controle de acoplamento
No entanto, é preciso cuidado para não criar um "monolito distribuído" - quando há acoplamento excessivo entre os serviços distribuídos, anulando muitas das vantagens dessa abordagem.
Desenvolvimento Orientado ao Domínio
Uma forma que eu recomendo de desenvolver serviços é "codá-los de maneira egoísta" - se preocupe com quem vai consumir, mas não no sentido de ficar adaptando tudo para que tipo de cliente diferente.
Isso evita o "acoplamento mental", onde seu conhecimento sobre como a outra ponta vai consumir o serviço influencia o código que você está escrevendo.
E Devemos Começar com qual Abordagem?
Desconfie sempre de quem fala que existe uma resposta certa. Você deve optar pela abordagem que parece razoável dada as variáveis que tem naquele momento.
Na minha última experiência, trabalhei num produto onde eu tinha profundo conhecimento sobre o domínio. Neste contexto, eu preferi já começar por uma abordagem distribuída, com serviços de granularidade um pouco mais grossa.
Já quando eu não possuo tal conhecimento, começar com tudo misturado pode ser mais interessante, pelo menos na minha visão. Eu nem manjo do problema com profundidade suficiente, vou fatiar isso como?
E se você for buscar por referências, vai encontrar também opiniões diferentes. Aqui Martin Fowler explica que a experiência dele, até o momento da escrita do post, era de que começar por monólitos pode ser uma boa. Já aqui, Stefan Tilkon explica que pode ser melhor começar distribuído, para você tentar fugir das facilidades perigosas de ter o código todo juntinho.
Você vai encontrar também uma linha de pensamento falando dos monólitos modulares, que parecem que são o meio termo da coisa. Vai ter gente falando bem, e vai ter gente te alertando que o meio termo pode te levar a fazer tudo que é ruim nos dois lados.
Neste momento da minha heurística padrão é:
- Entendo que conheço muito bem o domínio? Começo distribuindo guiado pela coesão dos elementos necessários para colocar o sistema no ar. Talvez na primeira versão, isso me deixe com um monólito.
- Não tenho confiança no entendimento do domínio? Começo deixando tudo junto, já que não tenho competência naquele momento para julgar a coesão das coisas.
Conclusão
A principal mensagem que podemos extrair dessa discussão é clara: monolitos não são dinossauros. Nem toda arquitetura distribuída é superior, e nem todo monolito é ultrapassado. O que importa é que a arquitetura escolhida seja adequada para o problema específico que está sendo resolvido.
As três ideias principais são:
- Não existe bala de prata em arquitetura de software - defina métricas e reavalie quando certas magnitudes mudarem
- Comece com monolitos para resolver problemas específicos e distribua em serviços quando perceber que está extrapolando os limites
- A coesão deve ser o guia para suas decisões - mantenha junto o que é coeso e separe o que não é
A arquitetura deve evoluir à medida que o entendimento do problema e as necessidades de escala evoluem. O importante é manter a sistematização e a análise constante para tomar decisões fundamentadas.
Referência
O artigo original pode ser lido em https://www.allthingsdistributed.com/2023/05/monoliths-are-not-dinosaurs.html
Conheça a Jornada Dev + Eficiente
A Jornada Dev + Eficiente é um treinamento focado em fazer você crescer na carreira como uma pessoa cada vez mais especializada em Entregar Software que Gera Valor com o Máximo de Qualidade e Fluidez.
A Jornada pavimenta este caminho através de uma abordagem integrada, trabalhando diversos aspectos que influenciam na qualidade da entrega final, tais como: Engenharia de Requisitos, Design de Código, Arquitetura, Testes etc.
É o único local que você vai encontrar que é 100% focado em fazer você crescer como uma pessoa desenvolvedora de software completa.
Para conhecer mais, acesse https://deveficiente.com