Refactorización paralela al desarrollo: nuestra experiencia y dos listas de verificación



Para muchos equipos, refactorizar es una molestia. Porque si refactoriza, no desarrolla el producto principal, y si no lo hace, la deuda técnica del proyecto aumenta. En algún momento, los equipos piensan: "¡Distingamos entre refactorización y desarrollo y asignemos, por ejemplo, el 20% de nuestras horas hombre, y el resto del tiempo continuaremos participando en el desarrollo!" Esta idea no es mala, lo único es que por cada 100 horas de desarrollo nunca obtendrá 20 horas puras de refactorización. Porque "desarrollo" no es solo trabajar con código.

Si estamos hablando de equipos maduros, en lugar de mini-equipos comprimidos en un punto material para 3-5 personas, entonces el "desarrollo" incluye una gran cantidad de actividades de equipo diferentes además de escribir código. En el "desarrollo", puede escribir reuniones tan poco queridas por muchos, trabajar con documentación, mantener informes en administradores de tareas, etc. Todo esto consume alrededor del 30% de nuestros relojes destinados al desarrollo. Y de alguna manera, desapercibido, resulta que en lugar de la imagen "80 horas de código, 20 horas de refactorización", obtenemos una cifra desagradable de ~ 13 horas para, directamente, la refactorización en sí, porque todo lo demás fue absorbido por otras actividades.

A continuación, le diremos cómo combinar el desarrollo con la refactorización para que la deuda técnica del proyecto no crezca como una bola de nieve, sino que también hablemos sobre la distribución correcta del tiempo y la priorización.

¿Por qué la refactorización causa tantos problemas? En primer lugar, debido al hecho de que los equipos no pueden evaluar adecuadamente sus propios recursos y combinar este proceso con el desarrollo. A las personas les parece que si su jornada laboral es de 8 horas al día (40 por semana), entonces las 40 horas supuestamente están dedicadas al desarrollo. Esto no es asi.
Todo el proceso de desarrollo se puede dividir en dos partes: estas son actividades paralelas y todo lo que está directamente relacionado con el código.


Así es como se ve la distribución de tiempo de uno de nuestros equipos de desarrollo

El lector puede tener una pregunta razonable: "¿cómo construiste este diagrama?" y ahora intentaremos dar una respuesta. Los datos no fueron tomados del techo, sino basados ​​en nuestras estadísticas internas. Nuestros desarrolladores realizan un seguimiento de su actividad en Jira. Cada registro de trabajo personal consta de cuatro secciones: revisión de código, discusiones técnicas, tickets específicos y "todo lo demás". Gracias a esta clasificación bastante simple y transparente, creamos un análisis de cuánto tiempo pasamos los equipos en cada aspecto del desarrollo. Si un tercio de todo el tiempo de trabajo corresponde a reuniones, stand-ups y revisiones, todo está dentro del rango normal. Si se gasta más del 33% en estas actividades, el equipo tiene problemas y debe abordarse.

Parece que no hay trampa y todo es lógico, pero ¿cómo encajamos la refactorización en esta historia? ¿Declarar un "mes de refactorización" y puntuar en desarrollo? Sin embargo, cualquier producto comercial tiene su propio horario, lo cual es extremadamente indeseable. Todavía refactorizar es como un atolladero: si comenzaste a lidiar con él, entonces es difícil de detener, te sientes atraído por este fondo. La refactorización cambia el enfoque de la atención del equipo hacia sí mismo, y obtenemos un sesgo monstruoso hacia la "restauración del orden" en el código ya escrito en lugar de mover el proyecto a un futuro más brillante. Entonces, ¿cómo distribuir el tiempo?

La siguiente diapositiva ofrece algunas respuestas:


Mantenga registros de tiempo, es muy útil

Las reuniones y las revisiones permanecen intactas, porque creemos que estas actividades se optimizan tanto como sea posible y se mantienen al mínimo adecuado (aquellos que trabajaron en equipos donde las reuniones y las revisiones de códigos tomaron el 70% del tiempo confirmarán nuestras palabras). Por lo tanto, nos tomamos el tiempo para refactorizar el código y las correcciones de errores del desarrollo. Y aquí aplicamos nuevamente el enfoque de "uno y dos tercios" y dividimos las horas hombre recibidas por nosotros en "refactorización" y "errores", separando claramente estos conceptos. Dicho modelo es viable y le permite encontrar el tiempo para restablecer el orden del proyecto, al menos sin aumentar la deuda técnica. Si aprovechamos demasiadas horas de "desarrollo", el proyecto se detendrá.

Abordamos el proceso de refactorización correctamente


Suponga que decide refactorizar en lugar de reescribir un proyecto desde cero. Pero aquí no puedes tomar el primero y refactorizar como en el ejército, "desde aquí hasta el almuerzo". Dado que nuestros recursos son limitados y nuestro objetivo es detener el crecimiento de la deuda técnica (e idealmente lograr una reducción en su tamaño), debemos abordar esta tarea con sensatez.

La mejor solución parece permitir que el líder del equipo u otro gerente de desarrollo determine el alcance del trabajo, asigne tareas y proceda con la refactorización. Pero esta opción tiene un defecto grave. Timlid es el director de nuestro equipo, pero los problemas de los músicos locales no siempre son obvios para el director. Si eres partidario de una vertical rígida y un modelo en el que una persona decidirá cómo se llevará a cabo la refactorización, entonces voluntariamente te sientas en el ardiente KAMAZ, que con los frenos rotos se precipita desde la montaña hacia el abismo.

Nuestra experiencia muestra que una versión robusta del desarrollo de eventos es una definición colectiva de varias direcciones de refactorización, es decir, los desarrolladores deben participar en la compilación de una lista de trabajos futuros. Solo el autor inmediato del código puede admitir honestamente si esta sección se cerró adecuadamente o por falta de tiempo, se apilaron varias muletas allí. Además, son los desarrolladores quienes están a la vanguardia de la tecnología y son capaces de evaluar con sensatez qué elementos de un proyecto necesitan ser refactorizados y cuáles no deben ser tocados.

Para nosotros, se nos ocurrió este enfoque: cada uno de los desarrolladores recuerda los puntos débiles del proyecto y escribe una tarjeta sobre lo que hay que hacer para mejorarlo. En estas tarjetas, se determinarán las tareas. Es cierto que hay un matiz: después de la primera tarjeta recibida en el estilo "hacerlo bien" sin ningún contexto, comenzamos a exigir este contexto en forma comprimida.


Las mismas cartas

Pero definir una tarea no es suficiente para comenzar su implementación. Por lo tanto, se debe compilar una lista de verificación para cada tarjeta, que responde a una serie de preguntas simples como "¿Necesitamos hacer algo en paralelo?" o "¿Hay algún factor que nos impida completar esta tarea?" Después de completar dicha lista de verificación, el desarrollador recibe una lista específica de todos los posibles problemas y bloqueadores que deben resolverse en la etapa de trabajo preparatorio.

Otro paso obligatorio es determinar quién se encuentra en qué áreas del proyecto quién sabe mejor. Esto optimizará el proceso de refactorización y proporcionará a los miembros del equipo tareas en aquellas áreas donde puedan probarse mejor. Es cierto que un día nos enfrentamos a una situación en la que una persona y media normalmente entendía un aspecto del proyecto, pero incluso este problema puede resolverse. Para eliminar el vacío de información, los desarrolladores que todavía "hurgan" en el área por donde pasa el resto del equipo, deben compartir sus conocimientos. Esto puede ser documentación, algún tipo de mini-presentación, incluso un video con explicaciones del código. Es importante transmitir información a los colegas y asegurarse de que haya la menor cantidad posible de puntos oscuros.

Y finalmente, el equipo debe responder claramente la pregunta "¿cuál es el tamaño de nuestra deuda técnica?" Grados como "grado C", "aceptable", "cinco de diez", "puedes vivir" ya no funcionan. Anteriormente, respondimos "uno de cada diez" en una pregunta similar de la estación de servicio para uno de los proyectos, y cuando convertimos la cantidad de deuda técnica en números, obtuvimos 650 horas. Fue incomodo. Solo una respuesta clara a esta pregunta ayudará a evaluar de manera sensata el alcance del próximo trabajo. Esto también es importante porque las tareas "interminables" matan la motivación de los miembros del equipo, además de enfurecer al negocio: tanto los desarrolladores como la gerencia deberían ver algún punto final tangible por el que el equipo se esforzará.

Priorización


Después de definir el frente del trabajo, debemos combinar la refactorización con el desarrollo. Obviamente, no podemos detener el corte de características en diferentes partes del proyecto o asignar un tiempo especial para este evento.

Aquí es donde comienza la parte más difícil. El equipo de desarrollo debe determinar con sensatez en qué momentos el desarrollo es más importante y en qué refactorización es importante, especialmente cuando se está recortando alguna característica en este punto del código. Quizás, después de refactorizar, el desarrollo posterior será más fácil y, en algunos casos, podremos finalizar nuestra función y solo entonces refactorizar. Nos comunicamos con el producto, discutimos la decisión y acordamos cuál será el pedido. Por ejemplo: "Primero refactoricemos, no solo porque nos apetezca, sino porque el término total será menor al final".

Lo más importante es no olvidar que nuestro objetivo es desarrollar un producto, y no escribir el código perfecto en aras del código perfecto o la eliminación completa de la deuda técnica. El desarrollo debería ser totalmente adecuado a este respecto: si la refactorización en este momento perjudica nuestra tarea de desarrollo empresarial, entonces terminamos de escribir un nuevo código, y solo entonces corregimos el anterior. Si las circunstancias dicen que será más rentable para el proyecto refactorizar esta sección (no importa cuán monstruoso parezca el frente del trabajo), ya que el trabajo adicional será más simple y divertido, entonces necesitamos refactorizar.

Este enfoque encaja extremadamente mal en el modelo de gestión vertical y, a veces, encontrará situaciones en las que tendrá que defender sus decisiones frente al cliente. Pero por lo demás nada.

¿Qué obtenemos como resultado?


Con el enfoque descrito, integramos orgánicamente los procesos de refactorización en el desarrollo actual, reducimos el tamaño (o detenemos el crecimiento) de la deuda técnica, y todo esto sin mayores víctimas.

Sí, en aras de la refactorización, será necesario reducir el tiempo para desarrollar nuevas características, lo que aumentará el tiempo, pero la elección es pequeña: puede refactorizar en paralelo con el desarrollo, o tarde o temprano llegar a tal montón de muletas, problemas y errores para que sea más fácil reescribir el proyecto desde cero. Entonces, si valora el trabajo de su equipo, debería pensar en refactorizar en lugar de reescribir en el futuro.

Materiales utiles:

1. El informe de Alexey Kataev sobre refactorización: ejemplos más prácticos, así como una increíble historia del gerente Gleb, que aún no quería refactorizar ...



2. Nuestras regulaciones para la discusión de tareas

3. Nuestra revisión del código de la lista de verificación

Source: https://habr.com/ru/post/468579/


All Articles