Elegir el patrón de diseño correcto

32

Siempre he reconocido la importancia de utilizar patrones de diseño. Tengo curiosidad por saber cómo otros desarrolladores eligen el más adecuado. ¿Utiliza una serie de características (como un diagrama de flujo) para ayudarlo a decidir?

Por ejemplo:

Si los objetos están relacionados, pero no queremos especificar una clase concreta, considere Resumen

Cuando se deja la instanciación a clases derivadas, considere Factory

Necesita acceder a elementos de un objeto agregado secuencialmente, intente Iterator

¿o algo similar?

Carl Sagan
fuente
8
¿Cuál crees que es la importancia? programmers.stackexchange.com/questions/70877/…
pdr
Creo que la importancia está en la capacidad de reconocer el patrón más apropiado y holístico, para poder comunicarlo a otros desarrolladores. ¿Si eso tiene sentido?
Carl Sagan
Estoy de acuerdo con @pdr. Pienso en lo que necesito hacer, y recordar el nombre del patrón me ayuda a nombrar la Clase para que otros sepan lo que hace también.
Amy Blankenship
44
En efecto. Esto podría resumirse simplemente en "¿Cómo se elige el diseño correcto?". Primero, no hay un diseño correcto , solo muchos incorrectos. Más allá de eso, viene con experiencia en pilas (elegir las incorrectas).
Telastyn

Respuestas:

109

Una idea errónea clave en el mundo de la codificación actual es que los patrones son bloques de construcción. Toma un AbstractFactoryaquí y un Flyweightallá y quizás un Singletonallá y los conecta con XML y listo, tiene una aplicación que funciona.

Ellos no están.

Hmm, eso no fue lo suficientemente grande.

Los patrones no son bloques de construcción

Eso es mejor.

Un patrón es algo que usa cuando descubre que tiene un problema: necesita cierta flexibilidad que proporciona el patrón o que se ha tropezado cuando está haciendo un pequeño lenguaje en el archivo de configuración y dice "espera un momento, detente, este es su propio intérprete que estoy escribiendo: este es un problema conocido y resuelto, usa un patrón de intérprete ".

Pero tenga en cuenta que es algo que descubre en su código, no algo con lo que comienza. Los creadores de Java no dijeron "Oh, pondremos un Flyweight en el número entero" al principio, sino que se dieron cuenta de un problema de rendimiento que podría resolver un flyweight .

Y por lo tanto, no hay un "diagrama de flujo" que use para encontrar el patrón correcto. El patrón es una solución a un tipo específico de problema que se ha encontrado una y otra vez y las partes clave del mismo se destilaron en un Patrón.

Comenzar con el Patrón es como tener una solución y buscar un problema. Esto es algo malo: conduce a una ingeniería excesiva y, en última instancia, a la inflexibilidad en el diseño.

Mientras escribe el código, cuando se da cuenta de que está escribiendo una Fábrica, puede decir "¡ah, es una fábrica que estoy a punto de escribir" y usar su conocimiento de conocer el patrón de Fábrica para escribir rápidamente el siguiente fragmento de código sin intentar redescubrir el patrón Factory. Pero no comienzas con "Tengo una clase aquí, escribiré una fábrica para que sea flexible", porque no lo hará.

Aquí hay un extracto de una entrevista con Erich Gamma (de Gamma, Helm, Johnson y Vissides ): Cómo usar patrones de diseño :

Intentar usar todos los patrones es algo malo, porque terminarás con diseños sintéticos, diseños especulativos que tienen una flexibilidad que nadie necesita. En estos días el software es demasiado complejo. No podemos permitirnos especular qué más debería hacer. Necesitamos centrarnos realmente en lo que necesita. Por eso me gusta refactorizar los patrones. Las personas deben aprender que cuando tienen un tipo particular de problema u olor a código, como lo llaman en estos días, pueden ir a su caja de herramientas de patrones para encontrar una solución.


La mejor ayuda para el "qué usar, cuándo" es probablemente la página de Wikipedia para el patrón de diseño de software : la sección "Clasificación y lista" describe la categoría en la que se encuentra cada patrón y qué hace. No hay diagrama de flujo; la descripción allí es probablemente la mejor que encontrará como un breve fragmento de "qué usar, cuándo".

Tenga en cuenta que encontrará diferentes patrones en diferentes áreas de programación. El diseño web tiene su propio conjunto de patrones, mientras que JEE (no el diseño web) tiene otro conjunto de patrones. Los patrones para la programación financiera son completamente diferentes a los del diseño de interfaz de usuario de aplicaciones independientes.

Por lo tanto, cualquier intento de enumerarlos a todos es inherentemente incompleto. Usted encuentra uno, descubre cómo usarlo y luego eventualmente se convierte en una segunda naturaleza y no necesita pensar cómo o cuándo volver a usarlo (hasta que alguien le pida que se lo explique).

Robert Harvey
fuente
11
+1 para "solución en busca de un problema". Conocer los patrones le permitirá omitir el descubrimiento natural de ellos cuando resulte que necesita resolver un problema que ellos resuelven. Aprender sobre ellos probablemente ayudará a mejorar sus habilidades de codificación y diseño, de la misma manera que leer el código de otras personas o aprender otro lenguaje de programación. Pero definitivamente no deberías intentar activamente "ajustar patrones" a tu código.
gregmac
1
Siempre recomiendo a los desarrolladores que empiecen a mirar patrones para familiarizarse primero con los principios de diseño. Cada patrón es una ilustración de algunos de los principios del diseño (el conjunto de principios 'SOLIDOS' es solo un ejemplo).
ryscl
2
Tal vez agregue un decorador y una fachada para tener una aplicación ;-) Dicho de otra manera, el objetivo de los patrones de diseño es darnos un nombre, un lenguaje común al discutir lo que estamos construyendo. Es la abreviatura de una pila de conocimientos de desarrollo ganados con esfuerzo.
EBarr
2
Leyendo entre las líneas aquí, los pasos para elegir un patrón de diseño: 1. Siempre piense críticamente en cualquier código en el que esté trabajando. 2. Resuma el código específico en un problema base 3. ¿Ese problema tiene una solución conocida (patrón de diseño )? 4. Sí, ¿cómo aplico esa solución a mis detalles? 5. Adapte la solución genérica al problema abstracto, para crear una solución a su problema específico.
Chris
@Chris que realmente lo resume. Tampoco hay nada de malo en escribirlo sin patrones y luego refactorizar el código en el patrón apropiado si el diseño lo necesita.
18

Me pregunto:

  1. ¿Qué problema estoy tratando de resolver?
  2. ¿Qué patrón de diseño de software (si lo hay) resuelve más de cerca el mismo problema o proporciona una ruta lógica para resolver mi problema?
  3. ¿Necesito la abstracción adicional (y la complejidad) que proporciona el patrón, o es una ingeniería excesiva para mi problema particular? ¿Se puede resolver el problema de una manera más simple y eficiente sin el patrón?

El proceso de elegir un patrón de software no es diferente al proceso de elegir una estructura de datos, excepto que al elegir una estructura de datos, evaluaría el rendimiento y las características de la memoria de su problema, y ​​elegiría la estructura de datos que más se ajuste a esas características.

Robert Harvey
fuente
Por supuesto, eso es algo sobre experiencia y experiencia, en lugar de un plano o diagrama de flujo, y estoy de acuerdo con usted. Pero debe haber algún uso de recursos completos, como una hoja de trucos avanzada en la que se ha categorizado, al menos en el caso de los patrones más importantes y frecuentes como la fábrica, etc. Estoy buscando una de las situaciones recomendadas más conocidas en cuál sería mejor usar un patrón. ¿Conoces ese recurso en Internet?
Pmpr
3
@Trix: sourcemaking.com/design_patterns
Robert Harvey