Por que “design patterns” é um nome genérico demais
Uma crítica ao termo design pattern e uma proposta para distinguir padrões de ergonomia, arquitetura e implementação de software.
Introdução
Um dos meus hobbies atuais é ler posts antigos, como os do blog AkitaOnRails. Um deles é Design Patterns representam defeitos nas linguagens.
Primeiramente, este é um bom post, muito bem embasado de acordo com o blog post Universe of Discourse
Um dos pontos que me incomodou foi a mistura entre design de software, arquitetura de software e ergonomia da linguagem.
Mas primeiramente vamos ver o que me incomodou em ambos os blog posts.
Na última vez que escrevi sobre design patterns, foi para apontar que embora o movimento tenha sido inspirado pelo trabalho de “linguagem de pattern” de Christopher Alexander, não é parecido com nada que Alexander tenha sugerido, e que de fato o que Alexander sugeriu é mais interessante e provavelmente teria sido mais útil para programadores do que o movimento de design pattern escolheu seguir.
Uma das coisas que eu apontei foi essencialmente o que Norvig disse: que muitos patterns não estão realmente endereçando problemas recorrentes de design em programas orientados a objetos. Eles estão, na realidade, endereçando deficiências em linguagens de programação orientadas a objetos e que em linguagens melhores, esses problemas simplemente não aparecem ou são resolvidos de maneira tão fácil e trivial que a solução não requer um pattern. Em linguagem assembly, “chamada de sub-rotina” pode ser um pattern; em C, a solução é escrever result = function(args …), que é simples demais para se qualificar como pattern. Em uma linguagem como Lisp ou Haskell ou mesmo Perl, com um bom tipo de lista e poderosas primitivas para operar em valores de listas, o pattern “Iterator” (iterador) é aliviado em um grande degrau ou tido como invisível. Henry G. Baker pegou esse ponto em seu artigo Iterators: Sinais de Fraqueza em Linguagens Orientadas a Objetos.
Recebi muitas mensagens sobre isso, e curiosamente, alguns chegaram à mesma conclusão da mesma forma: eles disseram que embora eu estivesse certo sobre Iterator, era um exemplo pobre porque era um pattern muito simples, mas que era impossível imaginar um pattern mais complexo como Model-View-Controller ser absorvido e se tornar invisível dessa maneira.
Obviamente, como um post antigo não vou dar muito trelo ainda mas, veja.
O motivo de conseguirmos enxergar um iterator
for (auto mp : m_children){
// Do anything
}
O incômodo
Sendo absorvido por uma linguagem, mas nunca um MVC é simplesmente uma diferença de escopo.
Uma coisa é você aprimorar a ergonomia da linguagem facilitando um método de escrita em detrimento de outro.
Outra coisa é pegar o modelamento da arquitetura e fazer uma linguagem com isso.
Imagine que, no léxico de uma linguagem, print pertença a uma view, os parâmetros sejam models e as funções sejam controllers.
Simplesmente estúpido ao máximo.
E qual o problema original…
Esse é um problema do nome pattern: mesmo design pattern ainda é pouco descritivo.
Eu estou falando do design da linguagem para aumentar a produtividade do programador?
Ou estou falando do design na arquitetura para melhorar legibilidade e manutenção do código ao todo?
O Model-View-Controller deveria se enquadrar em design pattern então? SIM!!!
E Iteradores? SIM!!!
E Orientação a Objetos? SIM!!!
Novamente, é um problema de nomeação e domínio. Se tudo é um design pattern, fica difícil criar uma categorização mais aprofundada.
O mesmo ocorre quando comparamos software monolítico e microsserviços.
Aqui temos dois padrões de arquitetura de software que de alguma forma também um padrão de design.
Podemos dizer que uma linguagem pode absorver uma arquitetura de software?
Uma solução
Podemos adjetivar o design pattern para seu domínio.
Ergonic design patternpara quando falamos de um padrão de arquitetura que pode ser absorvido pela linguagem.
Sendo um exemplo o Iterator, Goto, Function.
Architecture design patternpara quando falamos de um padrão de arquitetura que não pode ser absorvido pela linguagem, mas pelo software em geral.
Sendo exemplos: Model-View-Controler, JSP Model1, Model-View-Adapter, Model-View-Presenter
Implementation design patternpara quando falamos de um padrão de arquitetura que não pode ser absorvido pela linguagem, nem pelo software em geral mas colocado para facilitar a implementação.
Sendo exemplos: Strategy Pattern, Observer pattern, Servant pattern, Command pattern, Chain of responsibility pattern.
Conclusão
No geral, o termo Design Pattern é genérico demais para ser útil no debate técnico.
Agrupar desde ergonomia da linguagem até arquitetura distribuída sob o mesmo nome é um desserviço.
A proposta de Adjetivar os patterns conforme seu domínio deve trazer clareza e distinguir melhor o que é arquitetural e o que é uma boa prática de implementação.
Talvez ao reclassificar os padrões com base não apenas naquilo que elas resolvem mas também no lugar onde operam.