2008-10-30 47 views
19

¿Existen, en la lista canónica de Gang of Four, patrones de diseño que a menudo se consideran mal utilizados, incomprendidos o sobreutilizados (que no sean el altamente debatido Singleton)? En otras palabras, ¿hay un patrón de diseño que aconsejaría pensar dos veces antes de usarlo? (¿Y por qué?)Patrones de diseño incorrectos

+0

No creo que usted debe desalentar el uso de cualquiera de ellos (si se ajustan a la situación). Estos patrones están diseñados para resolver problemas comunes, debe informarles a aquellos que los implementan sobre los problemas antes de informarles que desalienten el uso de los patrones que resuelven los problemas. –

Respuesta

15

Patrones de fábrica ...

que se lanzó en paracaídas en un proyecto antes de que cada sola MyObject en el sistema tenía un equivalente MyObjectFactory para la generación de nuevos casos. No existía el concepto de abstracción o clases ampliadas ... simplemente viejo ClassX & ClassXFactory.

Y nadie podía explicar por qué ... "Fue simplemente las cosas como siempre se han hecho"

+0

A veces esto tiene que hacerse para facilitar la prueba del código incorrecto. Con las fábricas, su código de prueba puede simular cualquier fábrica y reemplazarla por sus propias fábricas, pero si va a hacerlo en ese sentido, ¿por qué no usar DI? –

+0

Exactamente. La vinculación estática a una fábrica no es mucho mejor que la vinculación estática a través del nuevo operador (excepto que hay al menos alguna posibilidad de reutilización de objetos). – kyoryu

4

En realidad, lo que veo con más frecuencia es la falta del uso de un patrón apropiado. Escenario típico: yo: "Oye, el módulo A ya tiene un fragmento de código que recorre un conjunto de objetos y realiza la operación de la base de datos X en ellos, ¿por qué no reutilizaste ese código?" codificador: "bueno, pero tuve que hacer la operación Y en esos objetos". Yo: "¿Qué pasa con el uso de refactorización para utilizar el patrón de comando para ejecutar X o Y, según corresponda?"

Una vez vi como el uso del patrón Subject-Observer se salía de control. Se implementó entre procesos que usan la base de datos para almacenar persistentemente el Sujeto. Debido a la gran cantidad de actualizaciones sobre el tema y el número de observadores, la carga en la base de datos fue enorme y causó una desaceleración imprevista en todo el sistema.

1

El patrón de observador es bastante inútil en C# porque tiene eventos.

+6

Los eventos de C# son una implementación del patrón de observador. – kenny

+0

No conozco los eventos en C#, pero seguramente la distinción entre lo que "es un patrón" y lo que "no es" depende del idioma. Piensa en el Iterador ... –

+1

Supongo que incluso la "llamada de rutina" podría considerarse como un "patrón de diseño", en la década de 1940 ... –

4

También diría que el patrón de fábrica. Experiencia similar a Eoin. En mi caso, el proyecto tenía toneladas de fábricas porque algunas personas pensaban que podrías haber usado el objeto A para una implementación local y el objeto B para el remoto y fue abstraído a través de una fábrica (lo cual es algo sensato que hacer).

Pero la implementación "remota" nunca se ha necesitado o implementado o incluso se prevé en el futuro ... y también, los ingenieros menos capacitados comenzaron a adoptar el patrón para muchas otras cosas como un cortador de galletas ...

+1

Caso clásico de 'YAGNI': ¡no vas a necesitarlo! –

17

el patrón Singleton .. estado global a menudo conduce a problemas al probar

Cualquier código dependiendo del Singleton se hace más difícil y más difícil de probar debido a que la dependencia no puede ser burlado fácilmente ..

+3

No solo las pruebas también son problemáticas cuando se hace concurrencia o en una aplicación donde tiene que restablecer completamente el estado de la aplicación (como juegos). –

+0

Todos están siempre odiando en el patrón de singleton. Me sorprende que esto no sea lo mejor de la lista. –

+0

A menudo les pregunto a las personas que quieren usar singletons si solo consideran utilizar una clase estática. Si dicen que no, les pregunto cómo usar un singleton es, prácticamente, diferente. Singletons debe ser sobre control de instanciación, no acceso global. – kyoryu

9

el único (además del mencionado Singleton y su socio en el crimen, th e Factory) no sería un GoF, sino que sería setters y getters cuando se aplica a las propiedades nativas de un objeto.

Los adaptadores y getters aplicados a las variables miembro son funcionalmente idénticos a las variables de miembros públicos. Un getter sin setter se parece más a una variable miembro pública final, pero en ese momento, ¿por qué no usar solo una variable pública miembro final? No hacen más daño ...

La única diferencia es que "podrías" interceptar la llamada y anularla, pero la gente rara vez lo hace. Más a menudo se usa como una muleta para los programadores de procedimientos para evitar la programación OO (que es la verdadera razón por la cual es un antipatrón).

Con un setter y/o getter todavía está exponiendo su estructura de miembro interna al mundo exterior (por ejemplo, tendrá que refactorizar otras clases si encuentra que necesita cambiar una int a una larga) y usted casi garantizan que algún código que debería estar dentro de su objeto se coloque afuera.

Hay algunas excepciones que se me ocurren:

Setter utilizados para simplificar una construcción de objetos. A veces es necesario crear un objeto y luego establecer otros valores después. Estos valores deben ser inmutables (no debe poder llamar al grupo dos veces) por seguridad.

Getters utilizados para acceder a los objetos contenidos. Dado que los objetos contenidos son usualmente capaces de asegurar su propia integridad, compartirlos es genial. En este caso, los incubadores generalmente son malos. No desea que un objeto con un estado específico intercambiado salga justo debajo de su nariz, hace que sea mucho más difícil asegurar su propia integridad.

Java Beans utilizados para los componentes de la pantalla: Sí, no se puede encontrar una mejor manera de implementar estas "bolas de propiedad". La reflexión es útil para este componente, los patrones son útiles; es un tanto hacky pero funciona.

DAO/DTO Bean objects. Honestamente, creo que estos son un uso dudoso del patrón, pero son el patrón. Hace que la manipulación de las propiedades a través de los metadatos en lugar del código sea mucho más difícil de lo que debería ser, ya que tiene que ser reflectante. Las propiedades de los beans siempre están ligadas a alguna fuente externa (formato de base de datos, formato de transferencia de datos, propiedades de componentes, ...) entonces, ¿por qué estamos duplicando el trabajo de definir cada parte?

Editar: Robado del comentario de kyoryu, apareció en la publicación porque es realmente un resumen perfecto de lo que estaba diciendo y podría perderse en los comentarios. Es necesario ya que no todo el mundo parece tener el concepto de que la adición de descriptores de acceso a la lengua sólo se codifica un mal patrón de diseño orientado a objetos:

corta Versión -

if (account1.balance > 1000) 
{ 
    account1.balance = account1.balance - 1000; 
    account2.balance = account2.balance + 1000; 
}; = BAD CODE. 

account2.deposit(account1.withdraw(1000)); = GOOD CODE. 

El segundo no requiere descriptores de acceso ... - Kyoryu (Ligeramente modificado por bill k porque tengo un poco más de espacio que en su comentario).

El segundo mueve la prueba y algunas otras operaciones matemáticas dentro de la cuenta en lugar de duplicarla en el código en cada lugar donde realice una transferencia.

Para más información, tenga en cuenta que con el estilo "BUEN CÓDIGO" es bastante obvio que la salida de .withdraw podría ser un objeto de transacción que contiene información sobre la transacción completa incluyendo su éxito, fuente y destino y habilidad de registro. ¿Cómo se le habría ocurrido esto a alguien que escribe su código en el estilo "BAD CODE"?

Además, ¿cómo podría refactorizar BAD CODE incluso para usar un objeto de este tipo? Es solo un desastre.

+1

Getters y setters, al igual que muchos otros patrones, son intentos de corregir una limitación del idioma. En este caso, propiedades. Muchos codificadores de Java chillan de miedo al ver una variable pública en otros idiomas. A menudo se olvidan de que en * saner * idiomas, si necesita agregar lógica al conjunto o obtener de esa variable, puede simplemente reemplazarlo con una propiedad del mismo nombre, en lugar de hacer una gran cantidad de 'getId()' y 'setId()' * por si acaso *. (Incluso VB6 tenía propiedades) – voyager

+2

En realidad, las propiedades son el problema tanto como getters y setters. La idea de OO es que le pidas a un objeto que haga algo por ti. ¿Dónde encaja un getter o setter en eso? Los getters o las propiedades de solo lectura no son realmente dañinos y se necesitan algunas veces (evítelos a menos que los necesite), pero los setters/propiedades de escritura son terribles. El mayor problema que tengo con las propiedades es que fomentan este mal comportamiento. Cuando absolutamente lo necesitas, son una sintaxis más agradable, pero tener propiedades integradas en el lenguaje anima a las personas a pensar que son una buena idea. –

+2

Exactamente lo que Bill K dijo. Versión corta - if (account.balance> 1000) {account.balance = account.balance - 1000; TransfertoMe (1000)}; = MAL CÓDIGO. cuenta.Withdraw (1000); = BUEN CÓDIGO. El segundo no requiere accesadores ... – kyoryu

2

El gran problema que veo es el patrón singleton en el que no se aplica el cuidado y la diligencia suficiente sobre cómo y cuándo debe llamarse al destructor de un singleton.

Para un patrón tan omnipresente, casi no hay discusión sobre el proceso adecuado para decidir cuándo debe morir un singleton.

Just my 0.02.

aplausos,

Rob

2

En realidad, yo diría que los patrones de diseño en general son usados ​​en exceso cuando un BESO ( Keep It Simple, Stupid que sea breve y simple) solución es todo lo que se necesita .

Los patrones de diseño son excelentes para hacer que un sistema sea flexible, pero a costa de hacer la implementación más compleja. Esto es solo una valiosa compensación cuando la flexibilidad proporcionará una ventaja práctica.

+0

En este caso, creo que KISS también podría significar "Keep It Stupid Stupid" – Nate

+0

Creo que esto solo es cierto cuando los patrones de diseño son poco conocidos ... – kyoryu

+1

(que, en para ser justos, es aproximadamente el 90% del tiempo en mi experiencia) – kyoryu

2

El patrón Mediator definitivamente tiene el potencial de ser mal utilizado si todo tipo de lógica se engloba en una gran clase.

0

Primero, "depende" del idioma: algunas estructuras en algunos idiomas disminuyen la necesidad de ciertos patrones de diseño.

Segundo, parte de la plantilla para el concepto de Design Pattern desde el principio ha incluido secciones para "Aplicabilidad" y "Consecuencias" - ignórelas bajo su propio riesgo. "Conocer" un patrón no solo significa que usted sabe cómo codificarlo en el idioma de su elección; también significa saber cuándo usarlo y qué inconvenientes puede tener.

3

ALL.

No me malinterpreten aquí, considero que son una base excelente y cuando se entienden bien, son muy útiles. Le cuesta tanto adquirir las habilidades de diseño para saber cuándo y cómo aplicarlas en el código. En realidad, ese es el caso general de las habilidades para crear código limpio.

No se trata de no usar entonces, es exactamente lo que dijiste en la pregunta "piensa dos veces antes de usar". Comprenda bien lo que está haciendo y por qué. Si no lo hace, hable con alguien que pueda aconsejarlo sobre eso, además de leer mucho. Tenga cuidado con los que conocen todos los patrones, pero no puede explicarle claramente el qué/por qué de ninguno de ellos, especialmente del que está en cuestión.

+2

Para mí, lo más importante es que los patrones de diseño son más útiles si los miras desde un modelo de programación ligeramente diferente al OO pseudo-procedimental "tradicional". El código escrito usando patrones de diseño debe parecerse mucho al código usando un modelo Actor, y si se escribe código usando un modelo tipo Actor, los patrones de diseño se tornan extremadamente pragmáticos y frecuentemente obvios. – kyoryu

+0

+1 Esta es la razón por la que se introdujeron los AntiPatterns. Un patrón de diseño utilizado en el contexto incorrecto se convierte en un AntiPattern, lo que significa que los inconvenientes superan los beneficios. – helpermethod

1

Solo quería añadir otro comentario después de ver algunas de las respuestas "Todos los patrones son malos".

Si usted es un programador medio decente que trabaja en problemas moderadamente desafiantes, casi todos los patrones deberían haberse presentado en un punto u otro como la solución "obvia" a un problema.

El único punto real del libro Design Patterns era poner nombres a lo que hacemos todos los días para poder comunicarnos mejor.

Supongo que si eres un programador novelesco, sería muy útil leerlos para que el día que necesites uno no tengas que resolverlo por tu cuenta, ya esté en tu caja de herramientas, pero en general: cualquiera de estos podría ser resuelto por un Gang of One (anyOne!).

Si hay alguno de estos que no conocía, probablemente nunca lo haya necesitado.

Es muy útil poner nombres a los patrones y formalizarlos un poco, no me quejo del libro en absoluto. Si no ves la necesidad ocasional de casi todos los patrones aquí, simplemente no estás trabajando en un código muy difícil (o duplicas mucho el código, algo que considero el pecado cardinal).

+0

Por supuesto que podría resolverlos usted mismo, pero tomaría un tiempo para descubrir todas las sutilezas y cuando se enfrenta con un problema similar, es posible que tenga que pasar por este proceso de nuevo. Pero generalmente estoy de acuerdo, no hay magia detrás de todo esto. Si eres un buen programador y tienes una comprensión decente de OOD, probablemente usarías Design Pattern sin saberlo. – helpermethod

0

Utilice solo un patrón cuando sea necesario.No se puede predecir el futuro, de modo que si bien se puede poner un patrón para hacer el diseño flexible, ¿qué sucede cuando el producto toma una dirección diferente y su patrón se convierte en lo que le impide implementar lo que sus usuarios quieren?

Mantenga los diseños lo más simple posible para empezar. Cuando sepa más acerca de cómo debe cambiar su diseño, use el patrón apropiado y no antes.

0

GUARDAMUEBLES PATRÓN

La mayoría de la gente comienza a usar este patrón correcto después de leer el libro Domain Driven Design de Eric Evans.

¿Cuántas personas aquí han visto repositorios construidos como objetos de acceso a datos?

0

No puede tener una respuesta directa para esta pregunta. Es principalmente subjetivo y depende de los requisitos de la aplicación.

  1. La mayoría de las personas citadas que Singleton_pattern es malo, pero no es malo para todos los usuarios y del proyecto. Para los requisitos de mi proyecto, sirve para el propósito. Necesito un ConnectionManager para gestionar la sesión entre el Cliente y la Aplicación y Singleton hace el trabajo de forma brillante.

  2. Usted ha dado un frasco de terceros con buena documentación. El contenedor contiene una jerarquía de herencia. Ahora tiene que agregar una operación en cada niño. Como no tienes el código fuente, no puedes hacerlo. Ahora puede beneficiarse al usar Visitor_pattern. Pero si tiene un código fuente, no puede usar el patrón Visitor. Puede agregar una operación nueva simple en el padre y cada hijo. La falta de código fuente no implica que estoy haciendo un uso indebido del patrón Visitor.

  3. Quiero limitar la comunicación entre varios objetos. Voy a continuar con implementar Mediator_pattern para la comunicación de objetos. Quiero limitar la exposición del cliente a mi sistema para ocultar la complejidad. Voy a seguir adelante con Facade_pattern. Eso no quiere decir que estoy usando mal estos patrones. Este mismo ejemplo se puede extender a otros patrones como Proxy_pattern etc.