Yo solo refactoré 15 mil líneas heredadas. Fueron las peores dos semanas de mi vida.



Hace unos meses trabajé en un personal. Este no es un lugar donde necesita entusiasmo y fe en el gran objetivo del proyecto. Junto con el equipo, simplemente me vendieron a los clientes, y en las reuniones fue importante cuántas entradas cerré. Los ataques de perfeccionismo son algo malo para un lugar así, pero no pude hacer nada con ellos. Pagué mucho por uno de ellos, tuve una crisis infernal y pasé las peores dos semanas de mi vida.

Mi compañía me pidió que viniera a Moscú durante dos semanas, a la oficina principal, para trabajar con el equipo. La solicitud es razonable, acepté. Unos días antes de la salida, tomé otro boleto. Fue necesario agregar una función al SDK para una docena de proyectos en los que estamos trabajando. Este SDK es un legado infranqueable que nadie en su sano juicio toca. Hay un pantano tan grande que incluso los ingenieros quemados son bautizados supersticiosamente, si todo funciona, cómo funciona. Cuando necesitamos arreglar algo o agregar una característica, retrocedemos cuidadosamente el código con otra muleta y, sin respirar, lo enviamos a manos de CI y QA.

Planeaba hacer lo mismo. La esencia de la tarea era simple. El SDK en sí es un envoltorio sobre un sistema binario muy inteligente que puede levantar una VPN. Ella se comunica con nuestro back-end, recibe todo tipo de configuraciones, autoriza al usuario, obtiene una lista de países para VPN, etc.

Solo necesitaba agregar otra solicitud al backend, que recibe una lista de servidores. Parece extremadamente simple: agregó un método a la API pública, ingresó una solicitud para la URL deseada, abofeteó el modelo, analizó y lo regaló. Luego enseñó a las aplicaciones del cliente a usar esta solicitud, y ya está. Hice la tarea en dos días.

Un gran error. No hay tareas simples. Con un ojo ya estaba revisando los bares de Moscú, donde necesitaba beber toda la cerveza, con el otro vi el primer problema. No solo obtenemos una lista de servidores, también utilizamos uno de ellos para crear un túnel VPN. Anteriormente, solo usábamos países para esto. Pero algún genio decidió que sería una gran idea almacenar países como una lista de cadenas. Por supuesto, la esencia de un nodo VPN es una cosa demasiado amplia como para caber en una línea.

Como resultado, surgieron un montón de métodos en el SDK que toman una cadena (código de país) y hacen algo allí, y ahora todos estos métodos deberían tomar un código de país o un objeto de servidor, y hacer algo allí. Todo lo que hicimos en el código SDK y las aplicaciones con países, ahora tenemos que hacerlo tanto con países como con servidores.

Cuando entendí esto, por alguna razón, estaba encantado. El alcance de la tarea ahora me permitió refactorizar ligeramente el pantano, lleno de mierda en la que nado todo el tiempo. Declaré mi deseo, y ahora lo sé con certeza: me dieron el visto bueno con una expresión, como si hubieran perjudicado a una mujer discapacitada al precio de Maserati. Acepté un presupuesto semanal y me puse a trabajar.



Hubo un par de días antes de la salida. La semana parecía un infinito entero. Decidí que, hasta que escribiera el código, simplemente sacudía la decisión en mi cabeza, y tan pronto como llegara, rápidamente dispersaría todo.

Cuando una persona normal realiza un viaje de negocios, compra boletos por adelantado, resuelve el problema de la vivienda, advierte a su esposa y, en general, hace todo bien. Soy un idiota miope que pisoteó a Moscú con su esposa y sus dos hijos. Tuve que llevar a mi esposa porque le conté sobre el viaje tres horas antes de la salida. En dos horas, comencé a buscar un conductor con una minivan, porque mi auto se averió. Alquilé un apartamento en el mismo momento. Seis horas de viaje con niños gritando y una esposa insatisfecha terminaron como deberían: el apartamento era exactamente dos mil veces más pequeño de lo que parecía en las fotos. El peor olor era el olor a hierba. La criada que nos acogió dijo que envenenaron a las cucarachas (cucarachas !!!). Mi esposa le creyó, y decirle a mi esposa que distingo el olor a hierba del veneno para cucarachas no me interesa.

Llegué a la oficina, me dieron una computadora portátil. Durante medio día instalé el entorno, conocí a todos. Cuando todo se descargó e instaló, comenzó a funcionar. La ira del terrible movimiento aún no se ha enfriado. Abrí el proyecto con el SDK, una vez más me maldije fuertemente y pensé: “¿Qué demonios? Sí, aquí hay que tirar y rehacer todo al infierno con los perros ".

Le dije al líder sobre esto, y él, por supuesto, respondió: "Estoy de acuerdo, hombre". Un proyecto de 15 mil líneas, cada una de las cuales es un crimen de lesa humanidad. Estaba a punto de arreglarlo en dos semanas. Y si tuviera diez horas de viaje y tres hijos, ¿qué sugeriría una pista? ¿Inventar en una semana un nuevo PL específicamente para el proyecto?

Pero me pareció que si ordenaba al menos algo, sería más fácil para mí. Ahora crucifico a este govnokod, haré todo como debería, viviremos. Una vez leí libros sobre cómo hacer una refactorización profunda. Hubo muchos pensamientos inteligentes sobre cómo pintar pasos, escribir pruebas, pensar en sus acciones para que tenga confianza en cada paso: el proyecto funciona, nada está roto. Libros y mejores prácticas, es genial, pero nunca aprendo de los errores de los demás. Al comienzo de mi carrera, leí mucho sobre todo tipo de cosas básicas, pero no creí en ellas hasta que necesité expandir la funcionalidad de mi primer proyecto.

La tarea de cualquier rastrillo es darle una frente. Hasta que tus decisiones fallidas no te importen personalmente, no las considerarás infructuosas.

Comencé a refactorizar sin depender de la práctica. Dividí mentalmente el proyecto en grandes piezas lógicas. Esto no se reflejó en su estructura de archivos, así que llevé esta estructura de archivos al infierno. Creé un papá del nivel superior: aquí tenemos trabajo con la parte de atrás, aquí trabajamos con VPN, aquí ayudantes, hay excepciones. Pruebas unitarias existentes, también las rechacé. Entonces me pareció que el govnokod no tenía derecho a la vida, pero ahora entiendo que salté del avión y no tomé el paracaídas, porque se violó las instrucciones.

Comencé a transferir el govnokod de viejos papás a nuevos, al mismo tiempo que lo ordenaba. Nada especial, solo sigue las buenas prácticas. Hay una clase que describe el modelo de usuario, tiene todas las propiedades opcionales, todas con setters. Convirtiéndolo en la jerarquía de herencia de un niño. Todo ridículamente, todo a través del constructor. Para que los usuarios de esta clase siempre sepan exactamente lo que tienen en sus manos. Hay un método de gobierno en cuatrocientas líneas: golpeas en submétodos. Ves un archivo con mil responsabilidades, lo conviertes en mil archivos con un solo deber. Hay una clase que tiene el método Initialize, que siempre debe llamarse inmediatamente después de crear la clase: se aplica el patrón de "estado"

Los conceptos de código bueno y malo son muy vagos. Toda mi vida aprenderé a distinguirlos. Pero, francamente, código de mierda que puedo ver ahora. Ver y corregir. Intenté no traspasar mucho la arquitectura de nivel superior y cambiar la API externa del SDK lo menos posible.



Quedarse en el trabajo durante un par de horas, cuando su esposa lo está esperando en una ciudad extranjera, en la peor cabaña del mundo, y tiene dos hijos pequeños que rugen del estrés sin parar, es una mala decisión. Me quedé por siete horas. El primer día de trabajo, me senté en la oficina hasta la una de la mañana y copié dos por ciento de la fuerza.

"En casa" me esperaba un escándalo merecido, en la mañana: café instantáneo de mierda. Alquilé un departamento a cinco minutos de la oficina, pero estaba tan extraño y asustado en esta terrible ciudad que los primeros tres días fui a trabajar en taxi.

Todos en la oficina estaban muy alegres: la gente iba a beber por la noche. Estos moscovitas hacen esto todos los días. También me llamaron. Prometí intentarlo, aunque yo mismo lo sabía con certeza: no hay opciones. Se puso a trabajar de nuevo.

Entonces me pareció que yo mismo tenía la culpa de toda la mierda de la casa, porque me llevaba las cosas por su cuenta. Era mejor buscar un apartamento, prepararse mejor, prever todos los problemas con la familia y la vida. Un montón de problemas que no podrían haber sido. Al mirar el código, pensé: esto es a lo que conducen las medias medidas.

Rápidamente decidió que mi enfoque de ayer era demasiado comprometido. Si lo rehaces, entonces eso es todo. He dejado de limitarme a renombrar y dividir. Cada archivo que estaba a punto de procesar fue analizado cuidadosamente. He estado en este proyecto durante bastante tiempo, entiendo bien lo que la empresa quiere aquí y lo que debe hacer nuestro código.

Pero aquí comencé a encontrar constantemente código que no entiendo: qué problema resuelve y por qué fue escrito. Y tomé una decisión: si no entiendo por qué se necesita el código, entonces no es necesario. Felizmente comencé a enviar esta basura digital al inframundo.

Este enfoque ha dado lugar a nuevos problemas. La API pública del proyecto estaba equivocada. Había muchos métodos con una firma absurda (por ejemplo, un método toma una cadena y un objeto que contiene la misma cadena). Muchos métodos tenían nombres idiotas. Y, en general, si usa este SDK con la API que tenía, puede romper la aplicación de diez mil maneras.

En este momento, ya he ido lo suficientemente lejos. El proyecto no iba a funcionar, y no había posibilidad de que lo hiciera en los próximos días. Todo lo que cambio en él, lo puedo verificar solo al final del trabajo. Y dado que ya cambié tanto, ¿por qué no cambiar la API pública entonces? Bueno, fui lo suficientemente inteligente como para hacer copias de repositorios desde el SDK y las aplicaciones, para poder duplicar los cambios de API en estas copias y encontrar errores. Después de todo, ni siquiera pude compilar la versión principal del SDK.

Los problemas comenzaron de inmediato. Cambió la firma de un método? Captura más doscientos errores de tiempo de compilación en aplicaciones. Debido a las firmas incorrectas, los parámetros incorrectos se pasaron a los métodos y las aplicaciones funcionaron. Al mismo tiempo, trabaja en cuatro ventanas IDE. Después de cambiar los tres métodos, y curar todos los errores con ellos, pensé que, dado que el trabajo ya estaba hecho, sería una tontería cambiar solo una parte de la estúpida API, necesitamos rehacerlo aún más. Y entró en el proceso aún más profundo.



Constantemente tenía que tomar decisiones, sobre todo éticas. Entonces sé cómo debería funcionar algo, y ahora veo el código que debería hacerlo. Lo leo y entiendo que él no. Pero este código está en producción, pasó QA. ¿Y quién es el tonto? ¿Cómo puedo asumir esta responsabilidad? Al principio, pensé durante mucho tiempo sobre cada caso, consulté con un líder y un equipo. Pero tomó demasiado tiempo.

Me di cuenta de que estaba trabajando lentamente porque tenía miedo de romper algo, tratando de resolverlo en alguna parte, para tener cuidado. Luego me dije: "Soy más inteligente que el que escribió esta mierda, sé lo que hay que hacer, tengo una tarea y un presupuesto para la refactorización, y tengo derecho a todo". Los débiles entienden y se preocupan, un hombre sabe lo que quiere y lo hace sin hacer demasiadas preguntas.

En algún momento, entré en un extraño estado de un robot que procesa metódicamente un archivo con código tras otro. Sin comprobar nada, sin dudar nada. Veo un mal código: cambio. Esta cadena plantea nuevas áreas problemáticas y las repara. En cada uno reemplazo el govnokod con algo tolerable.

Parece un bombardeo en ajedrez. Juegas un juego en el que lo más importante es pensar en todas las opciones posibles, pero tienes tan poco tiempo que ni siquiera puedes pensar en qué opciones valen la pena pensar en ellas. Siempre pierdo bombardeos. Para el segundo día hice mucho. Aquí hay un código que no puede verificar, no es un código. Y lo sabía.



Una noche, recordé que le había prometido a mi esposa que iría a Ikea. El departamento en el que vivíamos era terrible, y mi esposa quería comprar basura acogedora. Escribí código todo el día, mi cerebro estaba exhausto, pero tenía que irme. Ponga el coche compartido, el coche más cercano estaba a veinte minutos. Llamé a un taxi para llegar al auto. Imagine un típico callejón sin salida de Moscú repleto de autos hasta los globos oculares. Al final de esto, Renault Kaptur me estaba esperando. Después de haber derrotado la IU rezagada del Delimobile, pude abrir este cubo. Había una sorpresa esperándome: caja de cambios automática. Nunca conduje una máquina, pero pensé que podría manejarla. Si desea avanzar, debe mover la manija hacia adelante, si está hacia atrás, hacia atrás. No Me di cuenta de que el auto no iba exactamente en el momento en que todavía era posible salvar la situación.

Freno deprimido. Naturalmente, el pie equivocado, porque en una estúpida máquina solo dos pedales, y mi cerebro entendió mal todo. Idiota salvaje, el auto se levantó. Dos milímetros para el Mercedes S-Class.

De alguna manera salí del callejón sin salida y me di cuenta de que todos los autos del mundo estaban a mi alrededor, pero no tenía idea de dónde o cómo ir. Conduje hasta la "casa", llevé a mi esposa, atravesé la medianoche por la ciudad más terrible del mundo, perdí una docena de vueltas, dejé una fortuna en Ikea.

Regresamos a las cuatro de la mañana, mi cerebro se apagó tan pronto como mis ojos vieron la cama.



A las ocho de la mañana estaba en el trabajo otra vez. Allí todos están felices nuevamente, discutiendo sus asuntos y bares de Moscú a los que no puedo llegar. Tengo el SDK nuevamente. Con la cabeza pesada, hojeé los cambios que había hecho. Todo esta muy mal. Mañana el rally se estaba prolongando, y necesito otros trescientos años para terminarlo.

Tengo una buena habilidad: cuando recibo un boleto grande, siempre lo descompongo en varios pequeños. De ahí mi flujo de trabajo. Un ticket, uno o dos commits, una solicitud de extracción. Por lo tanto, en principio, no puedo dividir la tarea en varias confirmaciones en el proceso de codificación; por lo general, no necesito esto. Pero el estrés me terminó y la habilidad falló. En el proceso, convertí una pequeña tarea en una gigante, pero comencé a trabajar en ella de la misma manera que trabajaría en una pequeña. Sin un sistema, estúpidamente donde vi el problema, lo arreglé allí. No dividió el proceso en pasos lógicos, sino simplemente como el último junio lo agarró de inmediato.

No puedes devolverlo. El principal problema persistía: no podía construir y ejecutar la solución completa, y no tenía idea de cómo funcionaría. Fue muy aterrador, el último día miré las diferencias y me di cuenta de que había reescrito casi todo el proyecto. Daba mucho miedo.



Todo siempre se desliza en el último día. El viaje de negocios terminó, mi tiempo extendido para refactorizar también. Mi esposa llamó y dijo que estábamos siendo desalojados a la una de la tarde, aunque acepté una tarde. Naturalmente, esto significaba que no podía terminar el último día hasta el final.

Junto con tres galones de sudor frío, lo que se me ocurrió cuando emprendí esta tarea, planifiqué una refactorización, acepté un viaje de negocios, llevé a niños, me quité un alijo durante dos semanas: soy el idiota más importante del mundo. Vale la pena que los psiquiatras resuelvan mis motivos, pero decidí ir hasta el final. Ya sea para castigarme o para creer irracionalmente que estoy haciendo todo bien.

Con el culo ardiendo, congelo todo en una hora, lanzo CI y vuelvo a casa. Todo el camino me desplazo por mi código en mi cabeza y estoy absolutamente seguro de que nada funcionará. Demasiados cambios, habrá cien errores, y rechazaremos esta refactorización.

Cuando volví a casa, la noticia me estaba esperando: el proyecto está funcionando. Lead corrigió un par de pequeñas cosas, mis cambios pasaron las pruebas automáticas y ahora están siendo sometidos a pruebas manuales con éxito. No lo creí. He estropeado el código de una carretilla de casa, recopilé y verifiqué manualmente todos los scripts en los que no confiaba. Funcionó. Funcionó !!!

Estaba tan orgulloso de mí mismo. La calidad de la base de código ha crecido muchas veces, han aparecido varias características, eliminé un montón de errores que los probadores aún no han podido solucionar. Liba podría usarse cómodamente, y probé que estaba en forma profesional.



Ráfagas de entusiasmo y trabajo sacrificado: la gran cantidad de tontos ingenuos. Me alegraría demostrar lo contrario a mí mismo con esta historia. Pero unos días después de regresar, me esperaban más noticias.

El cliente decidió abandonar el proyecto. Casi un centenar de personas en el personal (la mitad de toda la compañía) resultaron estar "esperando un nuevo proyecto". Considere - desempleados limbicamente. Y los controles remotos en tales asuntos se cortan en primer lugar. Me dijeron que me mudara a Moscú permanentemente y me cambiara a otro proyecto. O te despediremos.

Le pregunté qué pasaría con el antiguo proyecto.

En esos momentos, las personas se vuelven dolorosamente honestas. La adulación, los adornos y la ética corporativa ya no son necesarios. Me dijeron que este código ya no es necesario para nadie en todo el mundo, enviado al basurero de la historia. Los productos en sí se utilizarán durante mucho tiempo, pero nadie admitirá la base del código. Todo esto es la calidad y legibilidad del código, escalabilidad, facilidad de uso, comportamiento inequívoco: todo se hizo en vano.

Escucho y entiendo que podría hacer una función y caminar por los bares. Pero me senté por la noche, no dormí, soporté escándalos por el bien de una buena base de código que nadie más necesitaba. El entusiasmo es algo mentiroso. Dices que estás listo para trabajar, incluso si no hay ganancia en esto. Pero cuando te dicen que tu mayor gratuidad realmente no trae beneficios, por alguna razón mata. Esperabas cambiar con tu impulso toda maldad universal.

Creo que entendí todo perfectamente desde el principio. Simplemente no quería ser un chico pragmático.

Por lo tanto, dije que podían despedirme al infierno y dejar que sus madres fueran transportadas a la mierda de Moscú para que sus gordos traseros se rasgaran sin goma a mil millones de pedazos pequeños. Él cortésmente escribió sobre esto y se quedó en casa. Hay suficientes tasas en el mundo que solo necesitan hacerse.

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


All Articles