¿Es posible aplicar DRY sin aumentar el acoplamiento?

13

Supongamos que tenemos un módulo de software A que implementa una función F. Otro módulo B implementa la misma función que F '.

Hay varias formas de deshacerse del código duplicado:

  1. Deje que A use F 'de B.
  2. Deje que B use F de A
  3. Coloque F en su propio módulo C y deje que A y B lo usen.

Todas estas opciones generan dependencias adicionales entre los módulos. Aplican el principio DRY al costo de aumentar el acoplamiento.

Por lo que puedo ver, el acoplamiento siempre se incrementa o al arrendarlo se mueve a un nivel más alto cuando se aplica DRY. Parece que hay un conflicto entre dos de los principios más básicos del diseño de software.

(En realidad no me sorprende que haya conflictos de este tipo. Probablemente esto es lo que hace que el diseño de software sea tan difícil. Me parece sorprendente que estos conflictos no se aborden normalmente en los textos introductorios).

Editar (para aclarar): Supongo que la igualdad de F y F 'no es solo una coincidencia. Si F tendrá que ser modificado, F 'probablemente tendrá que ser modificado de la misma manera.

    
pregunta Frank Puffer 15.07.2018 - 19:18

5 respuestas

14
  

Todas estas opciones generan dependencias adicionales entre los módulos. Aplican el principio DRY al costo de aumentar el acoplamiento.

Por qué sí lo hacen. Pero disminuyen el acoplamiento entre líneas. Lo que obtienes es el poder de cambiar el acoplamiento. El acoplamiento viene en muchas formas. Extraer código aumenta la indirección y la abstracción. Aumentar eso puede ser bueno o malo. La cosa número uno que decide cuál obtienes es el nombre que usas para ello. Si mirar el nombre me deja sorprendido cuando miro adentro, entonces no le has hecho ningún favor a nadie.

Además, no sigas SECO en el vacío. Si elimina la duplicación, asumirá la responsabilidad de predecir que estos dos usos de ese código cambiarán juntos. Si es probable que cambien de forma independiente, ha causado confusión y trabajo adicional por poco beneficio. Pero un nombre realmente bueno puede hacer que sea más aceptable. Si todo lo que se te ocurre es un mal nombre, por favor, detente ahora.

El acoplamiento siempre existirá a menos que su sistema esté tan aislado que nadie sepa si funciona. Así que el acoplamiento de refactorización es un juego de elegir tu veneno. Seguir a DRY puede ser rentable al minimizar el acoplamiento creado al expresar la misma decisión de diseño una y otra vez en muchos lugares hasta que es muy difícil cambiarlo. Pero DRY puede hacer que sea imposible entender su código. La mejor manera de salvar esa situación es encontrar un nombre realmente bueno. Si no puede pensar en un buen nombre, espero que tenga experiencia en evitando nombres sin sentido

    
respondido por el candied_orange 15.07.2018 - 21:58
3

Hay formas de romper dependencias explícitas. Una popular es inyectar dependencias en tiempo de ejecución. De esta manera, obtiene DRY, retire el acoplamiento al costo de la seguridad estática. Es tan popular hoy en día, que la gente ni siquiera entiende, que eso es una compensación. Por ejemplo, los contenedores de aplicaciones rutinariamente proporcionan una gestión de dependencia que complica enormemente el software al ocultar la complejidad. Incluso la simple inyección del constructor anterior no garantiza algunos contratos debido a la falta de un sistema de tipos.

Para responder al título: sí, es posible, pero prepárese para las consecuencias del envío en tiempo de ejecución.

  • Defina la interfaz F A en A, proporcionando la funcionalidad de F
  • Defina la interfaz F B en B
  • Pon F en C
  • Cree el módulo D para administrar todas las dependencias (depende de A, B y C)
  • Adapte F a F A y F B en D
  • Inyectar (pasar) envoltorios a A y B

De esta manera, el único tipo de dependencias que tendría sería D dependiendo de cada otro módulo.

O bien, registre C en el contenedor de la aplicación con la inyección de dependencia incorporada y disfrute de la fortuna de la conexión automática de los bucles y puntos muertos de carga de clases en tiempo de ejecución.

    
respondido por el Basilevs 15.07.2018 - 21:30
1

No estoy seguro de que una respuesta sin más contexto tenga sentido.

¿ A ya depende de B o viceversa? - en cuyo caso podríamos tener una elección obvia de hogar para F .

¿ A y B ya comparten dependencias comunes que podrían ser un buen hogar para F ?

¿Qué tan grande / complejo es F ? ¿De qué otra cosa depende F ?

¿Se utilizan los módulos A y B en el mismo proyecto?

¿De todos modos, A y B terminarán compartiendo alguna dependencia común?

¿Qué sistema de lenguaje / módulo se está utilizando? ¿Qué tan doloroso es un módulo nuevo, en el dolor del programador, en la sobrecarga de rendimiento? Por ejemplo, si está escribiendo en C / C ++ con el sistema de módulos siendo COM, lo que causa problemas al código fuente, requiere herramientas alternativas, tiene implicaciones en la depuración y tiene implicaciones de rendimiento (para invocaciones entre módulos), podría toma una pausa seria.

Por otro lado, si está hablando de Java o C # DLL que se combinan perfectamente en un solo entorno de ejecución, ese es otro asunto.

Una función es una abstracción, y admite DRY.

Sin embargo, las buenas abstracciones deben estar completas; las abstracciones incompletas pueden muy bien provocar que el cliente consumidor (programador) compense el déficit utilizando el conocimiento de la implementación subyacente: esto resulta en un acoplamiento más estrecho que si se ofreciera la abstracción como más completa.

Por lo tanto, argumentaría buscar crear una mejor abstracción para que dependan A y B que simplemente mover una sola función a un nuevo módulo C .

Estaría buscando un conjunto de funciones para descubrir una nueva abstracción, es decir, podría esperar hasta que el código base esté más avanzado para identificar una refactorización de abstracción más completa / más completa que hacer. de uno basado en un solo código de función.

    
respondido por el Erik Eidt 15.07.2018 - 21:29
0

Las respuestas aquí que se enfocan en todas las formas en que puede "minimizar" este problema le están haciendo un mal servicio. Y las "soluciones" que simplemente ofrecen diferentes formas de crear un acoplamiento no son soluciones en absoluto.

La verdad es que no se comprende el problema que ha creado. El problema con su ejemplo no tiene nada que ver con DRY, sino (más ampliamente) con el diseño de la aplicación.

Pregúntese por qué los módulos A y B están separados si ambos dependen de la misma función F? Por supuesto, tendrá problemas con la administración de dependencias / abstracción / acoplamiento / you-name-it si se compromete con un diseño deficiente.

El modelado correcto de la aplicación se realiza de acuerdo con el comportamiento. Como tales, las piezas de A y B que dependen de F deben extraerse en su propio módulo independiente. Si esto no es posible, entonces A y B deben combinarse. En cualquier caso, A y B ya no son útiles para el sistema y deberían dejar de existir.

DRY es un principio que se puede usar para exponer un diseño deficiente, no para provocarlo. Si no puede lograr DRY ( cuando realmente se aplica, teniendo en cuenta su edición) debido a la estructura de su aplicación, es una clara señal de que la estructura se ha convertido en una responsabilidad. Es por esto que la “refactorización continua” también es un principio a seguir.

Los ABC de otros principios de diseño (SÓLIDO, SECO, etc.) que hay por ahí todos se utilizan para que cambiar (incluida la refactorización) sea una aplicación más sencilla. Enfóquese en eso , y todos los demás problemas comienzan a desaparecer.

    
respondido por el king-side-slide 16.07.2018 - 02:08
0
  

Todas estas opciones generan dependencias adicionales entre los módulos. Aplican el principio DRY al costo de aumentar el acoplamiento.

Tengo una opinión diferente, al menos para la tercera opción:

De su descripción:

  • A necesita F
  • B necesita F
  • Ni A ni B se necesitan.

Poner F en un módulo C no aumenta el acoplamiento ya que tanto A como B ya necesitan la función de C.

    
respondido por el mouviciel 24.07.2018 - 10:14

Lea otras preguntas en las etiquetas