O que permanece o mesmo? O que muda?
Os padrões são os mesmos. As técnicas de linguagem mudam.
Existem princípios orientadores como o SOLID,
Sim. Na verdade, eles continuam sendo os princípios orientadores. Nada muda.
ou padrões canônicos (talvez inteiramente novos) que um novato em linguagem dinâmica deveria conhecer?
Algumas coisas são únicas. Principalmente o impacto é que as técnicas de implementação mudam.
Um padrão é - bem - um padrão . Não é uma lei. Não é uma sub-rotina. Não é uma macro. É apenas uma boa ideia que se repete porque é uma boa ideia.
Boas idéias não saem de moda nem mudam drasticamente.
Outras notas. Python não é "fracamente digitado". É mais tipificado do que Java ou C ++ porque não há operação de conversão. [Sim, existe uma maneira de falsificar a classe associada a um objeto, mas não é o tipo de coisa que é feita, exceto para provar um ponto exigente e legalista.]
Além disso. A maioria dos padrões de design é baseada em diferentes maneiras de explorar o polimorfismo.
Olhe para Estado ou de comando ou Memento como exemplos. Eles têm hierarquias de classe para criar estados polimórficos, comandos ou lembranças de mudanças de estado. Nada muda significativamente quando você faz isso no Python. Pequenas mudanças incluem o relaxamento da hierarquia precisa de classes, porque o polimorfismo no Python depende de métodos comuns e não de ancestrais comuns.
Além disso, alguns padrões são simplesmente uma tentativa de obter ligação tardia. A maioria dos padrões relacionados à fábrica é uma tentativa de permitir alterações fáceis em uma hierarquia de classes sem recompilar todos os módulos C ++ no aplicativo. Essa otimização não é tão interessante em uma linguagem dinâmica. No entanto, uma fábrica como forma de ocultar detalhes de implementação ainda tem um valor enorme.
Alguns padrões são uma tentativa de conduzir o compilador e o vinculador. Singleton , por exemplo, existe para criar globais confusos, mas pelo menos os encapsula. As classes singleton em Python não são uma perspectiva agradável. Mas os módulos Python já são singletons, muitos de nós apenas usamos um módulo e evitamos tentar mexer com uma classe Singleton .
Peter Norvig abordou essa questão em 1998, leia http://norvig.com/design-patterns/ppframe.htm para obter um conjunto de coisas detalhadas que ele notou e http://c2.com/cgi/wiki?AreDesignPatternsMissingLanguageFeatures para discussão adicional sobre o assunto.
A versão curta é que, quando seu idioma possui mais recursos, os padrões de design repetitivo tendem a se tornar mais simples - geralmente a ponto de ficarem invisíveis. Ele descobriu que isso era verdade para a maioria dos padrões de design que o GoF havia identificado.
fonte
A programação em uma linguagem dinâmica orientada a objetos usa muitos dos mesmos padrões e princípios, mas existem alguns ajustes e diferenças devido ao ambiente:
Substituir interfaces por Duck Typing - Onde o Gang of Four diria para você usar uma classe base abstrata com funções virtuais puras e você usaria uma interface em Java, em uma linguagem dinâmica, você só precisa entender. Como você pode usar qualquer objeto em qualquer lugar e funcionará bem se implementar os métodos realmente chamados, não será necessário definir uma interface formal. Pode valer a pena documentar um, para que fique claro o que é realmente necessário.
As funções também são objetos - Existem muitos padrões relacionados à separação entre decisão e ação; Comando, Estratégia, Cadeia de Responsabilidade, etc. Em uma linguagem com funções de primeira classe, geralmente é razoável simplesmente passar uma função ao invés de criar objetos com
.doIt()
métodos. Esses padrões se transformam em "use uma função de ordem superior".VENDIDO - O Princípio de Segregação de Interface leva o maior sucesso aqui, por não haver interfaces. Você ainda deve considerar o princípio, mas não pode reificá-lo em seu código. Somente a vigilância pessoal o protegerá aqui. No lado positivo, a dor causada pela violação desse princípio é muito reduzida em ambientes dinâmicos comuns.
"... no meu particular ... idioma!" - Cada idioma tem boas práticas e más práticas, e você precisará aprendê-las e segui-las, se quiser o melhor código nessas línguas. Um padrão de iterador perfeitamente escrito pode ser considerado uma linguagem com compreensões de lista incorporadas, por exemplo.
fonte
Na minha experiência, alguns padrões ainda são úteis em Python e ainda mais fáceis de configurar do que em linguagens mais estáticas. Alguns padrões OTOH simplesmente não são necessários, ou até desaprovados, como o padrão Singleton. Use uma variável ou função no nível do módulo. Ou use o Padrão Borg.
Em vez de configurar um Padrão de Criação, geralmente é suficiente transmitir uma chamada que cria objetos. Pode ser uma função, um objeto com um
__call__
método ou mesmo uma classe, já que não existenew()
no Python, apenas uma invocação da própria classe:O padrão de estado e estratégia compartilha uma estrutura muito semelhante em linguagens como C ++ e Java. Menos no Python. O Padrão de Estratégia permanece mais ou menos o mesmo, mas o Padrão de Estado se torna praticamente desnecessário. O padrão de estado em idiomas estáticos simula a mudança de classe no tempo de execução. No Python, você pode fazer exatamente isso: alterar a classe de um objeto em tempo de execução. Contanto que você o faça de maneira encapsulada e controlada, você deve ficar bem:
Os padrões que dependem do Static Type Dispatch não funcionarão ou funcionarão de maneira bastante diferente. Você não precisa escrever tanto código da placa da caldeira, por exemplo, Visitor Pattern: em Java e C ++, é necessário escrever um método de aceitação em todas as classes visitáveis, enquanto que no Python você pode herdar essa funcionalidade por meio de uma classe mixin, como Visitable:
Muitas situações que exigem a aplicação de um padrão em uma linguagem estática não o fazem tanto em Python. Muitas coisas podem ser resolvidas com outras técnicas, como funções de ordem superior (decoradores, fábricas de funções) ou meta-classes.
fonte
__class__
a implementação de uma fábrica em Python ?