Design patterns no desenvolvimento de software: heróis ou vilões?
26 de fevereiro de 2025
7 min de leitura
Ferramenta reduz a complexidade e possibilita a adaptabilidade do código, mas seus impactos devem ser analisados antes da implementação

Há muito se fala sobre o uso dos design patterns no desenvolvimento de software e seus benefícios. Porém, será mesmo que a simples utilização desses padrões garante a solução dos problemas que eles se propõem a resolver?
Os designs patterns (ou padrões de projeto) são soluções padronizadas para problemas recorrentes em projetos de software, oferecendo modelos para a resolução dos problemas, o que torna o código modular e legível.
A expectativa é que esses padrões sejam utilizados para facilitar a manutenção e otimizar a eficiência do software, melhorar a qualidade do código e facilitar a comunicação entre os integrantes da equipe de desenvolvimento. Além disso, como a ferramenta reduz a complexidade e proporciona o reuso e a adaptabilidade do código, ela também possibilita ganhos de produtividade para a equipe.
O histórico dos padrões de projeto de software não é recente. A ideia surgiu na arquitetura antes de ser aplicada ao desenvolvimento de software. Em 1978, o arquiteto Christopher Alexander catalogou, juntamente com Sara Ishikawa e Murray Silverstein, 253 problemas comuns de arquitetura e suas soluções no livro “A Pattern Language: Towns, Buildings, Construction”.
Alexander definiu que um padrão deveria ter as seguintes características: encapsulamento, generalidade, equilíbrio, abstração, abertura e combinatoriedade. Essas características acabaram influenciando o desenvolvimento dos padrões dos projetos de software. Mais tarde, em 1987, Kent Beck e Ward Cunningham apresentaram os primeiros padrões na área de ciência da computação, para linguagens orientadas a objetos.
Porém, somente em 1994, por influência do trabalho de Alexander, ocorreu a popularização dos design patterns no desenvolvimento de software. O lançamento do livro “Design Patterns: Elements of Reusable Object-Oriented Software”, da “Gang of Four” (GoF) — Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides —, catalogando 23 padrões de design, formalizou o uso da ferramenta na área.
Ao utilizar design patterns, é fundamental entender cada categoria para escolher o padrão mais adequado para o problema a ser resolvido. Por isso, esses padrões foram divididos em três categorias:
- Padrões criacionais: permitem criar objetos sem “amarrar” o código a classes específicas, que exigem o controle do processo de criação. É como fazer um pedido de um sanduíche no Subway: você pode escolher o pão, o recheio, o queijo e a salada, mas permite que o atendente monte seu lanche do jeito dele. Isso garante flexibilidade (você pode escolher diferentes tipos de queijo e molhos), reutilização (os mesmos ingredientes podem ser utilizados para produzir lanches diferentes) e independência (novos ingredientes podem ser adicionados, sem que você precise mudar a forma de realizar seu pedido). Alguns exemplos de padrões criacionais são Builder (classe que cria objetos para representar um relatório com diferentes tipos de filtros, colunas e opções de formatação), Factory Method (uma aplicação pode usar este padrão para carregar plugins ou extensões, onde cada plugin é instanciado por uma factory específica) e Singleton (pode ser usado para a criação de um objeto que armazena as configurações da aplicação, como informações de conexão com o banco de dados ou preferências do usuário);
- Padrões estruturais: focam na construção de sistemas complexos a partir de partes menores (objetos e classes), que podem se encaixar de maneiras diferentes através de uma mesma interface, tornando-se muito adequados quando é necessário garantir alta flexibilidade entre as partes. Funciona como peças de Lego: embora existam peças de diferentes tamanhos, cores e propósitos, o “padrão de encaixe” é sempre o mesmo, permitindo que muitas coisas diferentes sejam construídas com as mesmas peças. Exemplos: Adapter (quando um sistema que usa uma biblioteca de processamento de pagamentos com uma interface específica precisa se comunicar com outra biblioteca de pagamentos com uma interface diferente) e o padrão Facade (por exemplo, durante o cadastro de um usuário no sistema, a interface de cadastro interage com uma classe, que coordena ações necessárias nos subsistemas de validação, como persistência no banco de dados e envio de e-mail de confirmação);
- Padrões comportamentais: tratam da forma como os objetos de um sistema trabalham juntos ao realizar uma tarefa. Esse padrão é útil quando é necessário ter flexibilidade de comunicação e separação de responsabilidades dentro do sistema. Pense em uma orquestra: cada músico (objeto) toca seu instrumento seguindo a sua própria partitura (seu código) e é responsável por produzir sons diferentes; seu comportamento é determinado pelos comandos do maestro (aumentar volume, mudar o ritmo). Um exemplo muito comum é o padrão Observer (uma plataforma de notícias pode usar esse padrão para notificar assinantes quando uma nova notícia é publicada); outro exemplo é o padrão Command (em aplicações com interfaces gráficas, é usado para representar as ações que podem ser executadas pelos usuários através de menus e botões; cada item de menu ou botão, como “Salvar”, “Abrir”, “Copiar” e “Colar”, pode ser associado a um objeto Command específico, que encapsula a lógica necessária para executar a ação).
Alguns estudos mostraram que projetos com equipes de desenvolvimento maiores tendem a utilizar padrões de projeto com mais frequência. Isso demonstra que os padrões são utilizados para melhorar a documentação e a comunicação entre os membros da equipe. Além disso, desenvolvedores com mais experiência em programação e design são mais propensos a utilizar padrões de projeto.
Al-Obeidallah (2021) analisou o impacto do padrão de projeto Adapter na manutenibilidade de software — atributo de qualidade que indica quão fácil de entender e modificar é o software. Os autores criaram versões de quatro sistemas de software sem o padrão Adapter, utilizando técnicas de refatoração, e compararam métricas de software entre as versões com e sem o padrão. A análise dessas métricas, correlacionadas com a manutenibilidade em estudos anteriores, concluiu que o padrão Adapter impacta positivamente a manutenibilidade, reduzindo indicadores como o número de métodos e linhas de código e melhorando a coesão.
Qasim (2021) investigou o impacto do uso de diferentes padrões de projeto no consumo de energia de aplicativos Android. Os autores implementaram cinco padrões (Singleton, Facade, Observer, Template e Abstract Factory) em dois aplicativos open source, medindo o consumo de energia antes e depois da implementação. Os resultados mostraram que padrões como Observer e Abstract Factory reduziram significativamente o consumo de energia, enquanto o Singleton, em contrapartida, causou um aumento.
Over-engineering
Entretanto, a simples utilização de um design pattern não garante as melhorias sugeridas. Em geral, as pesquisas sobre o impacto de design patterns na qualidade do software apresentam resultados mistos e contraditórios, sugerindo que a relação entre design patterns e qualidade do software é complexa e influenciada por vários fatores. Na verdade, existem estudos apontando que alguns padrões podem ter um impacto negativo na qualidade do software.
Paralelamente, alguns desenvolvedores, especialmente os menos experientes, podem tentar aplicar design patterns em situações em que soluções mais simples seriam suficientes, um problema conhecido como over-engineering.
Também é possível ocorrer um impacto negativo na produtividade caso algum padrão seja mal utilizado, adicionando complexidade excessiva e dificultando a compreensão, o que pode tornar as modificações nos códigos mais difíceis. A implementação de padrões “direto ao ponto”, ou seja, sem adaptá-los corretamente ao contexto da aplicação, pode gerar soluções ineficientes.
Há uma carência de estudos empíricos que avaliem o impacto dos padrões de projeto na qualidade do software, e muitos estudos se baseiam em questionários. Dessa forma, é difícil analisar e adotar um determinado padrão de projeto baseando-se em pesquisas e ferramentas.
Como escolher
Afinal, como escolher o design pattern mais adequado? Essa escolha deve ser feita levando em consideração diversos fatores. Em primeiro lugar, é necessário identificar exatamente qual é o problema que se pretende resolver por meio de um padrão. Os design patterns são soluções para problemas recorrentes, portanto, devemos verificar se a parte do software a ser padronizada pode ser identificada como um problema recorrente.
Somente após esse passo deve-se analisar a intenção de cada padrão, isto é, o tipo particular de problema que cada padrão pode resolver. É preciso também ponderar sobre as consequências e trade-offs que o design pattern escolhido vai trazer para o desenvolvimento e a equipe. O padrão selecionado deve facilitar a comunicação entre os membros da equipe, e não dificultar. Por isso, é importante considerar também a familiaridade que a equipe possui com os padrões.
Como os design patterns são soluções prontas, pode ser que seja necessária uma adaptação ao contexto do problema, a fim de obter a melhor relação entre o custo de implementação e os benefícios que a solução trará para o projeto. Afinal, os padrões de design foram pensados para melhorar a qualidade do código, caso contrário, é melhor definir a própria implementação, de maneira simplificada, buscando garantir os mesmos parâmetros de qualidade.
A fim de avaliar o impacto e a melhoria de qualidade do software, algumas métricas podem ser calculadas antes e depois de uma refatoração para uso de um determinado design pattern. Alguns indicadores, como o Índice de Manutenibilidade, o Acoplamento de Classes e Coesão e até mesmo o Tempo de Execução, podem ser relevantes para avaliar os benefícios da adoção do padrão de projeto em questão. No entanto, pode ser muito difícil obter essas métricas para realizar essa avaliação mais criteriosa.
Os design patterns não são a “bala de prata” para todos os tipos de problemas. É importante analisar muito bem a situação antes de utilizá-los em algum projeto de software, para verificar se trarão vantagens significativas. Em primeiro lugar, deve-se avaliar a real necessidade de adotá-los no projeto.
Muitas vezes, um bom ponto de equilíbrio pode ser desenvolver um código mais simples, sem seguir um determinado padrão, e depois refatorá-lo para utilizar algum design pattern, evitando alguns problemas de implementação. Utilizando métricas e a percepção geral do time, será possível avaliar se a utilização do padrão após a refatoração melhorou a qualidade do código e trouxe benefícios para todos.
Independentemente do exposto, é importante que todo desenvolvedor aprenda sobre design patterns, para conseguir identificá-los e contribuir mais facilmente em diferentes projetos open source, por exemplo. Aprender mais sobre esses padrões expande os horizontes e permite que o desenvolvedor encontre novas formas de resolver problemas e propor melhorias em sistemas existentes, criando softwares com muito mais qualidade.
Para ter acesso às referências desse texto clique aqui. |
Este conteúdo foi produzido por:
Lucas Schiolin Silveira
Formado em Ciências da Computação pela Unesp de Rio Claro, possui MBA em Data Science e Analytics pela USP/ESALQ. Trabalha como desenvolvedor e líder técnico na Skylar. É estudante de IA, Machine Learning e Data Science.