Violación del principio DRY

10

Estoy seguro de que hay un nombre para este antipatrón en alguna parte; Sin embargo, no estoy lo suficientemente familiarizado con la literatura antipatrón como para saberlo.

Considere el siguiente escenario:

or0es una función miembro en una clase. Para bien o para mal, depende en gran medida de las variables de los miembros de la clase. El Programador A aparece y necesita funcionalidades como, or0pero en lugar de llamar or0, el Programador A copia y renombra a toda la clase. Supongo que no llama or0porque, como digo, depende en gran medida de las variables miembro para su funcionalidad. O tal vez es un programador junior y no sabe cómo llamarlo desde otro código. Así que ahora tenemos or0y c0(c para copiar). No puedo culpar por completo al Programador A por este enfoque: todos tenemos plazos ajustados y pirateamos el código para realizar el trabajo.

Varios programadores mantienen or0así que ahora es la versión orN. c0Ahora es la versión cN. Desafortunadamente, la mayoría de los programadores que mantuvieron la clase contenida or0parecían desconocer por completo, lo cual c0es uno de los argumentos más fuertes que puedo pensar sobre la sabiduría del principio DRY. Y también puede haber habido un mantenimiento independiente del código en c. De cualquier manera parece que or0y c0se mantuvieron independientes el uno del otro. Y, alegría y felicidad, está ocurriendo un error en el cNque no ocurre orN.

Entonces tengo algunas preguntas:

1.) ¿Hay un nombre para este antipatrón? He visto que esto sucede tan a menudo que me resulta difícil creer que este no sea un antipatrón con nombre.

2.) Puedo ver algunas alternativas:

a.) Arreglo orNpara tomar un parámetro que especifica los valores de todas las variables miembro que necesita. Luego modifique cNpara llamar orNcon todos los parámetros necesarios pasados.

b.) Intente portar manualmente arreglos de orNa cN. (Eso sí, no quiero hacer esto, pero es una posibilidad realista).

c.) Vuelva orNa cNcopiar a - de nuevo, qué asco, pero lo enumero por completo.

d.) Trate de averiguar dónde cNestá roto y luego repárelo independientemente orN.

La alternativa a parece ser la mejor solución a largo plazo, pero dudo que el cliente me permita implementarla. Nunca tiempo o dinero para arreglar las cosas bien, sino siempre tiempo y dinero para reparar el mismo problema 40 o 50 veces, ¿verdad?

¿Alguien puede sugerir otros enfoques que no haya considerado?

Onorio Catenacci
fuente
"¿Hay un nombre para este antipatrón?" ¿El anti-patrón 'violado-seco'? :) En mi humilde opinión, lo respondiste tú mismo.
Steven Jeuris
Tal vez lo llame "The Dry Violator"?
FrustratedWithFormsDesigner
2
Lo llamo: golpe seco.
AJC
55
Copiar y pegar codificación?
tylermac
Se llama el patrón "demasiados cocineros estropean el caldo".
Doc Brown

Respuestas:

18
  1. simplemente se llama código duplicado ; no conozco más nombres elegantes para esto. Las consecuencias a largo plazo son como las describió, y peores.

  2. Por supuesto, eliminar la duplicación es la opción ideal si solo es posible. Puede llevar mucho tiempo (en un caso reciente en nuestro proyecto heredado, tuve varios métodos duplicados en más de 20 subclases en una jerarquía de clases, muchos de los cuales habían crecido evolutivamente sus propias pequeñas diferencias / extensiones a lo largo de los años. aproximadamente 1,5 años a través de sucesivas pruebas de escritura y refactorización para eliminar todas las duplicaciones. Sin embargo, la perseverancia valió la pena).

    En tal caso, es posible que aún necesite una o más de las otras opciones como soluciones temporales, incluso si decide comenzar a eliminar la duplicación. Sin embargo, cuál de ellos es mejor depende de muchos factores, y sin más contexto, solo estamos adivinando.

    Muchas pequeñas mejoras pueden hacer una gran diferencia a largo plazo. Tampoco necesita necesariamente la aprobación explícita del cliente para esto: una pequeña refactorización cada vez que toca dicha clase para corregir un error o implementar una función puede ser muy útil con el tiempo. Simplemente incluya algo de tiempo extra para refactorizar en sus estimaciones de tareas. Es como el mantenimiento estándar para mantener el software saludable a largo plazo.

Péter Török
fuente
3
+1, si no solo por mencionar el código duplicado, sino por el gran esfuerzo involucrado en su historia de refactorización de código. : D
Andreas Johansson
9

Hay una referencia al patrón WET (We Enjoy Typing) pero no sé si es un nombre estándar.

... Las licencias de software son una notable excepción a la práctica DRY (no se repita): el código de licencia de software debe ser lo más MOJADO (disfrutamos escribiendo - lo opuesto a DRY) como sea posible.

Si aísla su lógica de licencias en un lugar, separado de otras preocupaciones, facilitará mucho más la modificación de su software para deshabilitar las licencias por completo. Es mucho mejor repetir la lógica de licencia muchas veces a lo largo de la aplicación, preferiblemente de tal manera que se ejecute varias veces en una sola ejecución del software.

Por ejemplo, le sugerimos que realice una verificación de licencia durante la instalación, durante el inicio de la aplicación y siempre que se acceda a funciones importantes. No verifique la licencia una vez durante el inicio y pase ese valor; en su lugar, replica la verificación de licencia en cada área. Es inconveniente, pero mucho mejor que lanzar un producto fácil de descifrar ...

jeremy-george
fuente
3
WET puede significar: Escribe todo dos veces
StuperUser
1
@StuperUser Descubrí eso en el dailywtf ayer ...
jeremy-george
3

Si te entiendo bien, hay demasiadas cosas en la clase. Eso crea métodos que no siguen el principio de responsabilidad única . Conduce a un código que necesita ser movido, piezas tomadas mientras que otras quedan fuera. Esto también podría crear muchos miembros.

También debe revisar los modificadores de accesibilidad. Asegúrese de que las cosas que son públicas, de hecho deben ser públicas El consumidor no necesita saber acerca de cada pequeño miembro ... use la encapsulación.

Esto requiere un refactor. También parece que el código se está escribiendo sin un diseño inicial. Examina el desarrollo impulsado por pruebas. Escriba el código como debería llamarse en lugar de llamarlo, sin embargo, está implementado. Busque en TDD algunos consejos sobre cómo realizar la tarea.

P.Brian.Mackey
fuente
3

Si está copiando código, presentará una deuda técnica de doble mantenimiento o más específicamente: duplicación de código .

Por lo general, esto se soluciona mediante la refactorización. Más específicamente, redirige todas las llamadas a una nueva función (o un nuevo método en una nueva clase) que tiene el código común. La forma más fácil de comenzar es eliminar todo el código copiado y ver qué interrupciones, en las que arregla redirigiendo las llamadas al código común.

Hacer que su cliente acepte refactorizar el código puede ser difícil, ya que es difícil convencer a una persona no técnica para que repare una deuda técnica. Entonces, la próxima vez que proporcione estimaciones de tiempo, solo incluya el tiempo que toma refactorizar sus estimaciones . La mayoría de las veces los clientes asumen que está limpiando el código durante el tiempo que hace la corrección.

Spoike
fuente
1

A mí me parece un código de espagueti . La mejor solución es refactorizar / reescribir.

un término peyorativo para el código fuente que tiene una estructura de control compleja y enredada, especialmente una que usa muchos GOTO, excepciones, hilos u otras construcciones de ramificación "no estructuradas". Se llama así porque el flujo del programa es conceptualmente como un tazón de espagueti, es decir, retorcido y enredado ...

http://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Spaghetti.jpg/175px-Spaghetti.jpg

Tom Squires
fuente
-1 Refactorizar y reescribir son dos opciones muy diferentes. Las reescrituras totales, descartando software, nunca son una buena idea. joelonsoftware.com/articles/fog0000000069.html
P.Brian.Mackey
1
El código de espagueti es IMO, un término mucho más general y más suelto. Aunque dicho código a menudo contiene duplicaciones, puede tener código de espagueti sin duplicación, y también código altamente duplicado pero no espagueti.
Péter Török
@ P.Brian.Mackey Nunca dije que Refactor y reescribir fueran lo mismo. OP debería decidir cuál usar.
Tom Squires
2
Nunca fui fanático de ese artículo. Estoy de acuerdo en que la reescritura fue una mala idea en el ejemplo citado, pero solo porque fuera una mala idea en ese caso no significa que siempre sea una mala idea. Para empezar, ¿la reescritura bloqueará algún otro progreso? Si es así, eso es malo; si no, bueno, eso no es tan malo.
jhocking
@jhocking: creo que el objetivo de la política de no reescritura no es bloquear el progreso en otros programas, sino la pérdida de soluciones reales con el tiempo. Ese mágico "if (goldenNugget> 22)" aunque mal nombrado, aún resuelve un problema específico que puede ser imposible de identificar sin horas o días de investigación. Ahora, tomar esos mismos datos y mejorarlos es lo que debería hacerse en su lugar. Eso es un refactor. Tirarlo y decir "lo haremos bien la próxima vez" es una pérdida de tiempo. La misma razón para resolver problemas ya resueltos es una pérdida de tiempo. La adición de un buen código en la parte superior de las malas aumenta la deuda
P.Brian.Mackey
0

Dices que no puedes culpar por completo a A, pero copiar una clase de esta manera es realmente imperdonable. Es una falla masiva en su proceso de revisión de código. Es posiblemente la falla más masiva, ya que no tiene ninguna revisión de código.

SI alguna vez piensa que tiene que producir un código horrible para cumplir con una fecha límite, entonces la solicitud de máxima prioridad absoluta para el lanzamiento después de eso debería ser arreglar el código horrible AHORA. Entonces su problema se ha ido.

El principio DRY es para situaciones que no son del todo perfectas y pueden mejorarse. Duplicar una clase es un calibre completamente nuevo. Primero lo llamaría "código duplicado", y con el tiempo cambiará a lo peor de todos los desperdicios de tiempo, "código duplicado divergente": múltiples copias del mismo código que son casi idénticas, pero no del todo idénticas, y nadie sabe si Las diferencias son intencionadas, coincidencia o errores.

gnasher729
fuente
-3

Casi una década tarde a esta fiesta, pero el nombre de este antipatrón es Cambio Divergente , donde varias clases incluyen copias del mismo comportamiento, pero a medida que el tiempo y el mantenimiento avanzan y algunas clases se olvidan, esos comportamientos divergen.

Dependiendo de cuál sea el comportamiento compartido y cómo se comparte, podría llamarse Cirugía de escopeta , la diferencia es que aquí muchas características proporcionan una única característica lógica en lugar de una sola.

doOOooonkeyKoooOOOooong
fuente
1
Esto no se parece a lo mismo. El cambio divergente es cuando se realizan muchos cambios en la misma clase. El OP describe la duplicación de código. La cirugía de escopeta tampoco es lo mismo. La cirugía de escopeta describe el mismo cambio realizado en varias clases diferentes.
Robert Harvey