¿Cuáles son los puntos clave de trabajar eficazmente con código heredado? [cerrado]

133

He visto algunas veces el libro Trabajar eficazmente con código heredado recomendado. ¿Cuáles son los puntos clave de este libro?

¿Hay mucho más para lidiar con el código heredado que agregar pruebas de unidad / integración y luego refactorizar?

Armand
fuente
2
Por supuesto, el punto es agregar pruebas y luego refactorizar. El libro trata en gran medida de cómo logras obtener un código increíblemente complicado bajo prueba, y hay muchas revelaciones sobre ese punto. ¡Digamos que Plumas no toma prisioneros!
Kilian Foth
99
Tal vez deberías leer el libro
HLGEM
Buena revisión aquí: andreaangella.com/2014/03/…
rohancragg

Respuestas:

157

El problema clave con el código heredado es que no tiene pruebas. Por lo tanto, debe agregar algunos (y luego más ...).

Esto en sí mismo requeriría mucho trabajo, como señaló @mattnz. Pero el problema especial del código heredado es que nunca fue diseñado para ser comprobable . Por lo tanto, generalmente es un gran lío enrevesado de código de espagueti, donde es muy difícil o francamente imposible aislar piezas pequeñas para realizar pruebas unitarias. Entonces, antes de las pruebas unitarias, debe refactorizar el código para que sea más comprobable.

Sin embargo, para refactorizar de manera segura, debe realizar pruebas unitarias para verificar que no haya roto nada con sus cambios ... Esta es la trampa 22 del código heredado.

El libro le enseña cómo salir de esta trampa haciendo los cambios mínimos y más seguros al código solo para habilitar las primeras pruebas unitarias. No se pretende que el diseño sea más agradable, solo para permitir pruebas unitarias. De hecho, a veces hacen que el diseño sea más feo o más complejo. Sin embargo, le permiten escribir pruebas, y una vez que tenga las pruebas unitarias en su lugar, tiene la libertad de mejorar el diseño.

Hay muchos trucos para hacer que el código sea comprobable: algunos son obvios, otros no. Hay métodos que nunca hubiera pensado en mí, sin leer el libro. Pero lo que es aún más importante es que Feathers explica lo que precisamente hace que una unidad de código sea comprobable. Necesita cortar dependencias e introducir barreras en su código, pero por dos razones distintas:

  • detección : para verificar y verificar los efectos de ejecutar un fragmento de código, y
  • separación : en primer lugar, para obtener el fragmento de código específico en un arnés de prueba.

Cortar dependencias de forma segura puede ser complicado. Introducir interfaces, simulacros e Inyección de dependencias es un objetivo limpio y agradable, pero no es necesariamente seguro hacerlo en este momento. Entonces, a veces tenemos que recurrir a la subclase de la clase bajo prueba para anular algún método que normalmente, por ejemplo, iniciar una solicitud directa a un DB. Otras veces, incluso podríamos necesitar reemplazar una clase / jar de dependencia con una falsa en el entorno de prueba ...

Para mí, el concepto más importante introducido por Feathers son las costuras . Una costura es un lugar en el código donde puede cambiar el comportamiento de su programa sin modificar el código en sí . La construcción de costuras en su código permite separar el fragmento de código que se está probando, pero también le permite detectar el comportamiento del código que se está probando incluso cuando es difícil o imposible hacerlo directamente (por ejemplo, porque la llamada realiza cambios en otro objeto o subsistema , cuyo estado no es posible consultar directamente desde el método de prueba).

Este conocimiento le permite notar las semillas de la capacidad de prueba en el montón de código más desagradable, y encontrar los cambios mínimos, menos disruptivos y más seguros para llegar allí. En otras palabras, para evitar hacer refactorizaciones "obvias" que tienen un riesgo de romper el código sin que lo notes - ya que ni aún tiene las pruebas de unidad para detectar eso.

Péter Török
fuente
55
Tenga en cuenta que cuando la respuesta anterior dice "pruebas unitarias" , de hecho significa "pruebas automatizadas" . Para una aplicación heredada, una gran fracción de las pruebas automatizadas inicialmente útiles serán de hecho pruebas de integración (donde la lógica de prueba ejecuta una losa más grande del código general y puede producir fallas debido a defectos en muchos lugares diferentes), en lugar de la unidad verdadera pruebas (que tienen como objetivo analizar solo un módulo y ejecutar porciones mucho más pequeñas del código cada una).
Lutz Prechelt
99

Formas rápidas de obtener los puntos clave de trabajar eficazmente con código heredado

MarkJ
fuente
3
El enlace de MP3 en esa página de Hanselminutes está roto, pero el de hanselminutes.com/165/… no lo está: s3.amazonaws.com/hanselminutes/hanselminutes_0165.mp3 .
Peter Mortensen
Gracias rosston por arreglar el enlace PDF. Parece que objectmentor.com se ha ido, ¿tal vez el "Tío Bob" cerró?
MarkJ
No estoy seguro de lo que le pasó al mentor de objetos, pero en estos días el tío Bob trabaja para 7th Light.
Jules
40

Trabajo en una base de código de millones de líneas de código, algunas que datan de la década de 1980. Es solo software, por lo que es solo cuestión de escribir algunas pruebas unitarias, para que pueda ir y refactorizarlo, y hacerlo mucho mejor.

La palabra clave aquí es simplemente: es una palabra de cuatro letras que no pertenece al vocabulario de ningún programador, y mucho menos a una persona que está trabajando en sistemas heredados.

¿Cuánto tiempo cree que toma escribir una prueba unitaria, para probar una hora de esfuerzo de desarrollo? Por el bien de la discusión, digamos otra hora.

¿Cuánto tiempo se invierte en ese sistema heredado de hace 20 millones de líneas? Digamos, 20 desarrolladores durante 20 años por 2000 horas / año (trabajaron bastante duro). Ahora escojamos un número: tienes nuevas computadoras y nuevas herramientas, y eres mucho más inteligente que los muchachos que escribieron esta pieza de $% ^^ en primer lugar, digamos que vales 10 de ellas. ¿Tienes 40 años hombre, bueno, tienes ...?

Entonces la respuesta a su pregunta es que hay mucho, mucho más. Por ejemplo, esa rutina de 1000 líneas (tengo algunas que son más de 5000), es demasiado compleja y es una pieza de espagueti. Solo tomaría (un par de palabras de cuatro letras más) un par de días re-factorizarlo en unas pocas rutinas de 100 líneas y unos pocos ayudantes de 20 líneas más, ¿verdad? INCORRECTO. Oculto en esas 1000 líneas hay 100 correcciones de errores, cada una un requisito de usuario indocumentado o un oscuro caso marginal. Son 1000 líneas porque la rutina original de 100 líneas no hizo el trabajo.

Debe trabajar con la mentalidad " si no está roto, no lo arregle ". Cuando está roto, debe tener mucho cuidado al arreglarlo, a medida que lo mejora, para que no cambie accidentalmente otra cosa. Tenga en cuenta que "roto" puede incluir código que no se puede mantener, pero que funciona correctamente, eso depende del sistema y su uso. Pregunte "qué sucede si lo arruino y lo empeoro", porque un día lo harás, y tendrás que decirle al jefe de los jefes por qué elegiste hacer eso.

Estos sistemas siempre se pueden mejorar. Tendrá un presupuesto para trabajar, una línea de tiempo, lo que sea. Si no lo haces, ve y haz uno. Deje de mejorarlo cuando el dinero / tiempo se haya agotado. Agregue una función, dese tiempo para mejorarla un poco. Solucione un error, nuevamente, dedique un poco de tiempo extra y mejore. Nunca lo entregue peor de lo que era cuando comenzó.

Mattnz
fuente
2
¡Gracias por los consejos! ¿Son tuyos o del libro?
Armand
3
Probablemente un poco de ambos: leí el libro después de unos años de hacer este trabajo, y probablemente debería leerlo de nuevo. Al igual que cualquier buen libro, lo hará desafiar algo de lo que está haciendo actualmente, reforzar la mayoría de lo que hace, pero no tiene todas las respuestas para su conjunto específico de problemas.
mattnz
77
"Son 1000 líneas porque la rutina original de 100 líneas no hizo el trabajo". Muy raramente parece ser este el caso. La mayoría de las veces son 1,000 líneas simplemente porque el desarrollador original se arremangó y comenzó a codificar antes de ahorrar un momento para la planificación o el diseño.
Stephen Touset
3
No. Estoy diciendo que en la mayoría de los casos (personalmente me he encontrado), las rutinas de 1,000 líneas son indicaciones claras de que las personas comenzaron a escribir código antes de pensar en cómo escribir una abstracción adecuada. Las rutinas de mil líneas son, por definición, demasiado complicadas: ¿está diciendo que una rutina de mil líneas con cientos de correcciones de errores ocultas y sin comentar es el sello distintivo de un desarrollador responsable?
Stephen Touset el
16
Si creyó en cada publicación en este sitio, todos tienen que lidiar con el código de 1000 líneas de espagueti, sin embargo, nadie lo escribió. En mi experiencia, las rutinas de línea de 1000 (y 10000) son el sello distintivo de los desarrolladores que están haciendo lo mejor que pueden con lo que tienen, para entregar lo que el jefe les paga. Encuentro insultante y arrogante la forma en que muchos desarrolladores se sienten libres de comentar desde un segundo plano sin conocer las circunstancias, sin tener que exponer su propio trabajo a la comunidad para que lo critiquen.
mattnz
19

Hay dos puntos clave para quitar del libro.

  1. El código heredado es cualquier código que no tiene cobertura de prueba.
  2. Siempre que tenga que cambiar el código heredado, debe asegurarse de que tenga cobertura.

Como han señalado otros respondedores, tratar de actualizar de forma preventiva su código heredado existente es una tontería . En cambio, cada vez que tenga que hacer un cambio en el código heredado (para una nueva función o una corrección de errores), tómese el tiempo para eliminar su estado heredado.

Michael Brown
fuente
66
+1 Excelente punto: "Siempre que tenga que hacer un cambio en el código heredado, tómese el tiempo para eliminar su estado heredado".
John
3
Eliminando el estado Legacy, consigue mi voto :)
Rachel
7

En pocas palabras, eso es cierto: agregar pruebas y refactorizar es de lo que se trata.

Pero el libro le ofrece muchas técnicas diferentes para hacerlo con código que es muy difícil de probar y refactorizar de forma segura.

Oded
fuente