Cuando refactorizar

32

He leído la mayor parte del libro de Refactorización de Fowler y he refactorizado muchas aplicaciones en mi pasado, grandes y pequeñas.

Una de las cosas más difíciles que encuentro para enseñar es "cuándo" refactorizar. Tiendo a hacer esto basándome en una intuición que me ha servido notablemente bien en el pasado. Sin embargo, al entrar en discusiones con la gente acerca de si un código debe dejarse solo o refactorizarse en este momento, es difícil mantenerse al margen de la "verificación intestinal".

Siento que debería haber enfoques más rigurosos para esto, pero no estoy seguro de cuáles son.

Entiendo "olores de código", refactor rojo-verde y otros pensamientos, pero a menudo siento que el mejor momento para refactorizar no es la primera vez que escribes el código, sino la segunda o tercera vez que estás usando el código y te das cuenta que es realmente un problema y está en uso real.

Hortitude
fuente
2
Básicamente, está preguntando lo mismo que esto: programmers.stackexchange.com/questions/6268/… . Excepto que su umbral para tomar medidas es más bajo, ya que el costo y el riesgo son más bajos, ¿verdad?
S.Lott

Respuestas:

22

Refactorizar cuando el costo de refactorizar es menor que el costo de no refactorizar.

Mida el "costo" como pueda. Por ejemplo, ¿el código está tan mal implementado que los errores triviales cuestan horas o días solucionarlos? ¿La refactorización le permitirá ganar más clientes, aumentar la capacidad o mejorar el rendimiento y, por lo tanto, hacer que sus clientes actuales sean más felices?

Bryan Oakley
fuente
breve y perfecto
ZJR
8
En otras palabras: "vale la pena refactorizar cuando vale la pena refactorizar". Duh Bueno, en realidad no es una respuesta, ¿verdad? Measure "cost" however you can.- OK, ¿cómo? ¿No es esa la esencia de la pregunta? ¿Qué perspectiva de tiempo debe aplicarse al medir ese costo?
Konrad Morawski
2
@Morawski: no, esa es una paráfrasis incorrecta. Dije que vale la pena refactorizar si el valor recibido de la refactorización es mayor que el costo de la refactorización. Eso no es lo mismo que decir "vale la pena refactorizar cuando vale la pena refactorizar". Calcule el costo de refactorización. Calcule el costo de no refactorizar. ¿Cuál es más grande?
Bryan Oakley
@BryanOakley: el problema es que no puedes "calcular" estos costos. En el mejor de los casos, puede estimarlos, lo cual es realmente difícil de hacer cuando se trata del costo de no refactorizar . ¿Qué multiplicador de costo de mantenimiento aplica a la versión no refactorizada versus la versión refactorizada? ¿Cómo saber si el código en cuestión tendrá que ser mantenido o cambiado? ¿Cómo estima la cantidad de errores que generará? Al final, supongo que todos inconscientemente hacemos este tipo de estimaciones como parte de nuestro proceso de decisión cuando pensamos en la refactorización, pero no se puede esperar precisión de ella.
guillaume31
1
@ ian31: cierto, no puede calcular valores, y lo mejor que puede hacer es estimar. Aún así, esta es la única forma realmente válida de decidir si refactorizar o no, suponiendo que tenga tiempo y recursos limitados. Debe decidir si el refactor lo vale. Cómo define "valor" es una ciencia muy inexacta. El punto es que no deberías refactorizar por instinto; debería haber una buena razón para refactorizar que no sea "Quiero que el código sea más bonito".
Bryan Oakley
12

  1. ¿La complejidad ciclomática de la función es inferior a 5?
  2. ¿Entendiste completamente qué era la complejidad ciclomática sin seguir ese enlace?
  3. ¿Tiene una prueba automatizada o un caso de prueba documentado para cada ruta a través de la función?
  4. ¿Pasan todos los casos de prueba existentes?
  5. ¿Puede explicarme la función y todos sus casos límite en menos de 1 minuto?
  6. Si no, ¿qué tal 5 minutos?
  7. ¿10 minutos?
  8. ¿Hay menos de 100 líneas de código en la función (incluidos los comentarios)?
  9. ¿Puedes encontrar otros dos desarrolladores que estén de acuerdo en que este código está libre de errores solo mediante inspección visual?
  10. ¿Se utiliza esta función en un solo lugar?
  11. ¿Cumple la función sus objetivos de rendimiento (Tiempo / Memoria / CPU)?

Tanteo

Agregue las respuestas "no" arriba:

  • 0-1 - ¿Por qué pensarías en refactorizar esto? Probablemente solo desee cambiar el nombre de las variables porque no le gusta la convención de nomenclatura del desarrollador anterior
  • 2-5 - Esto podría necesitar un pequeño ajuste, pero no demoraría un lanzamiento de producción para algo en este rango
  • 6-8 - OK, probablemente necesitemos arreglar esto ... Es probable que sigamos revisando esto y / o no sepamos realmente qué está haciendo. Todavía en la cerca, pero es altamente sospechoso
  • 9+: este es un candidato principal para la refactorización. (Nota, escribir casos de prueba es una forma de refactorización)

http://mikemainguy.blogspot.com/2013/05/when-to-refactor-code.html

Mainguy
fuente
44
# 2 suena muy snob y en realidad es inútil para evaluar el código . # 3 y # 4 no todas las empresas utilizan pruebas unitarias. # 8 Evite los comentarios siempre que sea posible, y 100 líneas son muuuuy altas. Tengo 1 gran monitor panorámico en modo vertical y apenas podría ver toda la función a la vez. Si son más de 15 líneas de código real, ya debería haber una razón sólida por la que lo mantiene así. Es un enfoque agradable y práctico tener una lista de verificación, pero aquí se inventan demasiados puntos o se usan valores aleatorios sin ningún razonamiento.
R. Schmitz
8

Cuando tu instinto te dice que probablemente deberías hacer algunas refactorizaciones, es probable que tus instintos te digan un poco tarde que has estado posponiendo algo importante durante demasiado tiempo.

Entiendo "olores de código", refactor rojo-verde y otros pensamientos, pero a menudo siento que el mejor momento para refactorizar no es la primera vez que escribes el código, sino la segunda o tercera vez que estás usando el código y te das cuenta que es realmente un problema y está en uso real.

Hay efectivamente dos niveles para refactorizar. El primero son los problemas obvios que aparecen cuando codifica por primera vez. Estas son las pequeñas optimizaciones que le cuestan muy poco hacer por adelantado. Cosas como mantener sus métodos y clases pequeños, y adherirse a DRY y SRP. Luego tiene la etapa adicional de lidiar con fallas importantes en su diseño, que pueden no ser evidentes de inmediato hasta que su código tenga un par de millas debajo. Es de este segundo nivel del que está hablando y, sin embargo, para garantizar que la refactorización posterior no sea demasiado costosa, debe haber escrito su código de tal manera que el esfuerzo que prevé más adelante sea más fácil y menos costoso, lo que significa hacer una refactorización temprana.

Como Jeff mencionó en su respuesta, "el tiempo es dinero" , particularmente en compañías donde la carga de trabajo es alta y los riesgos aún mayores. El tiempo dedicado por adelantado para asegurarse de que el código esté en su mejor estado posible se ahorra tiempo más tarde, cuando descubrir lo que debería haber sido una refactorización fácil resulta ser una operación importante.

Al escribir software, cada momento dedicado a mejorar su código por adelantado es tiempo ahorrado más tarde, cuando realmente lo va a necesitar. Cuanto antes refactorice, más claros serán sus cambios posteriores. Es como hacer un pago inicial en dólares de hoy contra la deuda técnica futura que estará en dólares inflados de mañana.

En cualquier caso, la refactorización no debería ser una tarea que posponga hasta un futuro misterioso cuando el software ya esté completo y estable, ya que aumenta sus riesgos más adelante cuando las apuestas son mucho más altas y el producto es mucho más difícil de cambiar. La refactorización debe ser parte de sus actividades diarias, y esta es la esencia de la filosofía de refactorización rojo-verde que mencionó.

S.Robins
fuente
2

Creo que su pregunta puede ser respondida de manera diferente por cada desarrollador e incluso por la administración a cargo de la programación.

Mi preferencia personal es que, cada vez que aprendo algo nuevo o mejoro mis mejores prácticas, refactorizo ​​el código que puedo; me gusta mantener mi código al nivel tan pronto como sepa cuál es el mejor estándar para esa situación. Sin embargo, puedo hacerlo porque es una empresa más pequeña que utiliza el mismo software durante largos períodos de tiempo.

En una compañía de desarrollo de software más grande donde el tiempo es dinero, puede ser simplemente comenzar a diseñar con las mejores prácticas que aprendió de ahora en adelante, ¿no se preocupe por refactorizar hasta la versión 2 de ese software específico?

Siento que enseñar cuándo refactorizar realmente depende de la compañía en la que se encuentre actualmente.

Jeff
fuente
2

"¿Cuándo refactorizar?"

Respuesta corta: cada vez que te encuentras con un código que huele mal o podría mejorarse ( Regla de Boy Scout )

Prácticamente, esto sucede:

  • Si practica TDD, sistemáticamente durante el paso Refactor del ciclo TDD, es decir, una vez que su prueba esté verde y antes de comenzar a escribir una nueva prueba.
  • Como resultado de una revisión de código
  • Al asumir el código heredado
  • Al consumir código que parece extrañamente diseñado
  • etc.
guillaume31
fuente
Siento que esto simplemente dice "Deberías refactorizar" sin responder la parte más difícil: "Siento que debería haber enfoques más rigurosos para esto, pero no estoy seguro de cuáles son".
Hortitude
No sé qué decir, excepto sentir lo que es doloroso mantener, olfatear olores de código y usar su experiencia. Dudo que haya un método definitivo y establecido que le diga cuándo y qué refactorizar si eso es lo que está buscando.
guillaume31
1

Cuando aprendí por primera vez sobre la refactorización, mi mentor me dijo: "Hazlo dos veces, cúbrete la nariz. Hazlo tres veces. Refactoriza". (¡Gracias, Josh!) Para ser específicos, lo que estaba diciendo era que cuando estás a punto de escribir el mismo bloque de código por tercera vez (o incluso un patrón de código similar), ese es el momento de refactorizar. Lo he seguido durante los últimos 10 años, y descubrí que es una regla general lo suficientemente sólida.

El uso de Eclipse, o IDE similar que tiene un fuerte soporte de refactorización, reduce el esfuerzo para realizar la refactorización. El soporte IDE hace que sea más probable que refactorice tan pronto como llegue a la "tercera vez" (o vea la necesidad), en lugar de verlo como un esfuerzo adicional.

Además, TDD también es una gran ayuda, ya que puede seguir ejecutando sus pruebas como refactorizador y saber que no ha roto nada.

Sam Goldberg
fuente
1

Refactorizar por su definición es un proceso. Esto implica que no debe esforzarse por encontrar tiempo libre para realizar la tarea de factorización, sino que debe seguir refactorizando todo el tiempo cuando encuentre código de código que podría escribirse mejor.

Personalmente, me gusta escribir prototipos evolutivos, decirlo de manera más simple: código que simplemente funciona y luego refactorizarlos hasta que cumplan con los estándares de codificación esperados. Otro buen ejemplo es agregar funcionalidad adicional y refactorizar el código existente para permitir su reutilización.

0lukasz0
fuente
1

En mis 20 años de programación, esta es la única regla general que realmente he visto funcionar, a la que las personas pueden apegarse, y los gerentes permiten tiempo. (Refactorizar es como hacer dieta: claro, "las calorías que entran / las calorías que salen" es la fórmula para perder peso, pero eso no se traduce en una dieta que las personas cumplirán). Y así:

Refactoriza continuamente, mientras trabajas. Use Test Driven Development para que tenga varios ciclos de refactorización rojo-verde durante el día. Refactorice solo las partes del código que ha tocado.

Una vez que esté más seguro de sí mismo, puede variar de este régimen.

Dogweather
fuente
1

Creo que eso depende de las demandas del propietario del proyecto y del tipo que responde por la calidad del código. Simplemente no puede decidirlo solo, cuando el dinero de otra persona está en cuestión.

En cuanto a razones técnicas, hay varias.

  • Si tiene un error en el código, eso significa que este lugar no se entiende y es MUY probable que se puedan ocultar más errores aquí y seguramente habrá grandes problemas con cualquier intento de desarrollar las partes conectadas del código. Por lo tanto, este lugar debe verificarse para una posible refactorización.
  • Otra razón es cuando agrega o cambia una característica y el código antiguo es muy inconveniente para cambiar / agregar y los cambios / adiciones posteriores son muy posibles. Por supuesto, debe equilibrar el costo.
  • Quizás la razón más seria es cuando está cambiando el código y no se puede comprobar.
Gangnus
fuente
Como maestro de scrum, teníamos un desarrollador que constantemente argumentaba que cada historia que el equipo dimensionaba era más grande de lo que pensaba el equipo, y descubrió que quería refactorizar cada pieza de código que encontró. Por lo tanto, una historia de 3 puntos siempre fue un 8 para él. Claramente esto estaba arruinando la entrega de valor. Por lo tanto, de alguna manera debe haber cierta comprensión de cuándo refactorizar y cómo se debe tomar la decisión. Solo mi pensamiento, de esa (y algunas otras) experiencia.
Curtis Reed