Muitas pessoas parecem concordar que o padrão Singleton tem uma série de desvantagens e alguns até sugerem evitar o padrão completamente. Há uma excelente discussão aqui . Por favor, encaminhe quaisquer comentários sobre o padrão Singleton para essa pergunta.
Minha pergunta : Existem outros padrões de design que devem ser evitados ou usados com muito cuidado?
design-patterns
anti-patterns
Brian Rasmussen
fonte
fonte
Respostas:
Os padrões são complexos
Todos os padrões de design devem ser usados com cuidado. Na minha opinião, você deve refatorar os padrões quando houver uma razão válida para fazer isso, em vez de implementar um padrão imediatamente. O problema geral com o uso de padrões é que eles adicionam complexidade. O uso excessivo de padrões torna um determinado aplicativo ou sistema difícil de desenvolver e manter.
Na maioria das vezes, existe uma solução simples e você não precisa aplicar nenhum padrão específico. Uma boa regra prática é usar um padrão sempre que partes do código tendem a ser substituídas ou precisam ser alteradas com frequência e estar preparado para aceitar a advertência de código complexo ao usar um padrão.
Lembre-se de que seu objetivo deve ser a simplicidade e empregar um padrão se você vir uma necessidade prática de oferecer suporte a mudanças em seu código.
Princípios sobre padrões
Pode parecer discutível usar padrões se eles puderem levar a soluções complexas e com engenharia excessiva. No entanto, é muito mais interessante para um programador ler sobre técnicas e princípios de design que estabelecem a base para a maioria dos padrões. Na verdade, um dos meus livros favoritos sobre 'padrões de design' enfatiza isso reiterando quais princípios são aplicáveis ao padrão em questão. Eles são simples o suficiente para serem úteis do que os padrões em termos de relevância. Alguns dos princípios são gerais o suficiente para abranger mais do que programação orientada a objetos (OOP), como o Princípio de Substituição de Liskov , contanto que você possa construir módulos de seu código.
Há uma infinidade de princípios de design, mas aqueles descritos no primeiro capítulo do livro GoF são bastante úteis para começar.
Deixe-os penetrar em você por um tempo. Deve-se notar que, quando GoF foi escrito, uma interface significa qualquer coisa que seja uma abstração (o que também significa superclasses), não deve ser confundida com a interface como um tipo em Java ou C #. O segundo princípio vem do uso excessivo observado de herança, que infelizmente ainda é comum hoje .
A partir daí você pode ler sobre os princípios SOLID que foram divulgados por Robert Cecil Martin (também conhecido como Tio Bob) . Scott Hanselman entrevistou o tio Bob em um podcast sobre estes princípios :
Esses princípios são um bom começo para ler e discutir com seus colegas. Você pode descobrir que os princípios se entrelaçam uns com os outros e com outros processos, como separação de interesses e injeção de dependência . Depois de fazer TDD por um tempo, você também pode descobrir que esses princípios surgem naturalmente na prática, pois você precisa segui-los até certo ponto para criar testes de unidade isolados e repetíveis .
fonte
O que mais preocupou os próprios autores de Design Patterns foi o padrão "Visitante".
É um "mal necessário" - mas é freqüentemente usado demais e a necessidade dele geralmente revela uma falha mais fundamental em seu projeto.
Um nome alternativo para o padrão "Visitante" é "Multi-dispatch", porque o padrão Visitante é o que você acaba com quando deseja usar uma linguagem OO de despacho de tipo único para selecionar o código a ser usado com base no tipo de dois (ou mais) objetos diferentes.
O exemplo clássico é que você tem a interseção entre duas formas, mas há um caso ainda mais simples que costuma ser esquecido: comparar a igualdade de dois objetos heterogêneos.
De qualquer forma, muitas vezes você acaba com algo assim:
O problema com isso é que você juntou todas as suas implementações de "IShape". Você deu a entender que sempre que desejar adicionar uma nova forma à hierarquia, você também precisará alterar todas as outras implementações de "Forma".
Às vezes, este é o design mínimo correto - mas pense bem. Seu projeto realmente exige que você despache em dois tipos? Você está disposto a escrever cada uma das explosões combinatórias de métodos múltiplos?
Freqüentemente, ao introduzir outro conceito, você pode reduzir o número de combinações que realmente terá que escrever:
Claro, depende - às vezes você realmente precisa escrever código para lidar com todos esses casos diferentes - mas vale a pena fazer uma pausa e pensar antes de mergulhar e usar o Visitor. Isso pode lhe poupar muita dor mais tarde.
fonte
Singletons - uma classe que usa o singleton X tem uma dependência difícil de ver e de isolar para teste.
Eles são usados com frequência porque são convenientes e fáceis de entender, mas podem realmente complicar os testes.
Veja Singletons são mentirosos patológicos .
fonte
Eu acredito que o padrão Template Method geralmente é um padrão muito perigoso.
fonte
Não acho que você deva evitar Design Patterns (DP), e não acho que você deva se forçar a usar DPs ao planejar sua arquitetura. Só devemos usar DPs quando eles surgirem naturalmente de nosso planejamento.
Se definirmos desde o início que queremos usar um determinado DP, muitas de nossas futuras decisões de projeto serão influenciadas por essa escolha, sem garantia de que o DP que escolhemos seja adequado às nossas necessidades.
Uma coisa que também não devemos fazer é tratar um DP como uma entidade imutável, devemos adaptar o padrão às nossas necessidades.
Então, resumindo, não acho que devemos evitar os PDs, devemos abraçá-los quando já estão tomando forma em nossa arquitetura.
fonte
Acho que o Active Record é um padrão usado em demasia que incentiva a mistura da lógica de negócios com o código de persistência. Ele não faz um trabalho muito bom em ocultar a implementação de armazenamento da camada de modelo e vincula os modelos a um banco de dados. Existem muitas alternativas (descritas no PoEAA), como Table Data Gateway, Row Data Gateway e Data Mapper, que muitas vezes fornecem uma solução melhor e certamente ajudam a fornecer uma melhor abstração para armazenamento. Além disso, seu modelo não precisa ser armazenado em um banco de dados; Que tal armazená-los como XML ou acessá-los usando serviços da web? Seria muito fácil mudar o mecanismo de armazenamento de seus modelos?
Dito isso, o Active Record nem sempre é ruim e é perfeito para aplicativos mais simples onde as outras opções seriam exageradas.
fonte
É simples ... evite Design Patterns que não sejam claros para você ou aqueles nos quais você não se sinta confortável .
Para citar alguns ...
existem alguns padrões pouco práticos , como por exemplo:
Interpreter
Flyweight
também existem alguns mais difíceis de entender , como por exemplo:
Abstract Factory
- O padrão de fábrica totalmente abstrato com famílias de objetos criados não é tão fácil quanto pareceBridge
- Pode ficar muito abstrato, se abstração e implementação forem divididas em subárvores, mas é um padrão muito utilizável em alguns casosVisitor
- A compreensão do mecanismo de despacho duplo é realmente OBRIGATÓRIOe existem alguns padrões que parecem terrivelmente simples , mas não são uma escolha tão clara devido a vários motivos relacionados ao seu princípio ou implementação:
Singleton
- não é um padrão totalmente ruim, apenas muito usado (muitas vezes lá, onde não é adequado)Observer
- ótimo padrão ... apenas torna o código muito mais difícil de ler e depurarPrototype
- verifica o compilador de negociações quanto ao dinamismo (que pode ser bom ou ruim ... depende)Chain of responsibility
- muitas vezes apenas forçado / artificialmente empurrado para o designPara aqueles "pouco práticos", deve-se realmente pensar antes de usá-los, porque geralmente há soluções mais elegantes em algum lugar.
Para os mais "difíceis de agarrar" ... são uma grande ajuda, quando são usados em locais adequados e quando bem implementados ... mas são um pesadelo, quando usados indevidamente.
Agora, o que vem a seguir ...
fonte
Espero não apanhar muito por isso. Christer Ericsson escreveu dois artigos ( um , dois ) sobre o tópico de padrões de projeto em seu blog de detecção de colisão em tempo real . Seu tom é bastante áspero, e talvez um pouco provocador, mas o homem sabe o que faz, então eu não descartaria isso como delírios de um lunático.
fonte
Alguns dizem que o localizador de serviço é um antipadrão.
fonte
Eu acredito que o padrão do observador tem muito a responder, ele funciona em casos muito gerais, mas conforme os sistemas se tornam mais complexos, ele se torna um pesadelo, precisando de notificações OnBefore (), OnAfter () e, muitas vezes, postando tarefas assíncronas para evitar novas entrada. Uma solução muito melhor é desenvolver um sistema de análise automática de dependência que instrumenta todos os acessos a objetos (com barreiras de leitura) durante os cálculos e cria automaticamente uma borda em um gráfico de dependência.
fonte
Um complemento ao post de Spoike, Refatorar para padrões é uma boa leitura.
fonte
Iterator é mais um padrão GoF a ser evitado ou, pelo menos, a ser usado apenas quando nenhuma das alternativas estiver disponível.
As alternativas são:
para cada loop. Essa construção está presente na maioria das linguagens convencionais e pode ser usada para evitar iteradores na maioria dos casos.
seletores à la LINQ ou jQuery. Eles devem ser usados quando for-each não for apropriado, porque nem todos os objetos do container devem ser processados. Ao contrário dos iteradores, os seletores permitem manifestar em um lugar quais tipos de objetos devem ser processados.
fonte
yield
iterador. Eric White tem uma ótima discussão sobre isso em C # 3.0: blogs.msdn.com/b/ericwhite/archive/2006/10/04/… . Além disso, verifique a discussão de Jeremy Likness sobre corrotinas com iteradores: wintellect.com/CS/blogs/jlikness/archive/2010/03/23/… .