¿Qué patrones de diseño son los peores o los más definidos? [cerrado]

28

Para cada proyecto de programación, los gerentes con experiencia previa en programación intentan brillar cuando recomiendan algunos patrones de diseño para su proyecto. Me gustan los patrones de diseño cuando tienen sentido o si necesita una solución escalable. He usado Proxies, Observadores y patrones de Comando de una manera positiva, por ejemplo, y lo hago todos los días. Pero dudo mucho en usar un patrón Factory si solo hay una forma de crear un objeto, ya que una fábrica podría facilitarlo en el futuro, pero complica el código y es pura sobrecarga.

Entonces, mi pregunta es con respecto a mi futura carrera y mi respuesta a los tipos de gerentes lanzando nombres de patrones aleatorios:

¿Qué patrones de diseño usaste que te devolvieron en general? ¿Cuáles son los peores patrones de diseño , los que debe considerar, excepto en la única situación en la que tienen sentido (léase: qué patrones de diseño están definidos de manera muy limitada)? (Es como si estuviera buscando las críticas negativas de un buen producto general de Amazon para ver qué es lo que más molestaba a las personas al usar patrones de diseño). Y no estoy hablando de Anti-Patterns aquí, sino de Patrones que generalmente se consideran como patrones "buenos".

Editar: Como algunos respondieron, el problema es que los patrones no son "malos" sino "mal utilizados". Si conoce patrones, que a menudo son mal utilizados o incluso difíciles de usar, también encajarían como respuesta.

Akku
fuente
La mayoría de los patrones facilitan el cambio futuro en algunos ejes de cambio, pero pueden hacer que los cambios sean más difíciles en otros ejes de cambio. La pandilla de los cuatro libros es particularmente buena para decir cuándo es aplicable un patrón. Muchos libros posteriores sobre patrones pierden este punto. Tome el patrón de visitante como ejemplo. Facilita la adición de nuevos algoritmos de recorrido del árbol, pero hace que sea más difícil agregar nuevos tipos de nodos al árbol. También permite que los algoritmos transversales estén en una capa más alta que el árbol. Debe considerar qué eje de cambio es el menos estable y diseñar para que los cambios a lo largo de ese eje sean fáciles.
Theodore Norvell
Todos los del libro 'Gang of Four'.
Miles Rout

Respuestas:

40

¡No creo en los malos patrones, creo que los patrones se pueden aplicar mal!

  • En mi humilde opinión, el singleton es el patrón más maltratado y más mal aplicado. Las personas parecen contraer una enfermedad singleton y comienzan a ver las posibilidades de los singletons en todas partes sin considerar alternativas.
  • El patrón de visitantes de la OMI tiene el uso más limitado y casi nunca se justificará la complejidad adicional. Un buen pdf se puede obtener aquí . Realmente solo cuando tiene una estructura de datos que sabe que se atravesará mientras realiza diferentes operaciones en la estructura de datos sin conocer todas las formas de antemano, brinde al patrón de visitante una oportunidad de lucha. Es bonito aunque :)

Para esta respuesta, solo consideré los patrones GOF. No conozco todos los patrones posibles lo suficientemente bien como para tenerlos en cuenta también.

KeesDijk
fuente
Veo muy pocos usos para los visitantes. Singletons ... no me hagas empezar. Si la situación no es perfecta para uno, no la use.
Michael K
1
Puede haber muy pocos usos para Visitor, pero cuando los hay, ciertamente resuelve problemas. Entiendo que Vistor es esencial para LINQ.
quentin-starin
12
El patrón Visitor es crítico para reducir (o eliminar) la complejidad ciclomática en un programa de software. Cada vez que tenga un árbol if / else o una declaración de cambio, las probabilidades de que un visitante pueda reemplazarlos son altas, ofreciendo ejecución garantizada y verificación en tiempo de compilación. El Visitor es uno de los patrones más poderosos que conozco, y lo usamos regularmente con gran efecto. Hace que probar también sea un sueño.
Les Hazlewood
@LesHazlewood ¿No es entonces el visitante solo una solución para los lenguajes de programación inadecuados? Los lenguajes de tipo ML (Haskell, SML, OCaml, etc.) tienen tipos de datos algebraicos ("unión con esteroides") y coincidencia de patrones ("encender esteroides") que producen un código más simple que el de Visitantes, pero que el compilador ha verificado completamente. En comparación con el visitante, no tiene muchos métodos cuyo estado compartido necesita administrar manualmente a través de las propiedades del objeto. En lenguajes tipo ML, y todas las distinciones de casos deben ser completas, de lo contrario no se compilará.
vog
14

Aparte de Singleton y Visitor ya mencionados por los otros respondedores, no conozco los patrones de diseño "notorios". En mi humilde opinión, los mayores problemas no se derivan de que un patrón de diseño específico sea "incorrecto", sino de que los desarrolladores aplican patrones con demasiada entusiasmo.

Casi todos pasan por la fase de "fiebre del patrón" cuando se familiarizan con los patrones. Pensando que los patrones son lo mejor desde el pan rebanado, inicialmente uno intenta aplicarlos cada vez que ve una posibilidad. Esto hace que el código quede enterrado bajo patrones, donde los patrones en sí mismos ya no ayudan, solo hacen que el código sea más difícil de entender y mantener a largo plazo.

Eventualmente, la mayoría de nosotros supera esta fase y comienza a aprender cómo usar los patrones para resolver problemas reales, no por su propio bien. Los patrones tienen su precio, que es una complejidad adicional, y la aplicación de cualquier patrón específico solo se justifica cuando se paga la complejidad adicional al ayudar a simplificar alguna otra parte del sistema, lo que hace que el código / configuración en general sea más fácil de entender y mantener. Si este no es el caso, a menudo es mejor mantenerse alejado de los patrones, apegándose a la solución más simple que podría funcionar.

Péter Török
fuente
Absolutamente. Los patrones no son buenos ni malos, están bien aplicados o mal aplicados.
Prefiero enseñar a la gente la forma en que aprendí: OO primero, entendiendo cómo se relacionan los objetos y luego aprendiendo los nombres de los patrones. Es demasiado fácil pensar en términos de patrones que lo que hay que hacer. Son una herramienta de comunicación.
Michael K
Los patrones son un medio para comunicarse, no una lista prescriptiva. Si comienza con un patrón en mente, puede estar aplicando mal. Si encuentra uno, o los indicios de uno, en su diseño, los catálogos de patrones pueden ayudarlo a comprender qué más puede necesitar.
Rob Crawford
14

Voy a arriesgarme aquí y sugerir el uso excesivo de la herencia. Definitivamente más aplicable en lenguajes sin soporte sólido de polimorfismo en tiempo de compilación, como Java. La herencia en tiempo de ejecución es una herramienta, no una especie de maravilla única.

Otras personas ya han expresado algo similar a mi odio personal hacia Singletons, por lo que no voy a ampliar eso aquí.

DeadMG
fuente
10

Semifallo. Es uno de los patrones GOF que ahora se llama con más frecuencia como antipatrón. Una de las razones es que Singleton hace que el código sea más difícil de probar.

SiberianGuy
fuente
44
Existen numerosos defectos fundamentales en el patrón de singleton, la mayoría están bien ilustrados en este artículo de Steve Yegge - Singleton Considerado Estúpido
ocodo
Slomojo: Buen artículo. Voy a llamarlo 'patrón simple' de ahora en adelante:-)
Nadie
2
Sí, debido a que un tonto hace un mal uso de un patrón y pierde por completo el tema de lo que se trata OO (a juzgar por todas las clases de Manager que se le ocurrió), por supuesto, es culpa del patrón y no de los desarrolladores.
Dunk
¿Por qué todos asocian la implementación común (y problemática) de Singleton con el patrón Singleton? Uno es casi siempre malo, el otro no.
quentin-starin
1
@qes> Singleton plantea problemas importantes de implementación (especialmente con subprocesos). Esto ya es un mal punto. Pero también descubrirá que singleton es un patrón sobre cómo se demanda a la clase y no cómo funciona. La forma en que se usa la clase debe ser manejada por el código que usa la clase, por lo que Singleton es una ruptura de la separación de preocupaciones.
deadalnix
7

Si conoce patrones, que a menudo son mal utilizados o incluso difíciles de usar, también encajarían como respuesta.

Seguir el patrón MVVM para WPF demasiado estrictamente, como se indica, por ejemplo, en esta pregunta . Algunas personas intentan seguir la directriz de que no se debe poner ningún código en el código demasiado estrictamente y crear todo tipo de hacks exóticos.

Y, por supuesto, MVVM es difícil como el infierno, y simplemente no vale la pena para pequeños proyectos a corto plazo.

El Dr. WPF hizo una publicación irónica al respecto en su artículo MV-poo .

Steven Jeuris
fuente
@ Akku: Por supuesto, debe saber cómo usarlo, para que pueda decidir si es adecuado para su proyecto. Entonces sí, es esencial para el desarrollo de WPF y muy útil.
Steven Jeuris
Uno de los problemas es que las personas no entienden el patrón MVVM. No es "difícil como el infierno". La gente lo hace de esa manera al pensar que todos los demás patrones, como el Patrón de comando y el Patrón de mediador, son parte de él. Por sí solo, MVVM es uno de los patrones más simples, en mi opinión. Estoy de acuerdo, que seguir cualquier cosa hasta el final es una tontería.
BK
5

Algunos de los patrones en el libro GOF son específicos de C ++, en el sentido de que son menos aplicables en lenguajes con reflexión, por ejemplo, el patrón Prototype es menos significativo en Java.

Considero que el patrón de intérprete es "estrecho". Debe tener un problema general que valga la pena desarrollar un solucionador de problemas generales. Solo funciona para problemas especiales para los que puede inventar un lenguaje, definir una gramática y escribir un intérprete. Las instancias del problema deben ser representables como una oración en la gramática. No creo que te encuentres con tales situaciones a menudo.

Karl
fuente
1
la mayor parte de GOF solo es aplicable a la POO basada en clases estáticas. alejarse muy ligeramente de ese tipo de idiomas y el libro se convierte en una anécdota de entretenimiento.
Javier
5

El que lamento con más frecuencia (aunque no con mucha vehemencia): cuando debería haber creado una función pero implementé una solución OOP.

C SD
fuente
1
¿Por qué? ¿Qué te hizo lamentarlo? Expande tu respuesta y agrega tu experiencia.
Walter
De hecho, creo que una clase con variables locales y métodos claros es MUCHO más fácil de reutilizar que una sola función de 200 líneas que solo se puede volver a aplicar a través de copiar y pegar y luego no solo tiene un lugar para verse feo y poco comprensivo.
Akku
2
KISS implica que primero debe ser una función, luego refactorizar a una clase si es necesario.
Eva
5

Fábrica. He visto implementar código que solo crea un tipo. Ese es un código completamente inútil IMO. No ayuda que muchos de los ejemplos en línea estén completamente ideados. Fábrica de pizza?

Quizás la fábrica sea más fácil de probar debido a la inyección de dependencia. Pero agregar ese código cuando no lo necesite no tiene sentido para mí, y el argumento de prueba desaparece cuando puede usar marcos simulados como JMockit. Cuanto más simple sea un programa, mejor. Las fábricas solo tienen sentido con un mayor número de tipos (por mayor, quiero decir al menos más de 2).

Michael K
fuente
Sí, fábrica de pizzas, gracias por Head First Design Pattern ~
Niing
2

Semifallo

Estoy de acuerdo con los demás sobre Singleton. No es que nunca deba usarlos, solo que debe limitarse a muy pocos casos. Se usan como globales perezosos la mayor parte del tiempo.

La seguridad de subprocesos es un problema con los singletons. El manejo de excepciones es otro: si el singleton no se crea correctamente, no siempre se sabe si puede detectar el error de manera segura, especialmente si fue uno de esos objetos creados "antes de main". Y luego está la cuestión de la limpieza posterior.

Tiendo a preferir usar un singleton y hacer que todos los demás "wannabe" singletons "se suscriban" al suyo. Mi uso más común de singleton es el manejo de "eventos de gritos": simplemente "transmites al mundo" que un evento ha tenido lugar y cualquiera que escuche que manejará el evento lo hace. De esa manera, desacoplas los eventos que realmente suceden con lo que los está escuchando. (Registro, señales, etc.)

Visitante

Lo feo que encuentro sobre esto, aparte del hecho de que los desarrolladores no pueden pensar en nombres significativos y simplemente llamar a los métodos visit (), es que agrega extensibilidad en una dirección mientras lo elimina en otra, es decir, agrega funcionalidad adicional pero restringe la cantidad de objetos que sus visitantes necesitan saber sobre todos los tipos de objetos que pueden visitar.

Es posible, aunque desordenado, permitir la extensión en ambas direcciones, pero esto no utiliza totalmente el patrón de visitante en su forma regular. La aplicación más común para esto es imprimir objetos: tiene diferentes formas de imprimir objetos y diferentes objetos que deben imprimirse. Debería poder extender esto en ambas direcciones. (Imprimir significa cualquier tipo de convertir objetos en una secuencia: almacenar en un archivo / escribir en una consola / GUI ... etc.).

(Nota: no debe confundir esto con la arquitectura de vista de documento, que es un patrón ligeramente diferente).

CashCow
fuente
2
Su solución utiliza el viejo argumento de desacoplamiento de las cosas. En particular, publicas un evento y otro tipo maneja el evento y lo registra. ¡Eso es bueno, porque todos están desacoplados! ¡INCORRECTO! Solía ​​hacer eso, qué dolor real se convirtió. Me di cuenta de que si quiero que se registre algo, quiero decir explícitamente que registre exactamente esto, aquí, ahora, en el código en el momento en que ocurrió. No tener ningún otro objeto que descubra qué se debe registrar, con otros posibles eventos intervenidos por otros controladores, si es que se registra. No es más que un diseño excesivamente complicado.
Dunk
2

Creo que el problema con algunos de los patrones más complejos es que hay tantas variaciones en ellos que pierden gran parte de su valor como dispositivo de comunicación.

El peor delincuente que se me ocurre en esta categoría es el patrón MVC. Incluso si ignoramos el MVP, hay tantas variaciones en los roles de cada uno de estos elementos que debe pasar una hora en cada nuevo marco para descubrir dónde se encuentran los límites.

Uri
fuente
También creo que MVC debería usarse en todas partes, pero no implementarse de la misma manera en todas partes. Y mucha gente no lo entiende. Cuando quise usarlo por primera vez, hice tres clases llamadas Modelo, Vista (un formulario de Windows) y Controlador. Fue un desastre, ya que no se hicieron formularios para MVC.
Akku
1

No hay malos patrones, solo malas personas.

Prefiero heredar un código fácil de leer que haga algo claro pero que sea un poco detallado o no (queue evil villian music) reutilizable (¡jadeo!) Que algunos mish mash InheritAbstractTemplateFaucetSink<Kitchen>.

¡El código reutilizable es genial! Lo más probable es que no esté escribiendo código que se reutilizará o volver a escribir una lógica similar para otra aplicación le tomaría menos tiempo que un intento loco de reutilizar el código de otra aplicación.

Para leer más, abra algunos de los códigos C en las implementaciones sensatas de los encabezados posix o los clibs y reproduzca el patrón. Este código fue escrito por algunos de los programadores más inteligentes y dedicados del mundo. ¿Sabes cuántos patrones abstractos de fábrica vas a ver? ... ¡NINGUNA!. Aún más posibilidades hay de que si comprende las otras partes de lo que está sucediendo, encontrará la lógica muy fácil de entender y rastrear.

Mi punto es que la mayoría de los "patrones" no se crearon para mejorar el código, se crearon para vender libros y software de modelado. Si eres bueno programando, probablemente evitarás la mayoría de estos y escribirás un código claro, conciso e inteligentemente diseñado que resuelva tu problema. Cuando tenga otro problema, escribirá un código claro, conciso y hábilmente diseñado para resolver ese problema. Si su objetivo es escribir menos código, creo que no está hecho para ser un programador. Me encanta escribir código y quiero escribirlo tanto como sea posible. Cuando reescribo algo que ya escribí, lo hago diez veces más rápido y me deshago de todas las cosas con las que no estaba contento la primera vez que lo hice.

Con eso te dejaré con probablemente la mejor cita (relevante) en informática.

" Hay dos formas de construir un diseño de software: una es hacerla tan simple que obviamente no haya deficiencias, y la otra es hacerla tan complicada que no haya deficiencias obvias. El primer método es mucho más difícil " .

  • Tony Hoare (inventor del quicksort, padre del diseño moderno del sistema operativo, creador de la lógica Hoare y ganador del premio Turing)
nsfyn55
fuente
0

Definitivamente estoy de acuerdo en que hay un momento para la mayoría de los patrones, y que puedes abusar de muchos patrones. Sé que el que más he abusado en el pasado es el patrón de plantilla abstracta. En su totalidad, se conoce como formularios web ASP.NET.

Wyatt Barnett
fuente