DEV Community

Cover image for Padrões de Arquitetura vs Padrões de Projeto
Programador Filosofo
Programador Filosofo

Posted on

Padrões de Arquitetura vs Padrões de Projeto

Se você já se pegou em discussões do tipo "isso é padrão de projeto ou de arquitetura?" ou ouviu alguém chamar SOLID de padrão de projeto e microserviços de "padrão GoF moderno", saiba que isso é muito mais comum do que parece.

Na prática, a confusão não é só semântica. Quando misturamos os conceitos de padrões de arquitetura, padrões de projeto e princípios de design, fica mais difícil justificar decisões, ensinar o time e até diagnosticar os problemas de um sistema. Alguns autores resumem a diferença de forma bem direta: padrões de arquitetura cuidam da estrutura global do sistema, enquanto padrões de projeto tratam de soluções mais locais, em componentes ou partes específicas do código.

Este texto é um passeio organizado por esse terreno. A ideia é que você termine sabendo responder com segurança três perguntas:

O que é um padrão de arquitetura?
O que é um padrão de projeto?
Onde entram SOLID, GRASP e outras "siglas famosas" nessa história?

Mais do que decorar definições, o objetivo é criar um mapa mental que ajude no dia a dia: nas revisões de código, nas decisões de design, nas conversas com o time e, principalmente, na hora de evitar retrabalho.

Um mapa geral do "mundo dos padrões"

Antes de separar as coisas, vale montar um panorama.

De forma simplificada, o ecossistema de conceitos costuma ser organizado em camadas. Em um nível mais alto, estão os estilos e padrões de arquitetura, que falam de como o sistema se estrutura como um todo. Em um nível mais próximo do código, aparecem os padrões de projeto, lidando com a forma como classes e objetos colaboram para resolver problemas recorrentes. Atravessando tudo isso, aparecem princípios como SOLID e as orientações do GRASP, que funcionam como critérios de qualidade para avaliar se aquele design está saudável.

Você pode imaginar assim:

estilos e padrões de arquitetura respondem a perguntas do tipo "como vamos organizar o sistema inteiro?";
padrões de projeto respondem a perguntas como "qual estrutura de classes faz mais sentido para resolver esse problema específico?";
princípios de design ajudam a avaliar se a resposta que você encontrou é flexível, compreensível e fácil de evoluir.

Com esse mapa na cabeça, fica bem mais fácil entender o papel de cada peça.

Padrões de arquitetura: o esqueleto do sistema

Padrões de arquitetura são soluções consolidadas para problemas recorrentes de organização de sistemas. Eles definem como o software é dividido em partes maiores, quais responsabilidades cada parte assume e como essas partes se comunicam.

Quando falamos em arquitetura em camadas, MVC, microservices ou arquiteturas orientadas a eventos, estamos discutindo esse tipo de padrão. Não é só um detalhe de código; é a forma como o sistema se apresenta "de longe".

Um exemplo bem conhecido é a arquitetura em camadas, também chamada de layered ou N-tier. Nela, o sistema costuma ser organizado em blocos como interface de usuário ou APIs, camada de aplicação ou serviços, camada de domínio com as regras de negócio e camada de infraestrutura com banco de dados e integrações. Essa forma de organização aparece em livros, tutoriais e frameworks exatamente porque facilita a separação de responsabilidades, melhora a testabilidade e deixa mais claro "onde cada coisa deveria estar".

Outro exemplo clássico é o MVC, que separa Model, View e Controller e é usado desde frameworks web até aplicações desktop e mobile. O foco é manter a lógica de apresentação e a lógica de domínio em lugares distintos, favorecendo reuso e manutenibilidade. Em variações modernas, como o MVVM, esse princípio de separar visual, comportamento e dados continua, só muda a forma de organizar os papéis.

Microservices entram no jogo como um padrão de arquitetura mais avançado. Em vez de um único sistema grande, a aplicação é composta de vários serviços pequenos, cada um focado em uma capacidade de negócio e implantado de forma independente. Isso permite escalar partes específicas do sistema, dar mais autonomia para equipes e isolar domínios, mas cobra um preço alto em complexidade operacional, observabilidade, comunicação entre serviços e governança. É por isso que muitos autores insistem que microserviços não são uma "evolução natural" do monolito, e sim uma escolha que só vale a pena em determinados contextos. (GeeksforGeeks)

Por fim, vale mencionar o DDD (Domain Driven Design). Ele combina conceitos de modelagem de domínio com padrões arquiteturais e padrões táticos. Bounded contexts, entidades, value objects, agregados e repositórios são exemplos de elementos que aparecem com frequência em abordagens baseadas em DDD. Em muitos projetos, DDD vira quase um "guarda-chuva de arquitetura" que orienta como o sistema será dividido, nomeado e organizado em torno do negócio.

Em resumo: padrões de arquitetura lidam com decisões que mudam o desenho do sistema como um todo. Eles não são neutros; escolher um ou outro impacta performance, segurança, organização do time e até a forma como as regras de negócio são implementadas.

Padrões de projeto: soluções recorrentes dentro do código

Se a arquitetura é o esqueleto, os padrões de projeto são os movimentos e articulações que fazem o sistema funcionar de forma fluida.

Padrões de projeto surgiram como uma forma de documentar soluções recorrentes em design orientado a objetos. A referência mais famosa é o livro "Design Patterns: Elements of Reusable Object-Oriented Software", dos autores conhecidos como Gang of Four, que catalogou 23 padrões. Esses padrões foram organizados em três grupos principais: padrões criacionais, estruturais e comportamentais.

A grande ideia aqui não é "encher o sistema de padrões", e sim ter um vocabulário e um conjunto de soluções prontas para problemas muito comuns. Quando alguém diz que resolveu um problema com Strategy, por exemplo, está dizendo que encapsulou algoritmos em objetos intercambiáveis, permitindo variar o comportamento sem encher o código de condicionais. Quando alguém fala que criou uma Facade, está dizendo que colocou na frente de um subsistema complexo uma interface mais simples para quem consome.

O ponto interessante é o escopo. Autores que comparam padrões de arquitetura e de projeto são bastante claros em dizer que design patterns atuam em partes específicas do código, em componentes, enquanto architectural patterns tratam de decisões que impactam o sistema inteiro ou grandes subsistemas.

Imagine que você tem uma arquitetura em camadas definida. Essa arquitetura não diz exatamente como as classes dentro da camada de domínio vão se relacionar. É aí que padrões como Strategy, State, Observer, Factory Method, Adapter, entre outros, entram em cena para resolver problemas pontuais: variação de comportamento, acoplamento com bibliotecas externas, criação de objetos complexos, observação de eventos e assim por diante.

Padrões de projeto são, portanto, ferramentas para refinar uma arquitetura já escolhida. Eles funcionam melhor quando são usados com critério, em resposta a problemas reais, e não como um carimbo a ser aplicado a qualquer custo.

SOLID, GRASP e outros princípios: o "código de conduta" do design

Aqui aparece uma das confusões mais frequentes: tratar SOLID e GRASP como se fossem padrões de projeto.

SOLID é um acrônimo para cinco princípios de design orientado a objetos, propostos por Robert C. Martin, com a intenção de tornar o código mais compreensível, flexível e fácil de manter. Esses princípios estão relacionados a responsabilidade única, abertura para extensão, substituição correta de tipos, segregação de interfaces e inversão de dependência.

GRASP, por sua vez, é um conjunto de nove princípios de atribuição de responsabilidades em objetos, descritos por Craig Larman. Entre eles estão ideias como Information Expert, Low Coupling, High Cohesion, Controller, Creator, Polymorphism, Protected Variations e Pure Fabrication. A intenção é orientar como distribuir responsabilidades entre classes de forma que o projeto permaneça coeso, pouco acoplado e resistente a mudanças.

Repare que, no caso de SOLID e GRASP, não se trata de "estruturas prontas" como Strategy ou MVC, e sim de critérios para avaliar se a solução que você escolheu é boa. Em outras palavras, princípios como esses funcionam como um código de conduta do design. Eles ajudam a decidir se faz sentido colocar determinada lógica em uma classe, se a interface não está grande demais, se o acoplamento entre módulos não ficou excessivo.

Design patterns e princípios se relacionam, mas não competem. Um padrão como Strategy, por exemplo, ajuda a cumprir o princípio de aberto para extensão e fechado para modificação, que faz parte do SOLID. Da mesma forma, aplicar Observer com cuidado pode reforçar baixa acoplamento e alta coesão, conceitos centrais em GRASP.

Por isso é impreciso dizer que SOLID é "padrão de projeto". É mais correto dizer que você usou Strategy, por exemplo, de um jeito que respeita os princípios SOLID e GRASP.

Como tudo se encaixa em um projeto real

Um jeito prático de fixar essa diferença é imaginar uma situação concreta.

Suponha que você esteja criando um sistema de gestão de contratos. A primeira leva de decisões envolve arquitetura. Você decide que o sistema será inicialmente um monolito modular, organizado em camadas claras: uma API para entrada de requisições, uma camada de aplicação para orquestrar casos de uso, uma camada de domínio modelando contratos, apólices e cálculos, e uma camada de infraestrutura responsável por banco de dados e integrações externas. Nessa etapa, você está escolhendo padrões de arquitetura, talvez combinando camadas com alguns elementos de DDD.

Depois que o esqueleto está montado, aparecem problemas mais pontuais. Por exemplo, o cálculo do valor do contrato pode variar de acordo com o tipo de cliente, o produto e a vigência. Você quer evitar encher o código com condicionais. Aqui, um padrão de projeto como Strategy pode encaixar bem, encapsulando algoritmos de cálculo em classes diferentes e permitindo escolher a estratégia correta em tempo de execução. Em outro ponto do sistema, você quer esconder a complexidade de várias chamadas externas por trás de uma interface mais simples. Isso cheira a uma Facade.

Enquanto escolhe esses padrões, você avalia se o design está saudável usando princípios como SOLID e GRASP. Se uma classe de serviço começa a acumular casos de uso demais, talvez esteja violando responsabilidade única. Se uma camada depende diretamente de detalhes de infraestrutura, talvez você precise aplicar inversão de dependência. Se um módulo conhece detalhes internos de outro, pode estar faltando baixo acoplamento.

Perceba a sequência: primeiro a arquitetura dá o desenho macro. Dentro desse desenho, os padrões de projeto refinam as soluções locais. Em todas essas decisões, princípios como SOLID e GRASP funcionam como régua de qualidade.

Armadilhas comuns quando se fala de padrões

Conhecer os conceitos é apenas metade do caminho. A outra metade é evitar alguns erros bastante comuns.

Um deles é tratar padrão como objetivo em si. Às vezes, alguém decide que "precisa usar mais padrões" e começa a encaixar Strategy, Factory, Builder e por aí vai em lugares onde uma função simples resolveria o problema. O resultado é um código cheio de indireções desnecessárias, difícil de entender e de manter. Autores que documentam design patterns reforçam que eles são respostas a problemas recorrentes, não uma lista de coisas que você "tem que usar" para parecer profissional.

Outra armadilha é confundir framework com padrão. Usar um framework MVC não garante que a sua arquitetura esteja bem desenhada. É perfeitamente possível ter um "MVC" onde a View conhece detalhes de banco de dados ou onde o Controller faz todas as regras de negócio. O mesmo vale para microserviços: adotar um framework que facilita criar serviços pequenos não resolve, por si, problemas de definição de limites de contexto, orquestração e dados compartilhados.

Existe ainda o risco de tratar SOLID como religião. Quando cada princípio é aplicado de forma dogmática, surgem classes minúsculas demais, excesso de interfaces sem necessidade, camadas a mais só para cumprir "inversão de dependência" e um número de arquivos desproporcional ao valor entregue. Bons materiais sobre SOLID insistem em algo importante: os princípios são guias para evitar mau design, não regras inflexíveis.

O mesmo vale para GRASP. A busca por baixa acoplamento e alta coesão não significa sair quebrando o sistema em dezenas de serviços ou classes por reflexo. A ideia é encontrar pontos de variação e de responsabilidade que façam sentido, mantendo o desenho compreensível para humanos reais que vão ler e modificar aquele código.

No fundo, o problema central é o mesmo: esquecer que padrões e princípios são ferramentas a serviço de objetivos concretos, como clareza, robustez e facilidade de mudança.

Conclusão e próximos passos

A diferença entre padrões de arquitetura e padrões de projeto fica bem mais nítida quando você a enxerga pelo escopo da decisão.

Arquitetura lida com o desenho global do sistema. É na arquitetura que você decide se terá um monolito modular ou microserviços, se vai usar camadas tradicionais, hexagonal, orientada a eventos ou outra variação, e como as fronteiras entre contextos de negócio serão estabelecidas. Essas decisões impactam o trabalho do time inteiro e costumam ser difíceis de mudar depois de certo ponto.

Padrões de projeto atuam dentro desse desenho, cuidando de problemas recorrentes na colaboração entre classes e objetos: variação de comportamento, encapsulamento de dependências externas, criação de objetos complexos, notificação de múltiplos interessados e assim por diante. O catálogo de 23 padrões documentado pelo Gang of Four continua sendo uma base sólida e, até hoje, é referência em praticamente todos os cursos e materiais sobre design patterns.

Princípios como SOLID e GRASP, por fim, não são padrões no sentido de "estruturas prontas", e sim lentes pelas quais você avalia se o design está saudável. Eles ajudam a evitar classes gigantes, acoplamentos desnecessários, interfaces inchadas e decisões que dificultam a evolução. Funcionam bem justamente porque não estão presos a uma linguagem ou framework específico.

Se for para resumir em uma única ideia: quanto mais você conhece esses padrões e princípios, menos energia gasta inventando soluções para problemas que já foram estudados, documentados e refinados por outros desenvolvedores antes de você. Sobra mais espaço mental para o que realmente importa, que é modelar bem o domínio do seu sistema e entregar valor de negócio com qualidade técnica.

Top comments (0)