Quais padrões de design são os piores ou os mais estritamente definidos? [fechadas]


28

Para cada projeto de programação, gerentes com experiência anterior em programação tentam brilhar quando recomendam alguns padrões de design para o seu projeto. Gosto de padrões de design quando eles fazem sentido ou se você precisar de uma solução escalável. Eu usei padrões de Proxies, Observadores e Comando de uma maneira positiva, por exemplo, e faço isso todos os dias. Mas estou realmente hesitante em usar o padrão Factory, se houver apenas uma maneira de criar um objeto, pois uma fábrica pode facilitar tudo no futuro, mas complica o código e é pura sobrecarga.

Portanto, minha pergunta é em relação à minha futura carreira e minha resposta aos tipos de gerente que usam nomes aleatórios de padrões:

Quais padrões de design você usou que o levaram de volta no geral? Quais são os piores padrões de design , os que você deve considerar, exceto na única situação em que eles fazem sentido (leia-se: quais padrões de design são definidos de maneira muito restrita)? (É como se eu estivesse procurando as críticas negativas de um bom produto geral da Amazon para ver o que mais incomodava as pessoas ao usar padrões de design.) E não estou falando sobre Anti-Patterns aqui, mas sobre padrões que geralmente são considerados padrões "bons".

Edit: Como alguns responderam, o problema geralmente é que os padrões não são "ruins", mas "usados ​​incorretamente". Se você conhece padrões, que são frequentemente mal utilizados ou mesmo difíceis de usar, eles também serviriam como resposta.


A maioria dos padrões facilita as mudanças futuras em alguns eixos de mudança, mas eles podem dificultar as mudanças em outros eixos de mudança. A turma dos quatro livros é particularmente boa em dizer quando um padrão é aplicável. Muitos livros subsequentes sobre padrões perdem esse ponto. Tome o padrão Visitor como um exemplo. Isso facilita a adição de novos algoritmos de deslocamento em árvore, mas torna mais difícil adicionar novos tipos de nós à árvore. Também permite que os algoritmos de deslocamento estejam em uma camada superior à da árvore. Você precisa considerar qual eixo de mudança é menos estável e o design para facilitar as alterações ao longo desse eixo.
Theodore Norvell

Todos no livro 'Gang of Four'.
Route de milhas

Respostas:


40

Não acredito em maus padrões, acredito que os padrões podem ser mal aplicados!

  • IMHO o singleton é o padrão mais abusado e aplicado de maneira errada. As pessoas parecem ter uma doença isolada e começam a enxergar possibilidades de singletons em todos os lugares, sem considerar alternativas.
  • O padrão de visitantes do IMHO tem o uso mais restrito e quase nunca se justifica a complexidade adicional. Um bom pdf pode ser obtido aqui . Realmente, somente quando você tiver uma estrutura de dados que você sabe que será percorrida enquanto executa operações diferentes na estrutura de dados sem conhecer todas as formas de antecedência, dê ao padrão de visitante uma chance de lutar. É bonito :)

Para esta resposta, considerei apenas os padrões GOF. Não conheço todos os padrões possíveis o suficiente para levá-los em consideração também.


Vejo muito poucos usos para Visitantes. Singletons ... não me inicie. Se a situação não for perfeita para uma pessoa, não a use.
Michael K

1
Pode haver muito poucos usos para o Visitor, mas quando existe, certamente resolve problemas. Meu entendimento é que o Vistor é essencial para o LINQ.
Quentin-starin

12
O padrão Visitor é crítico para reduzir (ou eliminar) a complexidade ciclomática em um programa de software. Sempre que houver uma árvore if / else ou uma instrução switch, as chances de um Visitante poder substituí-las são altas, oferecendo execução garantida e verificação em tempo de compilação. O Visitante é um dos padrões mais poderosos que conheço, e o usamos regularmente com grande efeito. Isso torna o teste um sonho também.
precisa saber é o seguinte

@LesHazlewood O Visitor não é apenas uma solução alternativa para linguagens de programação inadequadas? Idiomas do tipo ML (Haskell, SML, OCaml etc.) têm tipos de dados algébricos ("união com esteróides") e correspondência de padrões ("troca de esteróides") que produzem código mais simples que o Visitor, mas totalmente verificado pelo compilador. Comparado ao visitante, você não possui muitos métodos cujo estado de compartilhamento você precisa gerenciar manualmente através das propriedades do objeto. Em idiomas semelhantes ao ML, e todas as distinções entre maiúsculas e minúsculas devem estar completas, caso contrário não serão compiladas.
Vog #

14

Além de Singleton e Visitor já mencionados pelos outros respondentes, não conheço padrões de design "notórios". IMHO, os maiores problemas não decorrem de um padrão de design específico estar "errado", mas de desenvolvedores que aplicam padrões com muita avidez.

Quase todo mundo passa pela fase da "febre do padrão" ao se familiarizar com os padrões. Pensando que os padrões são a melhor coisa desde o pão fatiado, inicialmente tenta-se aplicá-los sempre que vê uma possibilidade. Isso faz com que o código fique oculto sob padrões, onde os próprios padrões não ajudam mais, apenas tornam o código mais difícil de entender e manter a longo prazo.

Eventualmente, a maioria de nós supera essa fase e começa a aprender como usar os padrões para resolver problemas reais, não por eles mesmos. Os padrões têm seu preço, que é uma complexidade adicionada, e a aplicação de qualquer padrão específico só é justificada quando se paga pela complexidade adicionada, ajudando a simplificar alguma outra parte do sistema, tornando assim o código / configuração geral mais fácil de entender e manter. Se não for esse o caso, geralmente é melhor ficar longe dos padrões, mantendo a solução mais simples que possa funcionar.


Absolutamente. Os padrões não são bons nem maus, são bem aplicados ou mal aplicados.

Prefiro ensinar as pessoas da maneira que aprendi: OO primeiro, entendendo como o objeto se relaciona e depois aprendendo os nomes dos padrões. É muito fácil pensar em termos de padrões do que o que precisa ser feito. Eles são uma ferramenta de comunicação.
Michael K

Os padrões são um meio de comunicação, não uma lista prescritiva. Se você começar com um padrão em mente, poderá aplicá-lo mal. Se você encontrar um, ou as dicas de um, em seu design, os catálogos de padrões podem ajudá-lo a entender o que mais você pode precisar.
Rob Crawford

14

Eu vou sair em um galho aqui e sugerir o uso excessivo de herança. Definitivamente, o mais aplicável em linguagens sem suporte sólido ao polimorfismo em tempo de compilação, como Java. A herança em tempo de execução é uma ferramenta, não um tipo de maravilha de um recurso para todos.

Outras pessoas já expressaram similar ao meu ódio pessoal a Singletons, então não vou expandir isso aqui.


10

Singleton. É um dos padrões GOF que agora é chamado com mais frequência como antipadrão. Uma das razões para isso é que Singleton torna o código mais difícil de testar.


4
Existem inúmeras falhas fundamentais no padrão singleton, a maioria é bem ilustrada neste artigo por Steve Yegge - Singleton Considered Stupid
ocodo

Slomojo: Bom artigo. Vou chamá-lo de 'padrão simplório' a partir de agora:-)
ninguém

2
Sim, porque algum tolo usa um padrão de maneira errada e perde totalmente o objetivo do OO (a julgar por todas as classes de gerente que ele criou), é claro que é culpa do padrão e não dos desenvolvedores.
Dunk

Por que todos associam a implementação comum (e problemática) de Singleton ao padrão Singleton? Um quase sempre é ruim, o outro não.
Quentin-starin

1
@qes> Singleton apresenta problemas importantes de implementação (especialmente com threading). Este já é um ponto ruim. Mas você também descobrirá que o singleton é um padrão sobre como a classe é processada, e não como ela funciona. Como a classe é usada deve ser tratada pelo código usando a classe, para que Singleton seja uma quebra de separação de preocupações.
23412 deadalnix

7

Se você conhece padrões, que são frequentemente mal utilizados ou mesmo difíceis de usar, eles também serviriam como resposta.

Seguindo o padrão MVVM para WPF muito estritamente, como indicado, por exemplo, por esta pergunta . Algumas pessoas tentam seguir a diretriz de que nenhum código deve ser colocado no código por trás de maneira muito rigorosa e criar todo tipo de hacks exóticos.

E, é claro, o MVVM é difícil como o inferno, e não vale a pena para pequenos projetos de curto prazo.

O Dr. WPF fez um post irônico sobre isso em seu artigo MV-poo .


@ Akkku: É claro que você deve saber como usá-lo, para poder decidir se é adequado ao seu projeto. Então, sim, é essencial para o desenvolvimento do WPF e muito útil.
Steven Jeuris

Um dos problemas é que as pessoas não entendem o padrão MVVM. Não é "difícil como o inferno". As pessoas fazem dessa maneira pensando que todos os outros padrões, como Padrão de Comando e Padrão de Mediador, fazem parte dele. Por si só, o MVVM é um dos padrões mais simples, na minha opinião. Concordo que seguir qualquer coisa até t é apenas uma tolice.
BK

5

Alguns dos padrões no livro GOF são específicos para C ++, no sentido em que são menos aplicáveis ​​em linguagens com reflexão, por exemplo, o padrão Prototype é menos significativo em Java.

Considero o padrão do intérprete um padrão "estreito". Você precisa ter um problema geral que valha a pena desenvolver um solucionador de problemas geral. Ele funciona apenas para problemas especiais para os quais você pode inventar um idioma, definir uma gramática e escrever um intérprete. As instâncias do problema devem ser representáveis ​​como uma sentença na gramática. Eu não acho que você se depara com essas situações com frequência.


1
a maior parte do GOF é aplicável apenas a OOP baseado em classe estática. desvie-se um pouco desse tipo de linguagem e o livro se torna apenas uma anedota sobre entretenimento.
Javier

5

O que mais me arrependo (embora não com mais veemência): Quando deveria ter criado uma função, mas implementei uma solução OOP.


1
Por quê? O que fez você se arrepender? Expanda sua resposta e adicione sua experiência.
1700 Walter Walter

Na verdade, acho que uma classe com variáveis ​​locais e métodos claros é MUITO mais fácil de reutilizar do que uma única função de 200 linhas que só pode ser reaplicada via copiar e colar e, em seguida, não tem apenas um lugar para parecer feia e incompreensível.
Akku

2
O KISS implica que você a faça funcionar primeiro e depois refatorar para uma classe, se necessário.
Eva

5

Fábrica. Eu vi código implementá-lo que cria apenas um tipo. Isso é código totalmente inútil IMO. Não ajuda que muitos dos exemplos online sejam completamente inventados. Fábrica de pizza?

Talvez a fábrica seja mais fácil de testar devido à injeção de dependência. Mas adicionar esse código quando você não precisa, não faz sentido para mim, e o argumento de teste desaparece quando você pode usar estruturas simuladas como o JMockit. Quanto mais simples você puder criar um programa, melhor. As fábricas realmente só fazem sentido com um número maior de tipos (por maiores, quero dizer, pelo menos, mais de 2).


Sim, fábrica de pizzas, obrigado por Head First Design Pattern ~
Niing 04/04

2

Singleton

Eu concordo com os outros sobre Singleton. Não que você nunca deva usá-los, apenas que isso se limite a muito poucos casos. Eles são usados ​​como globais preguiçosos a maior parte do tempo.

A segurança de threads é um problema nos singletons. O tratamento de exceções é outro - se o singleton não conseguir criar corretamente - nem sempre você sabe se pode detectar o erro com segurança, principalmente se esse foi um desses objetos criados "antes do main". E depois há a questão da limpeza depois.

Costumo preferir usar um singleton e fazer com que todos os outros "wannabe" singletons "se inscrevam" no seu. Meu uso mais comum de singleton é o manuseio de "evento de grito": você apenas "transmite ao mundo" que um evento ocorreu e qualquer pessoa que esteja ouvindo que lida com o evento o faz. Dessa forma, você dissocia os eventos realmente acontecendo com o que os está ouvindo. (Registro, sinais, etc.)

Visitante

A coisa feia que eu acho sobre isso, além do fato de que os desenvolvedores não conseguem pensar em nomes significativos e apenas chamar os métodos visit (), é que ele adiciona extensibilidade em uma direção enquanto remove em outra, ou seja, adiciona funcionalidade extra, mas restringe o número de objetos que seus visitantes precisam saber sobre todos os tipos de objetos que podem visitar.

É possível, embora confuso, permitir a extensão nas duas direções, mas isso não usa totalmente o padrão de visitante em sua forma regular. O aplicativo mais comum para isso é a impressão de objetos: você tem diferentes maneiras de imprimir e diferentes objetos que precisam ser impressos. Você deve estender isso nas duas direções. (Impressão significa qualquer tipo de transformação de objetos em um fluxo: armazenamento em um arquivo / gravação em um console / GUI ... etc).

(Nota: você não deve confundir isso com a arquitetura de exibição de documento, que é um padrão ligeiramente diferente).


2
Sua solução usa o argumento antigo de dissociar as coisas. Em particular, você publica um evento e outro cara lida com o evento e o registra. Isso é bom, porque todo mundo está desacoplado! ERRADO! Eu costumava fazer isso, que dor real se tornou. Percebi que, se quero que algo seja registrado, quero dizer explicitamente registrar exatamente isso, aqui e agora, no código no momento em que ocorreu. Não há outro objeto para descobrir o que deve ser registrado, com possíveis outros eventos interceptados por outros manipuladores, se é que é mesmo registrado. Não passa de um excesso de design complicado.
Dunk

2

Penso que o problema com alguns dos padrões mais complexos é que existem tantas variações neles que perdem muito do seu valor como dispositivo de comunicação.

O pior infrator que consigo pensar nesta categoria é o padrão MVC. Mesmo se ignorarmos o MVP, há tantas variações nas funções de cada um desses itens que você precisará gastar uma hora em cada nova estrutura para descobrir onde estão os limites.


Eu também acho que o MVC deve ser usado em qualquer lugar, mas não deve ser implementado da mesma maneira em todos os lugares. E muitas pessoas não entendem isso. Quando eu quis usá-lo, criei três classes denominadas Model, View (um formulário do Windows) e Controller. Foi uma bagunça, pois os formulários não foram criados para o MVC.
Akku

1

Não existem padrões ruins, apenas pessoas ruins.

Prefiro herdar código facilmente legível que faz algo claro, mas é um pouco detalhado ou não (fila de músicas vilãs do mal) reutilizável (suspiro!) Do que um misto de mistura InheritAbstractTemplateFaucetSink<Kitchen>.

Código reutilizável é ótimo! Provavelmente, você não está escrevendo um código que será reutilizado ou reescrevendo uma lógica semelhante para outro aplicativo que levaria menos tempo do que uma tentativa insana de reutilizar o código de outro aplicativo.

Para uma leitura mais aprofundada, abra parte do código C nas implementações sãs dos cabeçalhos posix ou dos clibs e toque no padrão. Este código foi escrito por alguns dos programadores mais inteligentes e dedicados do mundo. Você sabe quantos padrões abstratos de fábrica você verá? ... NENHUM!. As chances são ainda melhores, se você entender as outras partes do que está acontecendo, encontrará a lógica muito fácil de entender e rastrear.

Meu argumento é que a maioria dos "padrões" não foram criados para melhorar o código, eles foram criados para vender livros e software de modelagem. Se você é bom em programação, provavelmente evitará a maioria deles e escreverá um código claro, conciso e inteligentemente projetado que resolve o seu problema. Quando você tiver outro problema, escreverá um código claro, conciso e inteligentemente projetado para resolver esse problema. Se seu objetivo é escrever menos código do que eu pensaria, você não seria um programador. Adoro escrever código e quero escrevê-lo o máximo possível. Quando reescrevo algo que já escrevi, faço isso dez vezes mais rápido e me livre de todas as coisas que não fiquei feliz com a primeira vez que fiz.

Com isso, deixarei você com provavelmente a melhor citação (relevante) em ciência da computação.

" Existem duas maneiras de construir um design de software: uma maneira é tornar tão simples que obviamente não há deficiências, e a outra maneira é torná-lo tão complicado que não há deficiências óbvias. O primeiro método é muito mais difícil. . "

  • Tony Hoare (inventor do quicksort, pai do design moderno do SO, criador da lógica Hoare e ganhador do prêmio Turing)

0

Definitivamente, concordo que existe um tempo para a maioria dos padrões e que você pode abusar de muitos padrões. Sei que o que mais abusou no passado é o padrão Abstract Template. Levado ao máximo, é conhecido como webforms do ASP.NET.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.