Cambié una firma de método y ahora tengo más de 25,000 errores. ¿Ahora que?

166

Comencé un nuevo trabajo recientemente en el que estoy trabajando en una aplicación muy grande (15M loc). En mi trabajo anterior teníamos una aplicación de gran tamaño similar, pero (para bien o para mal) utilizamos OSGi, lo que significa que la aplicación se dividió en muchos microservicios que se podían cambiar, compilar e implementar de forma independiente. La nueva aplicación es solo una base de código grande, con quizás un par de .dlls.

Así que necesito cambiar la interfaz de esta clase, porque eso es lo que mi jefe me pidió que hiciera. Inicialmente lo escribieron con algunas suposiciones que no se generalizaron demasiado, y durante un tiempo han estado evitando el problema de la refactorización porque está muy estrechamente relacionado. Cambié la interfaz y ahora hay más de 25000 errores. Algunos de los errores están en clases con nombres importantes como "XYZPriceCalculator", que realmente no debe interrumpir. Pero no puedo iniciar la aplicación para comprobar si funciona hasta que se resuelvan todos los errores. Y muchas de las pruebas unitarias hacen referencia directa a esa interfaz o están acopladas a clases base que hacen referencia a esa interfaz, por lo que corregirlas es una tarea bastante grande en sí misma. Además, realmente no sé cómo encajan todas estas piezas, así que incluso si pudiera hacer que empiece, realmente no sé cómo se vería si las cosas se rompieran.

Nunca tuve un problema como este en mi último trabajo. ¿Qué hago?

    
pregunta user788497 04.11.2016 - 03:01
fuente

9 respuestas

349

25000 errores básicamente significa "no tocar eso". Vuelve a cambiarlo. Cree una nueva clase que tenga la interfaz deseada y mueva lentamente a los consumidores de la clase a la nueva. Dependiendo del idioma, puedes marcar la clase antigua como obsoleta, lo que puede causar todo tipo de advertencias del compilador, pero en realidad no romperá tu compilación.

Lamentablemente, estas cosas suceden en bases de código antiguas. No hay mucho que puedas hacer al respecto, excepto hacer las cosas lentamente. Cuando cree las nuevas clases, asegúrese de probarlas correctamente y de crearlas usando los principios de SOLID para que sean más fáciles de cambiar en el futuro.

    
respondido por el Stephen 04.11.2016 - 03:35
fuente
80

Divide y conquista con refactorizaciones

A menudo, dividir el cambio que necesita hacer en pasos más pequeños puede ayudar porque luego puede realizar la mayoría de los pasos más pequeños de una manera que no rompa el software en absoluto. Las herramientas de refactorización ayudan mucho con estas tareas.

Divide

Primero, identifique los cambios más pequeños posibles (en términos de cambios lógicos, no en términos de LoC cambiado) que se sumen al cambio que desea lograr. Especialmente intente aislar los pasos que son refactorizaciones puras y se pueden llevar a cabo mediante herramientas.

Conquistar

Para casos complicados como el suyo, puede tener sentido realizar una pequeña refactorización a la vez y luego dejar que el problema descanse, de modo que todos los sistemas de integración continua puedan verificar el cambio, y quizás el equipo de pruebas también lo haya revisado. Esto valida los pasos que haces.

Para llevar a cabo una refactorización en particular, necesita absolutamente un soporte de herramientas para un caso en el que tenga 25,000 sitios de llamadas del método que desea cambiar. Tal vez la búsqueda y reemplazo también funciona, pero para un caso tan crítico, eso me asustaría.

Ejemplo

En C #, por ejemplo, es posible usar Resharper para cambie la firma de un método. Si el cambio es lo suficientemente simple, por ej. agregando un nuevo parámetro, luego puede especificar qué valor se debe usar en los sitios de llamadas que de otra manera tendrían un error de compilación.

Entonces, se encuentra inmediatamente en una base de código libre de errores y puede ejecutar todas las pruebas de unidad, que pasarán, porque solo fue una refactorización.

Una vez que la firma del método se ve bien, puede ir y reemplazar los valores que Resharper agregó como argumentos al parámetro recién introducido. Esto ya no es una refactorización , pero tiene una base de código libre de errores y puede ejecutar las pruebas después de cada línea que cambie.

A veces eso no funciona

Este es un enfoque muy útil para casos como el suyo, donde tiene muchos sitios de llamadas. Y ahora tiene un software que funciona, por lo que puede ser posible realizar pequeños pasos de refactorización para cambiar la firma solo un poco y luego realizar otra.

Lamentablemente, no funcionará si el cambio de firma es demasiado complejo y no se puede dividir en cambios más pequeños. Pero esto es raro; dividir el problema en problemas más pequeños por lo general muestra que es posible .

    
respondido por el theDmi 04.11.2016 - 08:37
fuente
36

Aclare su tarea con su jefe para ayudarlo a comprender el problema y sus necesidades como desarrollador de software profesional.

Si eres parte de un equipo, busca al desarrollador principal y pídele consejos.

Buena suerte.

    
respondido por el mmehl 04.11.2016 - 08:53
fuente
28

No lo toques. No cometas nada.

En cambio, siéntate en tu silla y grita "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ tan fuerte como puedas

Bueno, no exactamente así, pero pida consejo a cualquiera de sus colegas principales. Si tiene 25,000 errores, no corrige los errores, arregla lo que causó los errores. Y un colega sénior debería poder aconsejarte cómo para hacer el cambio que tu jefe desea sin los 25,000 errores involucrados. Hay varias formas de hacerlo, pero lo que es bueno depende de su situación específica.

Y podría ser que el jefe les haya dicho a sus colegas mayores que hagan el mismo cambio y dijeron "no". Porque sabían lo que pasaría. Por eso te dieron el trabajo.

    
respondido por el gnasher729 04.11.2016 - 10:02
fuente
22

Las API incrustadas no se pueden cambiar simplemente. Si realmente necesita cambiarlos, anote y / o documéntelos como obsoletos (por cualquier medio que permita el idioma) y documente qué API se debe usar en su lugar. La antigua API puede ser eliminada lentamente ... quizás muy lentamente dependiendo de su presupuesto de tiempo para la refactorización.

    
respondido por el Kevin Krumwiede 04.11.2016 - 03:29
fuente
10

Evaluate

Evalúe si este cambio es necesario o si puede agregar un nuevo método y dejar de usar el otro.

Hacia adelante

Si es necesario cambiar; entonces es necesario un plan de migración.

El primer paso es introducir el nuevo método y hacer que el antiguo método dé masajes a sus argumentos para que pueda llamar al nuevo. Esto puede requerir la codificación de algunas cosas; eso está bien.

Este es un punto de confirmación: verifique que todas las pruebas pasen, confirmen, empujen.

Emigrar

El trabajo ocupado está migrando todos los llamadores del método antiguo al nuevo. Afortunadamente, se puede hacer gradualmente gracias al promotor.

Así que adelante; no dude en usar herramientas para ayudar ( sed es la más básica, hay otras).

Marque el método antiguo como obsoleto (con un indicio de cambiar al método nuevo); le ayudará a detectar si olvidó algo y le ayudará si un compañero de trabajo introduce una llamada al método anterior mientras está trabajando en esto.

Este es un punto de confirmación (o tal vez varios puntos de confirmación): verifique que todas las pruebas pasen, confirmen, empujen.

Retirar

Después de que haya pasado algún tiempo (quizás tan solo un día), simplemente elimine el método anterior.

    
respondido por el Matthieu M. 04.11.2016 - 10:46
fuente
8

Si su cambio a la firma del método es simplemente un cambio de nombre, la solución simple es utilizar herramientas para automatizar el cambio en las 25,000 clases que hacen referencia al método en cuestión.

Supongo que simplemente ha editado el código manualmente, lo que dio lugar a todos los errores. También asumo que está familiarizado con Java (al ver su referencia a OSGi), así que, por ejemplo, en Eclipse (no sé qué entorno de programación usa, pero otros entornos tienen herramientas de refactorización similares) puede usar "Refactoring - > Rename "para actualizar todas las referencias al método, lo que debería dejarlo sin errores.

En caso de que esté realizando otros cambios en la firma del método que simplemente cambiando el nombre (cambiando el número o los tipos de parámetros), puede usar "Refactorización - > Cambiar la firma del método". Sin embargo, es probable que tenga que ser más cuidadoso, como sugieren las otras respuestas. Además, independientemente del tipo de cambio, todavía puede ser una tarea bastante complicada realizar todos esos cambios en una base de código ocupada.

    
respondido por el MikkelRJ 04.11.2016 - 10:16
fuente
6

Aquí mi contribución.

  

Comencé un nuevo trabajo recientemente en el que estoy trabajando en una gran empresa   Aplicación (15M líneas de código).

Probablemente no esté familiarizado con el proyecto y sus "características". Antes de escribir una sola línea de código, es importante estar familiarizado con el proyecto. Así que restaure sus cambios y comience por analizar el código . (Al menos el afectado)

Comprender la solución existente te brinda una mejor perspectiva de dónde te estás metiendo. Contextualice la solución y su importancia.

Como señaló @Greg, debería poder probar el código existente para tener una referencia válida para comparar con (pruebas de regresión). Su solución debe ser capaz de generar los mismos resultados que la existente. En esta etapa, no te importa si los resultados son correctos . El primer objetivo es refactorizar, no corregir errores. Si la solución existente dice "2 + 2 = 42", su solución también debería hacerlo. Si no lanza excepciones, el suyo tampoco debería hacerlo. Si devuelve nulos, el tuyo también debería devolver nulos. Y así. De lo contrario, estarás comprometiendo 25k líneas de código.

Esto es en aras de la compatibilidad retroactiva

¿Por qué? Porque en este momento, es su garantía única de un refactor exitoso.

  

Y muchas de las pruebas unitarias hacen referencia directa a esa interfaz,   o están acoplados a clases base que hacen referencia a esa interfaz.

Necesitamos con urgencia una forma de garantizar la compatibilidad retro. Aquí está su primer desafío. Aislar el componente para la prueba de la unidad.

Tenga en cuenta que esas 25k líneas de código se crearon asumiendo los posibles resultados del código existente. Si no rompe esta parte del contrato, está a medio camino de llegar a la solución final. Si lo haces, bueno: que la fuerza te acompañe

Una vez que haya diseñado e implementado el nuevo "contrato", reemplace el anterior. Descartarlo o sacarlo.

He sugerido dejar los errores solos debido a la refactorización y la corrección de errores son tareas diferentes. Si intentas adelantarlos juntos, puedes fallar en ambos. Puedes pensar que has encontrado errores, sin embargo, podrían ser "características". Así que déjalos en paz (por un minuto).

Las 25 mil líneas de código me parecen suficientes problemas para que me centre en una sola tarea.

Una vez que tu primera tarea haya terminado. Exponer esos errores / características a su jefe.

Finalmente, como @Stephen ha dicho:

  

No hay mucho que puedas hacer al respecto, excepto hacer las cosas lentamente.   Cuando cree las nuevas clases, asegúrese de probarlas correctamente y   Créelos usando los principios de SOLID para que sean más fáciles de cambiar en   el futuro

    
respondido por el Laiv 05.11.2016 - 17:22
fuente
5

Pruébalo.

Todos los demás recomiendan cómo refactorizar, por lo que hay poco impacto. Pero con tantos errores, incluso si logra refactorizar con tan solo 10 líneas de código (probablemente pueda), entonces ha afectado a 25,000 flujos de código , incluso si no tuvo que volver a escribir ellos.

Por lo tanto, lo siguiente que debe hacer es asegurarse de que su conjunto de pruebas de regresión pase con éxito. Y si no tienes uno, haz uno que lo haga. Agregar un conjunto completo de pruebas de regresión a su proyecto monolítico suena aburrido, pero es una buena manera de aumentar la confianza en los candidatos de lanzamiento, así como de lanzarlos más rápido si el conjunto está bien automatizado.

    
respondido por el Greg 04.11.2016 - 22:17
fuente

Lea otras preguntas en las etiquetas