¿Cuánto esfuerzo debo invertir en crear diseños sueltos?

10

Actualmente estoy aprendiendo sobre patrones de diseño.

Creo que la mayoría de la gente estaría de acuerdo en que estos patrones son excelentes herramientas, pero deberían usarse con moderación y no como la respuesta para todo. Usarlos demasiado complicaría demasiado la aplicación con pocos beneficios. Los patrones deben usarse solo donde puedan ser la mejor solución o ayudar en la creación de una buena solución (¿está de acuerdo?).

Teniendo esto en cuenta:

El libro que estoy leyendo (Head First Design Patterns) con frecuencia enfatiza la importancia del acoplamiento suelto . Este acoplamiento flexible se logra siguiendo principios como "programa a una interfaz, no una implementación" y "encapsulan lo que varía".

Básicamente, la mayoría de los patrones que aprendí hasta ahora existen principalmente para permitir que los diseños se acoplen libremente y, por lo tanto, sean más flexibles.

Entiendo la importancia y los beneficios del acoplamiento suelto.

Pero mi pregunta es, ¿cuánto esfuerzo debería uno realmente invertir en crear diseños flexibles y poco acoplados?

Quienes se oponen a los patrones de diseño dicen que los costos de usar estos patrones a menudo superan los beneficios. Usted invierte mucho tiempo en crear un diseño débilmente acoplado utilizando algún patrón, en el que , en realidad, el acoplamiento flexible, 'programar en una interfaz, no una implementación', y todos estos principios, podrían no ser tan importantes.

Lo que me gustaría saber es cuánto esfuerzo debería poner en la creación de niveles adicionales de abstracción y diseños, solo para permitir que mi aplicación siga los principios de OO, como acoplamiento flojo, programación de programas a una interfaz, etc. ¿eso? ¿Cuánto esfuerzo debo poner en esto?

Aviv Cohn
fuente
Algunas personas ponen toda su vida en ello, Kent Beck, por ejemplo, las personas que lo aprecian verían su esfuerzo.
Niing

Respuestas:

14

Respuesta fatua: cuanto más lo haces, menos esfuerzo es.

Básicamente, construir código débilmente acoplado no es realmente muy difícil. Por otro lado, entrenar tu mente para pensar en términos de acoplamiento flojo. Y, bueno, creo que vale la pena.

Suponga que toma un trabajo que utiliza un enfoque iterativo para el desarrollo de software, como lo ha recomendado la mayoría de las personas en los últimos 20 años. Construye algo que funciona maravillosamente en la iteración 1. En la iteración 2 construye sobre él, agregando algunas características nuevas y doblando una o dos cosas un poco cuando no encajan en su concepto de iteración 1 de cómo deberían funcionar las cosas . Ahora viene la iteración 3, y descubres que los requisitos te exigen repensar tu arquitectura básica. ¿Cómo desgarras tu código y lo reconstruyes sin volver al punto de partida?

Esto pasa. Mucho. O hace que los proyectos se retrasen, o hace que todos estén demasiado asustados para hacer lo que hay que hacer en iteraciones posteriores. En el mejor de los casos, obtienes una Big Ball of Mud. Cosas como el acoplamiento flojo y el principio de responsabilidad única mitigan estos problemas a lo grande. Es por eso que los principios de SOLID son promocionados: realmente ayudan.

Y descubrirá que después de tener algunos diseños ligeramente acoplados en su haber, comienza a surgir naturalmente. Los patrones son cosas que la gente encontró que funcionaban para ellos, por lo que los documentaron. Son herramientas útiles que también vienen naturalmente con el tiempo.

Matthew Flynn
fuente
5

La cantidad de esfuerzo requerida no siempre le dirá lo suficiente; Creo que una mejor medida sería la relación esfuerzo-beneficio. Pero descubrir cuál podría ser la recompensa no siempre es sencillo y está libre de errores.

Lo que hay que tener en cuenta con los patrones que aumentan la flexibilidad es que cuesta un poco ponerlos, y a menos que pueda ver exactamente por qué los necesita, puede terminar teniendo la complicación en el código, pero nunca usarlo. Si la flexibilidad nunca se flexiona, bien podría no estar allí.

Hay una cosa que debe hacer siempre (o lo más cerca que pueda razonablemente): convertir los componentes individuales de su software (objetos para OOP, funciones para programación funcional o de procedimientos) en cajas negras. Una caja negra es algo cuyo interior (implementación) no conocemos ni nos importa.

Si no sabemos o no nos importa cómo funciona, entonces no vamos a intentar usar nada más que la interfaz, por lo que si la implementación cambia sin cambiar la interfaz, eso solo importa dentro del cuadro negro, nada fuera de él. puede ser afectado También hace que pensar en el programa sea más fácil, ya que no tiene que tener en mente todos los detalles de todo el programa. Cuantos más detalles pueda olvidar legítimamente, más espacio habrá en su cabeza para los detalles que importan.

Creo que has entendido mal las objeciones a los patrones de diseño; No soy fanático de ellos, pero me gusta mucho el principio de acoplamiento flojo y programación a una interfaz. Mi mayor objeción a ellos es que se presentan como una solución preempaquetada que no fomenta la comprensión de los principios detrás de ellos, sino que fomenta la memorización de detalles. No voy a recomendar que no los estudies, pero cuando lo hagas, recuerda que comprender los principios detrás de ellos es más importante que los detalles de cualquier patrón en particular.

Una de las objeciones a los patrones de diseño es que son 'obvios' o que 'los estaba usando antes de escucharlos, pero no por ese nombre'. La razón por la cual las personas pueden hacer esas objeciones, o los creadores de los patrones de diseño podrían presentarlas en primer lugar, es porque entendieron los principios detrás de ellas.

El uso de cajas negras organiza su código de una manera sensata y no suelen costar mucho (si es que hay algo); Úselos en todas partes. El uso de un patrón de diseño o alguna otra técnica que agrega una capa de abstracción o complica las cosas tiene un costo; nunca los use solo porque son bonitos, limpios o inteligentes; úselas cuando se ajusten al problema y vale la pena pagar el costo para obtener el beneficio.

Michael Shaw
fuente
4

Su pregunta parece equiparar el acoplamiento suelto con los patrones de diseño, pero están realmente separados, pero están relacionados.

El acoplamiento flojo es una preocupación fundamental en la programación. Tan pronto como nos alejamos del código de máquina y pasamos a lenguajes simbólicos, los programas se unieron libremente con su ejecución. Etc.

OO en sí mismo es básicamente un modelo para crear componentes sueltos. La encapsulación hace que las partes internas de los objetos se acoplen libremente con otros objetos. La programación funcional puede ser aún más importante, porque la ejecución de la función está unida libremente con la ejecución de otras funciones en extremo.

Casi por definición, cualquier diseño que haga implicará un acoplamiento suelto. Hay formas en que puede hacer arreglos para que las cosas se acoplen inadvertidamente, pero solo he visto algunos casos en los que alguien realmente diseñó un sistema para estar más estrechamente acoplado.

(De vez en cuando trabajo con alguien que quiere evitar que los futuros desarrolladores tomen decisiones de diseño al incorporar referencias estáticas a artefactos de marcos particulares, forzando su uso, a propósito. Pero esa es realmente la excepción. La mayoría del diseño gira en torno a romper las cosas por modularidad y reutilizar en muchos contextos).

Robar
fuente
3

Los patrones deben usarse solo donde puedan ser la mejor solución o ayudar en la creación de una buena solución (¿está de acuerdo?).

Veo patrones de diseño estrictamente como detalles de implementación. Si documenta sus API y programas públicos en esa documentación, en general no importará (o le afectará mucho) dónde tiene patrones de diseño. Es decir, usted no dice "Tengo un patrón de puente aquí e implementaré un visitante encima". En cambio, es "esta clase tendrá implementaciones diferentes en varios sistemas operativos, por lo que se implementará utilizando un patrón de puente". Luego, cuando lo usas, eres indiferente a que se implemente como un puente, porque miras la API pública, no un patrón de puente.

¿Cuánto esfuerzo debería uno invertir en crear diseños flexibles y poco acoplados?

El acoplamiento flojo se puede lograr siguiendo un conjunto simple de reglas. Si respeta estos, su código se acoplará (más) libremente, a medida que lo escriba (es decir, cualquier esfuerzo ya forma parte del proceso de desarrollo).

Entre las reglas (no una lista exhaustiva):

  • defina sus interfaces pensando (o escribiendo) el código del cliente (cómo se usará la clase), no lo que hará la clase (es decir, diseño de interfaz, no implementación)
  • "dile, no preguntes"
  • construir objetos a partir de partes ya creadas
  • Pase al constructor los objetos reales que usará (no fábricas para los miembros, parámetros para las fábricas de los parámetros, ni nada de eso).
  • SECO (si tiene dos líneas que aparecen en el mismo orden en dos lugares, extráigalas en una función separada y así sucesivamente).
  • Si la creación de un objeto es una operación más compleja, implemente la creación de las partes intermedias como un método / clase de fábrica (es decir, no en el cuerpo del constructor).
  • YAGNI (crea cosas como las necesites, no antes).

Estas reglas se siguen de manera diferente, según el lenguaje, la metodología de desarrollo seguida por su equipo (por ejemplo, TDD), las limitaciones de presupuesto de tiempo, etc.

Por ejemplo, en Java, es una buena práctica definir su interfaz como un interface código de cliente y escribir sobre eso (luego, instanciar la interfaz con una clase de implementación).

En C ++, por otro lado, no tiene interfaces, por lo que solo puede escribir la interfaz como una clase base abstracta; Dado que en C ++ solo usa la herencia cuando tiene un fuerte requisito para ello (y como tal evita la sobrecarga de funciones virtuales innecesarias), probablemente no definirá la interfaz por separado, solo el encabezado de la clase).

Quienes se oponen a los patrones de diseño dicen que los costos de usar estos patrones a menudo superan los beneficios.

Creo que lo están haciendo mal. Si escribe código débilmente acoplado (y SECO), la integración de patrones de diseño en él conlleva un esfuerzo adicional mínimo. De lo contrario, tendrá que adaptar su código para implementar un patrón de diseño.

Si tiene que hacer muchos cambios para implementar un patrón de diseño, su problema no es el patrón de diseño, sino que su código base es monolítico y está estrechamente acoplado. Este es un problema de diseño malo / subóptimo, no un problema de patrones de diseño.

Lo que me gustaría saber es cuánto esfuerzo debería poner en la creación de niveles adicionales de abstracción y diseños, solo para permitir que mi aplicación siga los principios de OO, como acoplamiento flojo, programación de programas a una interfaz, etc. ¿eso? ¿Cuánto esfuerzo debo poner en esto?

Sus preguntas hacen la suposición (no declarada) de que el único beneficio del acoplamiento flojo es la capacidad de implementar fácilmente patrones de diseño. No lo es.

Entre los beneficios del acoplamiento suelto están:

  • refactorización y rediseño de flexibilidad
  • menos esfuerzo desperdiciado
  • comprobabilidad
  • mayor posibilidad de reutilizar el código
  • simplicidad de diseño
  • menos tiempo en el depurador

... y algunos otros que no me vienen a la mente en este momento.

utnapistim
fuente