Mucha gente parece estar de acuerdo en que el patrón Singleton tiene una serie de inconvenientes y algunos incluso sugieren evitar el patrón por completo. Aquí hay una excelente discusión . Dirija cualquier comentario sobre el patrón Singleton a esa pregunta.
Mi pregunta : ¿Existen otros patrones de diseño que deberían evitarse o usarse con mucho cuidado?
design-patterns
anti-patterns
Brian Rasmussen
fuente
fuente
Respuestas:
Los patrones son complejos
Todos los patrones de diseño deben usarse con cuidado. En mi opinión , debería refactorizar hacia patrones cuando hay una razón válida para hacerlo en lugar de implementar un patrón de inmediato. El problema general con el uso de patrones es que agregan complejidad. El uso excesivo de patrones hace que una aplicación o un sistema determinados sean difíciles de desarrollar y mantener.
La mayoría de las veces, existe una solución simple y no es necesario aplicar ningún patrón específico. Una buena regla general es usar un patrón siempre que los fragmentos de código tiendan a ser reemplazados o necesiten cambiarse con frecuencia y estar preparado para asumir la advertencia del código complejo al usar un patrón.
Recuerde que su objetivo debe ser la simplicidad y emplear un patrón si ve una necesidad práctica de admitir cambios en su código.
Principios sobre patrones
Puede parecer discutible usar patrones si evidentemente pueden conducir a soluciones complejas y sobre-diseñadas. Sin embargo, es mucho más interesante para un programador leer sobre técnicas y principios de diseño que sientan las bases para la mayoría de los patrones. De hecho, uno de mis libros favoritos sobre 'patrones de diseño' enfatiza esto al reiterar qué principios son aplicables al patrón en cuestión. Son lo suficientemente simples como para ser útiles que los patrones en términos de relevancia. Algunos de los principios son lo suficientemente generales como para abarcar más que la programación orientada a objetos (OOP), como el principio de sustitución de Liskov , siempre que pueda construir módulos de su código.
Hay una multitud de principios de diseño, pero los descritos en el primer capítulo del libro GoF son bastante útiles para empezar.
Deje que esos se hundan en usted por un tiempo. Cabe señalar que cuando se escribió GoF, una interfaz significa cualquier cosa que sea una abstracción (que también significa superclases), que no debe confundirse con la interfaz como un tipo en Java o C #. El segundo principio proviene del uso excesivo observado de la herencia que, lamentablemente, todavía es común en la actualidad .
A partir de ahí, puede leer sobre los principios SOLID que dio a conocer Robert Cecil Martin (también conocido como el tío Bob) . Scott Hanselman entrevistó al tío Bob en un podcast sobre estos principios :
Estos principios son un buen comienzo para leer y discutir con sus compañeros. Puede encontrar que los principios se entrelazan entre sí y con otros procesos, como la separación de preocupaciones y la inyección de dependencia . Después de hacer TDD por un tiempo, también puede encontrar que estos principios surgen naturalmente en la práctica, ya que necesita seguirlos hasta cierto punto para crear pruebas unitarias aisladas y repetibles .
fuente
El que más preocupaba a los autores de Design Patterns era el patrón "Visitante".
Es un "mal necesario", pero a menudo se usa en exceso y la necesidad a menudo revela un defecto más fundamental en su diseño.
Un nombre alternativo para el patrón "Visitante" es "Despacho múltiple", porque el patrón Visitante es con lo que termina cuando desea utilizar un lenguaje OO de despacho de un solo tipo para seleccionar el código que se utilizará según el tipo de dos (o más) objetos diferentes.
El ejemplo clásico es que tienes la intersección entre dos formas, pero hay un caso aún más simple que a menudo se pasa por alto: comparar la igualdad de dos objetos heterogéneos.
De todos modos, a menudo terminas con algo como esto:
El problema con esto es que ha acoplado todas sus implementaciones de "IShape". Ha insinuado que siempre que desee agregar una nueva forma a la jerarquía, también deberá cambiar todas las demás implementaciones de "Forma".
A veces, este es el diseño mínimo correcto, pero piénselo bien. ¿Su diseño realmente exige que se envíe en dos tipos? ¿Estás dispuesto a escribir cada una de las explosiones combinatorias de múltiples métodos?
A menudo, al introducir otro concepto, puede reducir la cantidad de combinaciones que realmente tendrá que escribir:
Por supuesto, depende, a veces realmente necesitas escribir código para manejar todos esos casos diferentes, pero vale la pena hacer una pausa y pensar antes de dar el paso y usar Visitor. Podría ahorrarte mucho dolor más adelante.
fuente
Singletons: una clase que usa singleton X tiene una dependencia que es difícil de ver y difícil de aislar para las pruebas.
Se utilizan con mucha frecuencia porque son convenientes y fáciles de entender, pero realmente pueden complicar las pruebas.
Ver Los solteros son mentirosos patológicos .
fuente
Creo que el patrón del método de plantilla generalmente es un patrón muy peligroso.
fuente
No creo que debas evitar Design Patterns (DP), y no creo que debas forzarte a usar DP al planificar tu arquitectura. Solo deberíamos usar DP cuando surjan naturalmente de nuestra planificación.
Si definimos desde el principio que queremos utilizar un DP determinado, muchas de nuestras futuras decisiones de diseño estarán influenciadas por esa elección, sin garantía de que el DP que elegimos se adapte a nuestras necesidades.
Una cosa que tampoco deberíamos hacer es tratar a un DP como una entidad inmutable, deberíamos adaptar el patrón a nuestras necesidades.
Entonces, resumiendo, no creo que debamos evitar los DP, deberíamos adoptarlos cuando ya están tomando forma en nuestra arquitectura.
fuente
Creo que Active Record es un patrón sobreutilizado que fomenta la mezcla de la lógica empresarial con el código de persistencia. No hace un buen trabajo al ocultar la implementación de almacenamiento de la capa del modelo y vincula los modelos a una base de datos. Hay muchas alternativas (descritas en PoEAA) como Table Data Gateway, Row Data Gateway y Data Mapper que a menudo brindan una mejor solución y ciertamente ayudan a proporcionar una mejor abstracción del almacenamiento. Además, su modelo no debería necesitar almacenarse en una base de datos; ¿Qué hay de almacenarlos como XML o acceder a ellos mediante servicios web? ¿Qué tan fácil sería cambiar el mecanismo de almacenamiento de sus modelos?
Dicho esto, Active Record no siempre es malo y es perfecto para aplicaciones más simples donde las otras opciones serían excesivas.
fuente
Es simple ... evite Patrones de Diseño que no le sean claros o con los que no se sienta cómodo .
Por nombrar algunos ...
hay algunos patrones poco prácticos , como por ejemplo:
Interpreter
Flyweight
también hay algunos más difíciles de entender , como por ejemplo:
Abstract Factory
- El patrón de fábrica abstracto completo con familias de objetos creados no es tan fácil como parece serBridge
- Puede volverse demasiado abstracto, si la abstracción y la implementación se dividen en subárboles, pero es un patrón muy útil en algunos casosVisitor
- La comprensión del mecanismo de doble despacho es realmente imprescindibley hay algunos patrones que parecen terriblemente simples , pero que no son una elección tan clara debido a varias razones relacionadas con su principio o implementación:
Singleton
- patrón no del todo malo, simplemente usado demasiado (a menudo allí, donde no es adecuado)Observer
- gran patrón ... solo hace que el código sea mucho más difícil de leer y depurarPrototype
- El compilador de operaciones comprueba el dinamismo (que puede ser bueno o malo ... depende)Chain of responsibility
- con demasiada frecuencia solo se empuja de manera forzada / artificial en el diseñoPara aquellos "poco prácticos", uno realmente debería pensar en ellos antes de usarlos, porque generalmente hay una solución más elegante en alguna parte.
Para los "más difíciles de entender" ... realmente son de gran ayuda, cuando se usan en lugares adecuados y cuando se implementan bien ... pero son una pesadilla, cuando se usan incorrectamente.
Ahora, que sigue ...
fuente
Espero que no me golpeen demasiado por esto. Christer Ericsson escribió dos artículos ( uno , dos ) sobre el tema de los patrones de diseño en su blog de detección de colisiones en tiempo real . Su tono es bastante duro, y quizás un poco provocativo, pero el hombre sabe lo que hace, así que no lo descartaría como desvaríos de un lunático.
fuente
Algunos dicen que el localizador de servicios es un anti patrón.
fuente
Creo que el patrón del observador tiene mucho por lo que responder, funciona en casos muy generales, pero a medida que los sistemas se vuelven más complejos, se convierte en una pesadilla, necesita notificaciones OnBefore (), OnAfter () y, a menudo, la publicación de tareas asincrónicas para evitar que se repita. fascinación. Una solución mucho mejor es desarrollar un sistema de análisis de dependencia automático que instrumente todos los accesos a objetos (con barreras de lectura) durante los cálculos y crea automáticamente un borde en un gráfico de dependencia.
fuente
Un complemento de la publicación de Spoike, Refactoring to Patterns es una buena lectura.
fuente
El iterador es un patrón de GoF más que se debe evitar, o al menos usarlo solo cuando no hay ninguna alternativa disponible.
Las alternativas son:
para cada bucle. Esta construcción está presente en la mayoría de los lenguajes convencionales y puede usarse para evitar iteradores en la mayoría de los casos.
selectores a la LINQ o jQuery. Deben usarse cuando para cada uno no sea apropiado porque no todos los objetos del contenedor deben procesarse. A diferencia de los iteradores, los selectores permiten manifestar en un lugar qué tipo de objetos se van a procesar.
fuente
yield
iterador. Eric White tiene una gran discusión sobre esto en C # 3.0: blogs.msdn.com/b/ericwhite/archive/2006/10/04/… . Además, consulte la discusión de Jeremy Likness sobre corrutinas con iteradores: wintellect.com/CS/blogs/jlikness/archive/2010/03/23/… .