Existem padrões de design desnecessários em linguagens dinâmicas como Python?

98

Comecei a ler o livro de padrões de design do GoF. Alguns padrões parecem muito semelhantes, com apenas pequenas diferenças conceituais.

Você acha que dentre os muitos padrões, alguns são desnecessários em uma linguagem dinâmica como Python (por exemplo, porque são substituídos por um recurso dinâmico)?

Gerenuk
fonte
1
É uma pergunta interessante, pois implica que a escolha da linguagem pode substituir efetivamente as construções de código.
Joshin4colours
3
Não é uma resposta, mas é relevante - eu pensei que os padrões de design do GoF eram tão relevantes para alguns princípios gerais que podem ser extraídos deles quanto para os padrões específicos. Não quero dizer a idéia de um padrão (embora isso seja certamente significativo), mas mais a permissão para usar classes de certas maneiras que violam os princípios ingênuos da OOP. Por exemplo, há muitos padrões em que "a forma" claramente não "se desenha" ou pelo menos delega algum aspecto do trabalho a outro objeto. Eu acho que essa lição é importante em qualquer idioma que suporte OOP.
31912 Steve314
Pergunta muito interessante. Eu gostaria de poder +5 em vez de +1.
precisa saber é o seguinte
1
Veja também em Padrões de design ausentes nos recursos de idioma e Padrões de design ausentes nos recursos de idioma em c2. Nem sequer é uma questão de 'linguagem dinâmica'. O exemplo mais simples é o padrão do iterador, que é trivial em python, perl (e até Java - não dinâmico).

Respostas:

92

Peter Norvig demonstra que 16 dos 23 padrões de design encontrados no livro do GOF são invisíveis ou mais simples em linguagens dinâmicas (ele se concentra em Lisp e Dylan).

Desde que você mencionou o Python, há uma boa apresentação de Alex Martelli sobre o tópico. Também relacionado ao Python, há um bom post no blog demonstrando seis padrões de design no Python idiomático .

Também mantenho um repositório do github com implementações (por outras pessoas) dos padrões de design mais comuns em Python .

sakisk
fonte
Ótimo! Isso seria um ponto de resposta :) Eu gostaria que todos tivessem compreendido a pergunta com clareza.
Gerenuk
2
Segundo Norvig, 2 dos 16 (intérprete e iterador) são "invisíveis ou mais simples" devido às macros (que o Python não possui).
Mjs
1
não está claro para mim que todos esses padrões não são necessários porque o lisp é dinâmico, mas devido a outros recursos, como uma forte linguagem funcional
jk.
Os iteradores do @mjs são um recurso interno do Python.
sakisk
1
Esta grande resposta pode ser mesmo ligeiramente melhorada alterando as legendas ligação um tanto sem sentido demonstra , apresentação e repositório - eles são muito melhores, então aqui , mas, você sabe ... :-)
Lobo
59

Nenhum padrão de design é necessário. Em qualquer idioma.

Costumo encontrar muitos códigos escritos por pessoas que leem sobre padrões de design e pensam que devem usá-los em todo o lugar. O resultado é que o código real fica oculto sob toneladas de interfaces, invólucros e camadas e é muito difícil de ler. Essa é uma abordagem errada aos padrões de design.

Os padrões de design existem para que você tenha um repertório de expressões úteis úteis quando se deparar com um problema. Mas você nunca deve aplicar nenhum padrão antes de identificar o problema. Mantenha as coisas simples Estúpido deve sempre ser o princípio superior de governo.

Também ajuda a pensar nos padrões de design como um conceito para pensar no problema, e não no código específico para escrever. E sobre grande parte do boilerplate como solução alternativa para Java sem funções livres e objetos de função padrão que você usa na maioria das outras linguagens que os possuem (como Python, C #, C ++ etc.).

Eu poderia dizer que tenho um padrão de visitante, mas em qualquer idioma com funções de primeira classe, será apenas uma função que assume uma função. Em vez da classe de fábrica, normalmente tenho apenas uma função de fábrica. Posso dizer que tenho uma interface, mas são apenas alguns métodos marcados com comentários, porque não haveria outra implementação (é claro que em python uma interface é sempre apenas comentários, porque é do tipo pato). Eu ainda falo do código como usando o padrão, porque é uma maneira útil de pensar sobre isso, mas não digite todas as coisas até que eu realmente precise.

Portanto, aprenda todos os padrões como conceitos . E esqueça as implementações específicas. A implementação varia, e deve variar, no mundo real, mesmo apenas em Java.

Jan Hudec
fonte
28
Sua declaração de abertura é simplista demais ao extremo. É verdade que os padrões têm seu custo, portanto, não devem ser usados ​​às cegas, apenas por causa disso. Mas no lugar certo, eles podem ser uma grande ajuda. E sim, eles são específicos do idioma - alguns padrões são desnecessários em alguns idiomas porque o próprio idioma suporta uma abordagem melhor. Mas isso ainda está muito longe da sua reivindicação inicial.
Péter Török
2
O Visitor Btw não é totalmente substituído por funções de ordem superior - é uma solução para implementar o envio duplo em uma linguagem que não o suporta nativamente (como C # e C ++). (E ele deve realmente ser usado muito moderadamente - Considero-o um dos padrões mais misteriosos e custosas cujo uso é IMHO tão difícil de justificar que eu mesmo nunca usei até agora.)
Péter Török
14
Bem, você nunca precisa de um padrão. O que você precisa é resolver um problema . Se você não conhece nenhum padrão para isso, ainda pode resolvê-lo, isso exigirá mais reflexão e você poderá encontrar uma solução que corresponda a algum padrão ou a um que não. Conhecer os padrões apenas facilita.
Jan Hudec
3
@ Gerenuk: Sim, mas o ponto é que os padrões não são específicos de um idioma, são para sua cabeça. Você geralmente descobre que algum padrão é realizado com muito mais facilidade e usando ferramentas diferentes em python, mas o mesmo conceito geralmente existe.
Jan Hudec
4
@ PéterTörök: O visitante não é substituído por nada. O ponto é que o mesmo conceito pode ser implementado usando ferramentas diferentes em casos diferentes, mas ainda o considero o mesmo padrão.
Jan Hudec
13

O padrão abstrato de fábrica é desnecessário em linguagem tipada como pato, como Python, pois é praticamente incorporada à linguagem.

vartec
fonte
10
bem, você ainda precisa de fábricas diferentes. Você simplesmente não precisa da definição da interface.
Stefano Borini
1
Se você tem uma aula, você já tem uma fábrica. As classes são objetos de primeira classe e podem ser passadas para qualquer lugar e simplesmente chamadas para criar um objeto (diferente do Java). Você não precisa criar mais nada. Se você quiser algo que não seja o construtor padrão, crie um lambda / callable de algum tipo que envolva o construtor de alguma maneira.
Spookylukey
13

O único que vem à mente é o padrão Singleton.

Como o Python não o força a usar classes para tudo , basta usar uma estrutura de dados global. Essa estrutura de dados global pode ser gerenciada por uma instância, mas você não precisa controlar a instanciação dessa classe, basta criar a instância na importação e deixá-la assim.

Principalmente, Singletons em python são substituídos por um módulo. Módulos em python são, por sua própria natureza, Singletons; o intérprete python os cria uma vez e apenas uma vez.

Todos os outros padrões no Design Patters que usei no Python uma vez ou outra, e você encontrará exemplos deles em toda a biblioteca padrão do Python e no próprio Python.

Martijn Pieters
fonte
2
Isso não é realmente um antipadrão hoje em dia?
Den
16
O Singleton é um antipadrão . Em todas as línguas Ele foi criado para resolver vários problemas não relacionados e também não é uma boa combinação (observe que até o Java possui membros estáticos, que existem uma vez por classe, portanto, você não precisa de uma instância para isso).
Jan Hudec
1
E em Python, nunca nos importamos com isso, pois nunca houve um problema a ser resolvido.
Martijn Pieters
1
"Python não força você a usar objetos para tudo" Não é verdade. Não é apenas desagradável como em Java, mas ainda assim, no Python tudo é um objeto. O módulo par é um objeto.
vartec
3
@Darthfett: Estou bem ciente de como lenfunciona; Guido fez uma escolha explícita aqui . Meu objetivo é mostrar que Python não é uma linguagem pura de POO; é uma linguagem pragmática. Eu gosto assim.
Martijn Pieters
8

Os padrões de design são para o programador, não para o idioma. Os programadores tendem a usar padrões que os ajudam a entender o problema em questão. Nenhum padrão de design é estritamente necessário, mas pode ser útil para ajudar a simplificar o que você está tentando fazer.

Python, e tipagem de pato especificamente, fornecem um fim em torno de muitos padrões e práticas comuns, e muitas das restrições impostas por alguns padrões (privacidade, imutabilidade etc.) só se mantêm na medida em que o programador concorda em não quebrá-las. . Mas, ainda assim, eles não funcionam enquanto o programador joga junto. Uma porta ainda é uma porta, mesmo que seja emoldurada por paredes imaginárias.

O Python é considerado uma linguagem "multi-paradigma"; você pode usar os padrões que quiser. Isso é intencional. Ele fornece hierarquias de classe complexas, por exemplo, mesmo que sejam completamente desnecessárias e um pouco artificiais. Mas para algumas pessoas essa abstração específica é útil. Não porque o problema exige, mas porque o programador exige. Então lá vai você.

tylerl
fonte
Isso é certamente interessante. Então, quais padrões em particular você quer esquecer, porque existem maneiras melhores em Python?
Gerenuk
4

O livro original "Design Patterns" documentou e nomeou alguns idiomas comuns úteis em linguagens imperativas e orientadas a objetos, como C ++ e Smalltalk. Mas o Smalltalk é uma linguagem de tipo dinâmico, por isso não pode ser estritamente uma questão de ser dinâmico.

No entanto, a resposta para sua pergunta ainda é "sim": alguns desses padrões de design serão irrelevantes para as linguagens modernas de tipo dinâmico. De maneira mais geral, haverá diferentes padrões de design em diferentes idiomas, especialmente em diferentes tipos de idiomas.

Para reiterar: um "padrão de design" é simplesmente um nome para um idioma de programação: uma solução comum para um problema freqüentemente encontrado. Idiomas diferentes exigem idiomas diferentes, porque o que é um problema para um idioma pode ser trivial para outro. Nesse sentido, os padrões de design tendem a apontar pontos fracos nos idiomas aos quais se aplicam.

Portanto, você pode procurar outros recursos que tornam as linguagens dinâmicas modernas (ou antigas como o Lisp) mais poderosas, tornando alguns desses padrões clássicos de design irrelevantes.

tempestade
fonte
1

Padrões de design são maneiras de resolver problemas específicos. Se um problema não for atendido, o padrão de resolução não será útil.

As pessoas estão tentando adaptar padrões de design em todos os lugares, como se fosse uma prática recomendada ter padrões de design em seu projeto. Isso é o contrário. Você encontrou um problema que pode ser resolvido com um padrão de fábrica? Legal. Adapte-o. Não procure seu código e tente encontrar o lugar certo para implementar um singleton (ou fábrica, fachada ou qualquer outra coisa ...).

Talvez o Python tenha seus próprios padrões de design não disponíveis para pessoas Java e .NET (devido à natureza dessas linguagens)?

Andrzej Bobak
fonte
1

Eu diria que os padrões sempre dependem da linguagem. O fato de a maioria dos padrões de python se parecer com os definidos no GoF é por causa do POO do Python, sendo dito que POO não é como POO (duas linguagens definem objetos e sua manipulação é 100% semelhante).

Portanto, não há dúvida de que alguns padrões não serão aplicáveis ​​"como estão", alguns podem não fazer sentido e existem alguns padrões que podem ser significativos apenas para o Python.

Para voltar exatamente à sua pergunta: os padrões são necessários apenas se você precisar deles. Você não precisa usá-los se não houver necessidade deles (como Jan Hudec já disse).

Além disso, existem muito mais padrões do que os mencionados no GoF. Veja na wikipedia outros padrões

estani
fonte