Pular para o conteúdo

Arquitetura Limpa

Arquitetura de software é o conjunto de decisões estruturais que molda como um sistema é organizado, evoluído e operado. Ela não é um diagrama bonito separado do código: aparece na forma como as dependências são direcionadas, como as responsabilidades são distribuídas e como o sistema reage à mudança.

Quando falamos em Arquitetura Limpa, falamos de uma proposta específica para organizar software de modo que regras de negócio permaneçam menos acopladas a frameworks, interfaces e infraestrutura. Mas, para entender por que essa proposta existe, vale primeiro ampliar o conceito de arquitetura.

Arquitetura é uma resposta à complexidade. Em software, ela ajuda a responder perguntas como:

  • do que o sistema é composto?
  • como as partes se relacionam?
  • onde estão as decisões mais sensíveis?
  • que tipo de mudança será cara ou barata?

Sem arquitetura, o sistema ainda pode funcionar. O problema é que ele passa a evoluir por acúmulo de decisões locais, sem uma direção clara para absorver mudança.

Uma boa arquitetura não existe para impressionar; existe para sustentar entendimento, evolução e operação.

Ela ajuda a:

  • tornar o sistema compreensível para quem chega depois;
  • limitar o impacto de mudanças;
  • tornar a implantação e a operação mais previsíveis;
  • explicitar fronteiras entre domínio e detalhe técnico.

Arquitetura, nesse sentido, é menos sobre tecnologia da moda e mais sobre custo futuro de mudança.

É útil separar dois aspectos complementares.

Trata de como o sistema é estruturado internamente: módulos, camadas, pacotes, portas, adaptadores, entidades, casos de uso e relações de dependência.

Nesse campo entram abordagens como:

  • DDD;
  • Screaming Architecture;
  • Hexagonal Architecture;
  • Onion Architecture;
  • Clean Architecture;
  • MVC.

Estratégias como Event Sourcing também influenciam essa organização, embora não sejam exatamente um estilo completo de arquitetura de aplicação por si só.

Trata de como o sistema é executado e implantado: monólito, microserviços, serverless, modularização de deploy, distribuição por ambientes e topologia operacional.

Essa distinção é importante porque muita discussão arquitetural mistura estrutura de código com forma de implantação. Um sistema pode, por exemplo, usar Clean Architecture logicamente e ainda ser implantado como monólito modular.

DDD enfatiza modelagem do domínio e linguagem ubíqua. Seu foco principal é alinhar software e negócio, especialmente em contextos complexos. Ele não substitui uma arquitetura de camadas, mas influencia fortemente como o código é organizado.

A ideia central é que a estrutura do projeto “grite” a intenção do negócio. Em vez de pastas chamadas services e utils, a organização deve evidenciar conceitos como faturamento, estoque ou matriculas.

Event Sourcing é uma estratégia de modelagem e persistência em que o estado pode ser reconstruído a partir de eventos registrados. Isso não é o mesmo que arquitetura orientada a eventos. Um sistema pode usar eventos para integração sem usar Event Sourcing, e pode usar Event Sourcing sem ser totalmente event-driven.

Também chamada de Ports and Adapters, propõe isolar o núcleo da aplicação dos detalhes externos. O domínio conversa com portas abstratas; as integrações concretas aparecem como adaptadores.

Organiza o sistema em anéis concêntricos, com o domínio no centro e detalhes externos nas bordas. A principal mensagem é de direção de dependências: o centro não deve depender da periferia.

MVC separa responsabilidades de interface, entrada e lógica associada. É especialmente conhecido em aplicações web e GUI, mas não resolve sozinho o desenho completo do domínio da aplicação.

Clean Architecture, popularizada por Robert C. Martin, organiza o sistema em camadas concêntricas com foco em independência de detalhes externos. A ideia principal é simples: regras de negócio mais centrais não devem depender de frameworks, banco de dados, interface gráfica ou mecanismos de entrega.

Em termos práticos, isso significa proteger o centro do sistema.

As camadas mais internas tendem a conter:

  • entidades e regras de negócio essenciais;
  • casos de uso ou regras de aplicação;
  • contratos que definem colaboração com o exterior.

Nas camadas mais externas ficam:

  • interface de usuário;
  • banco de dados;
  • frameworks;
  • serviços externos;
  • detalhes de infraestrutura.

O princípio mais importante da Clean Architecture é a direção das dependências. Dependências de código-fonte devem apontar para dentro, em direção às políticas mais estáveis do sistema.

Isso traz consequências importantes:

  • o domínio não conhece ORM, HTTP ou UI;
  • casos de uso não precisam conhecer framework web;
  • infraestrutura implementa contratos definidos mais perto do centro.

Essa separação reduz o risco de o sistema inteiro ficar refém de tecnologia periférica.

Quando bem aplicada, a Clean Architecture pode melhorar:

  • testabilidade de regras centrais;
  • independência de framework;
  • clareza das fronteiras do sistema;
  • facilidade de trocar detalhes de infraestrutura;
  • previsibilidade da evolução arquitetural.

Ela é particularmente útil quando o domínio possui regra de negócio relevante e o projeto precisa sobreviver a mudança tecnológica ao longo do tempo.

Nem todo sistema precisa do mesmo grau de separação. Aplicar Clean Architecture sem necessidade pode introduzir:

  • abstrações prematuras;
  • excesso de interfaces e mapeamentos;
  • aumento de complexidade para operações simples;
  • sensação de burocracia arquitetural.

Arquitetura boa depende de proporcionalidade. Em projetos pequenos, um desenho mais simples pode ser a escolha correta. O objetivo não é seguir um diagrama por fé, mas sustentar mudança com custo adequado.

Arquitetura física: monólito, microserviços e serverless

Seção intitulada “Arquitetura física: monólito, microserviços e serverless”

Essas decisões pertencem mais ao campo físico e operacional.

Mantém a aplicação em uma única unidade implantável. Não significa necessariamente código bagunçado. Um monólito bem modularizado pode ser excelente para muitos contextos.

Distribuem responsabilidades em serviços independentes. Podem trazer ganhos de autonomia e escalabilidade, mas aumentam o custo operacional, de observabilidade e de consistência distribuída.

É uma alternativa interessante quando o time quer separação arquitetural forte sem assumir cedo demais o custo dos microserviços. Muitas equipes maduras preferem começar aqui.

Move grande parte da infraestrutura operacional para o provedor, mas não elimina preocupação arquitetural. Apenas desloca restrições para outro tipo de ambiente.

A ideia de Monolith First reforça prudência arquitetural. Em muitos casos, começar com um monólito modular é melhor do que distribuir prematuramente um sistema ainda mal entendido.

Essa abordagem favorece:

  • descoberta do domínio antes da distribuição;
  • menor custo operacional inicial;
  • refatoração baseada em pontos reais de tensão;
  • extração posterior de serviços com mais evidência.

Porque os problemas variam. Escopo, equipe, domínio, criticidade, ritmo de entrega, integração externa e restrições operacionais mudam muito de um sistema para outro.

Cada proposta arquitetural enfatiza aspectos diferentes:

  • modelagem do domínio;
  • direção de dependências;
  • organização do código;
  • estratégia de implantação;
  • comunicação entre componentes;
  • experiência de desenvolvimento.

Nenhuma arquitetura é bala de prata. Cada uma resolve melhor certos problemas e pior outros.

Sim. Aliás, isso é muito comum.

Um sistema pode usar:

  • DDD para modelar domínio;
  • Clean Architecture ou Hexagonal para organizar dependências;
  • MVC na interface web;
  • Screaming Architecture na organização de pastas;
  • BCE (Boundary, Control, Entity) como guia de papéis em certos módulos;
  • monólito modular como forma de implantação.

Essas combinações fazem sentido quando há coerência entre as escolhas. Misturar nomes famosos sem uma intenção clara só adiciona ruído.

Ao revisar a arquitetura de um sistema, pergunte:

  • as decisões estruturais reduzem ou ampliam o custo de mudança?
  • o domínio central está protegido de detalhes externos?
  • a equipe consegue explicar claramente as fronteiras do sistema?
  • estamos discutindo arquitetura lógica ou física?
  • a complexidade arquitetural é proporcional ao problema?
  • a tecnologia está servindo ao domínio, ou o domínio está sendo deformado pela tecnologia?