Hay mucha información sobre herramientas y técnicas para mejorar las bases de código heredadas, pero no he encontrado ningún caso de éxito en el mundo real. La mayoría de los consejos son a nivel micro y, aunque son útiles, no convencen a muchas personas debido a la falta de evidencia, pueden ayudar a nivel macro.
Estoy buscando específicamente mejoras incrementales que hayan demostrado ser un éxito en el mundo real al actualizar una gran base de código heredada para cumplir con los estándares de calidad actuales, y no una reescritura completa.
Antes de:
- Grande: mayor que 1MLOC
- Legado: sin pruebas automatizadas
- Mala calidad: alta complejidad, alto acoplamiento, defectos de alto escape
Después
- Pruebas automatizadas
- Actualizaciones / mantenimiento más fáciles
- Alta calidad: complejidad reducida, código desacoplado, pocos defectos escapados
¿Qué tipo de pasos incrementales se han probado en el mundo real para actualizar una gran base de código heredada con éxito para cumplir con los estándares de calidad superiores, sin tener que realizar una reescritura total?
Si es posible, incluya un ejemplo de empresa o estudio de caso de un gran proyecto heredado que haya pasado por un proceso de mejora de calidad "exitoso" en su respuesta para respaldarlo.
fuente
Respuestas:
Libros como http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052 deberían ser testigos suficientes de cuán grandes y antiguas bases de códigos de mala calidad son comunes en la industria.
Supongo por qué no has escuchado o visto, y, lo que es más importante, es probable que nunca escuches sobre ellos hasta que trabajes en uno de ellos, es que nadie parece capaz por varias razones, salir limpio y decir que su código base fue todo lo anterior sin enfrentar repercusiones no triviales.
Esto podría explicar la escasez de estudios de los que hablas. Si lee suficientes libros, por ejemplo, Deep C Secrets de Peter van der Linden, leerá acerca de errores de millones de dólares en los que faltará la parte sobre qué proyecto los tenía.
NOTA: Quería hacer este comentario, pero fue demasiado largo. Entiendo que esto no responde la pregunta completamente.
EDITAR: C ++ 11 y se cuestiona la viabilidad a largo plazo de GCC : si los desarrolladores refactorizan GCC y lo hacen más útil como LLVM / clang, podría ser un buen ejemplo. La discusión señala que la documentación es deficiente en algunos lugares, lo que aumenta la barrera de entrada para los nuevos desarrolladores.
fuente
El 3 de febrero de 2013, Michael Meeks, uno de los desarrolladores de LibreOffice, dará una charla en un par de días titulada "LibreOffice: limpiar y refactorizar una base de código gigante, o por qué reescribirlo sería aún peor ". Suena exactamente como lo que está pidiendo: una discusión sobre lo que han hecho para tomar "una base de código gigantesca y poco entendida, ampliamente comentada en alemán, sin pruebas unitarias, una infraestructura de construcción enredada y veinticinco años de deuda técnica no pagada "y modernizarla.
La presentación se puede transmitir en línea y (creo) las grabaciones estarán disponibles en una fecha futura.
fuente
De hecho, he pasado por una refactorización bastante significativa tres veces en mi carrera. El código tiene una tendencia a la descomposición, por lo que si su base de código es lo suficientemente larga, un refactor grande es casi inevitable. Todos mis ejemplos estaban en bases de códigos privados, lo que podría explicar por qué los ejemplos públicos son difíciles de encontrar.
La primera vez fue una aplicación que, lo creas o no, tenía una arquitectura fundamental que hacía que solo funcionara con impresoras matriciales. Cuando mi empresa ya no pudo encontrar un proveedor para suministrar las cintas, me asignaron que funcionara con una impresora láser.
La segunda vez fue una migración de varios cientos de scripts de prueba automatizados de C a Java, en parte porque necesitábamos una mejor capacidad multiplataforma, y en parte porque era difícil contratar nuevos desarrolladores de C.
La tercera vez todavía estoy en el medio, que está modularizando una gran aplicación monolítica para permitir pruebas unitarias al reducir el acoplamiento y para propósitos de plataforma cruzada.
Comparo el esfuerzo de escalar una montaña. Tienes este gran objetivo por delante, pero no lo abordas a nivel macro. Se toma una mano a la vez, siempre con una posición de retroceso cercana, nunca desconectando el seguro anterior hasta que el siguiente esté en su lugar. Empiezas solo haciendo pequeñas mejoras incrementales, y después de un tiempo te das la vuelta y de repente hay esta hermosa vista.
Digamos que tiene 60,000 archivos de código altamente acoplado, por ejemplo. Desea comenzar a ponerlo bajo prueba unitaria, pero las dependencias lo hacen imposible. Como lo arreglas? Desacoplas un archivo. Agrega pruebas automatizadas. Regresas a terreno estable antes de continuar. Repite 59,999 veces.
Si eso suena simple, es porque es simple. No es fácil, pero es simple. Es difícil notar algún progreso al principio. Llevamos dos años en lo que parecía un refactor imposible, y es probable que tengamos años por delante hasta que hayamos terminado, pero al mirar hacia atrás, de repente nos damos cuenta de cuánto mejor ha mejorado el código y hemos podido continuar ofreciendo nuevas funciones. a nuestros clientes mientras tanto.
Las otras dos veces funcionaron de la misma manera. Usted encuentra el paso seguro más pequeño que puede tomar, y lo toma, siempre manteniendo la aplicación en funcionamiento. Solo te preocupas por el panorama general para asegurarte de que vas en la dirección correcta. Todas sus acciones son pequeñas, constantes e incrementales.
fuente
Por experiencia personal trabajando en una base de código de línea multimillonaria, he encontrado algunas estrategias que parecen funcionar.
Mire todos los errores (incluso los cerrados) e intente dividirlos en categorías. Específicamente para tratar de desglosarlos por el componente al que pertenecen. Si pertenecen a más de un componente, tenga en cuenta que lo hacen. Una vez que hayas hecho esto, mira qué cubo es el más grande y úsalo para determinar por dónde comenzar. Además, puede consultar el historial de revisiones de los archivos para determinar qué cambios son los más utilizados y usarlo como guía de dónde comenzar. Básicamente, lo que está tratando de hacer es encontrar lo que está más roto, arreglar eso y repetir. Además, descubrí que tratar de arreglar todo al mismo tiempo nunca funciona, solo causa más problemas.
Si encuentra que hay muchas cosas que pertenecen a múltiples componentes, eso es una indicación de problemas del "sistema" y puede apuntar a un código que está demasiado estrechamente acoplado o una API que necesita actualizarse.
Otra área en la que he pasado mucho tiempo es probar la base de código existente. Aquí hay múltiples estrategias y todas tienen mérito, pero nadie es una solución completa al problema.
fuente