17 puntos por GN⁺ 2024-08-04 | 3 comentarios | Compartir por WhatsApp

"¿La tabla merchants2? Sí, creamos merchants2 porque a merchants le faltaban columnas."

  • Cuando empecé a programar, no sabía que la gente ganaba dinero programando
  • Aprendí muchísimo en mi primer trabajo de software, y la base de código de ese lugar fue lo peor y lo mejor al mismo tiempo

Las bases de datos sobreviven para siempre

  • En un sistema legado, la base de datos hace más que solo almacenar datos. Define las restricciones de todo el sistema y es el punto donde se encuentra todo el código
  • SQL Server tiene un límite en la cantidad de columnas por tabla. En ese entonces era 1024; ahora es 4096. Como faltaban columnas en la tabla Merchants, crearon Merchants2 (con más de 500 columnas)
  • Merchants y Merchants2 eran el núcleo del sistema. Todo estaba conectado con Merchants. Había otras tablas normalizadas, pero también tenían relaciones de clave foránea con Merchants

SequenceKey

  • SequenceKey era una tabla simple con una sola columna y un solo valor
  • Se usaba para generar IDs. Supongo que se creó porque SQL Server no soportaba IDs autoincrementales
  • Todos los procedimientos almacenados tomaban una clave de SequenceKey, la incrementaban y la usaban como ID en varias tablas. Funcionaba como una unión implícita

Calendar

  • Calendar era una tabla de calendario ingresada manualmente. Si Calendar expiraba, no se podía iniciar sesión en el sistema
  • Esto pasó hace algunos años y un pasante agregó cinco años más. Nadie sabe qué sistema usa eso

Employees

  • Todos los días a las 7:15 de la mañana, la tabla employees se borraba y se volvía a llenar con un CSV recibido de ADP
  • Durante ese proceso no se podía iniciar sesión en el sistema. A veces este trabajo fallaba
  • Como los datos tenían que replicarse a la oficina central, se los enviaban por correo a una persona para que cada día apretara un botón y copiara los datos

La base de datos de reemplazo

  • Uno podría pensar que se podía limpiar la base de datos. La empresa también lo pensó
  • Había una copia de la base de datos, pero los datos tenían un retraso de unos 10 minutos. La sincronización ocurría solo en un sentido
  • Esta base de datos estaba normalizada, así que para encontrar un número de teléfono en merchants hacían falta 7 joins

Resultados de ventas

  • Todos los vendedores tenían una cuota mensual llamada "win" que debían alcanzar
  • La tabla que gestionaba esto era extremadamente compleja. Cada día corría un proceso que buscaba filas agregadas o modificadas y las sincronizaba con el sistema de la oficina central
  • El problema empezó cuando un vendedor pidió que le cambiaran un registro manualmente
  • Ese vendedor ya había alcanzado su win e hizo además una venta grande ese mismo mes, pero quería moverla al mes siguiente
  • Un pasante se hizo cargo de esto y, cuando el rumor se extendió, las solicitudes crecieron exponencialmente durante 3 años
  • Hubo un momento en que 3 pasantes se dedicaban por completo a escribir sentencias SQL. Crear una aplicación para esto se consideraba demasiado difícil

La base de código

  • La primera base de código que conocí estaba en Team Foundation Server, un sistema de control de versiones centralizado
  • La base de código en la que más trabajé estaba mitad en VB y mitad en C#. Corría sobre IIS y usaba estado de sesión por todos lados
  • Eso significaba, en la práctica, que si llegabas a una página por la Ruta A o por la Ruta B, veías cosas muy distintas en esa misma página
  • Todos los frameworks de JavaScript que existían en ese entonces estaban versionados en ese repositorio, casi siempre con modificaciones personalizadas que su autor creyó necesarias. Se notaban especialmente knockout, backbone, marionette, además de jquery y plugins de jquery
  • Además de esta base de código, había unas 12 aplicaciones SOAP y varias aplicaciones nativas de Windows

El disco duro de Gilfoyle

  • Gilfoyle tenía fama de ser un programador absurdamente rápido. Nunca lo conocí, pero lo conocía por su código y por el código que quedaba en su disco duro
  • Munch guardaba el disco duro de Gilfoyle en configuración RAID sobre su escritorio, aun años después de que Gilfoyle se fuera de la empresa
  • Porque Gilfoyle era famoso por no hacer check-in de su código y por crear aplicaciones arbitrarias, de un solo uso, de Windows, para usuarios individuales
  • No era raro que un usuario llegara con un reporte de bug de una aplicación que existía únicamente en el disco duro de Gilfoyle

El bug de envíos

  • Gran parte de mi trabajo consistía en rastrear bugs que el equipo no quería asignarse
  • Había un bug particularmente molesto que aparecía cada ciertos meses: pedidos que, después de enviarse, quedaban atorados en la cola de envíos y aparecían como no enviados aunque ya se habían enviado
  • Para resolverlo probamos distintas soluciones (scripts SQL, aplicaciones de Windows, etc.). Me aconsejaron no rastrear la causa raíz, pero no pude evitarlo
  • En el proceso aprendí a pensar como Gilfoyle. La app de envíos traía toda la base de datos, luego filtraba por fecha y conservaba todos los pedidos posteriores a la fecha de inicio de la aplicación
  • La app dependía de un servicio SOAP, pero no para hacer cosas propias de un servicio, sino como si fuera una función pura. El cliente causaba todos los efectos secundarios
  • En ese cliente encontré una jerarquía gigantesca de clases: 120 clases, cada una con varios métodos, y herencia de hasta 10 niveles
  • El único problema era que todos los métodos estaban vacíos
  • Eso existía para crear una estructura que pudiera usar reflexión. Esa reflexión armaba una cadena separada por pipes (basada en la base de datos, pero completamente estática) y la enviaba por socket
  • Al final eso se enviaba a Kewill, un servicio que se comunicaba con el transportista. El bug ocurría porque Kewill reutilizaba cada mes números de 9 dígitos, y alguien había desactivado un cron que borraba pedidos antiguos

Un caos hermoso

  • Podría decir mucho más sobre esta base de código: el equipo de desarrolladores senior que pasó 5 años reescribiéndola toda sin liberar código, o los consultores de Red Hat que construyeron una sola base de datos para controlarlo todo
  • Esta base de código tenía muchísimos rincones de locura, y muchas razones por las que habría valido la pena tener un equipo dedicado solo a rehacer una funcionalidad desde cero
  • Pero la historia más importante es la de cómo Justin mejoró la página de búsqueda de comerciantes. Esa página era el punto de entrada de toda la aplicación
  • Todos los representantes de servicio al cliente hablaban por teléfono con comerciantes e ingresaban un ID o un nombre para buscar su información. Luego iban a una página enorme con toda la información
  • Esa página estaba llena de toda la información necesaria y de todos los enlaces a los que uno querría entrar; era densa de información en el mejor sentido posible. Pero era increíblemente lenta
  • Justin era el único desarrollador senior de mi grupo. Era inteligente, sarcástico y no tenía demasiado interés en el negocio
  • Decía las cosas de frente, no se guardaba nada, y siempre podía resolver solo un problema más rápido que los equipos de alrededor
  • Un día Justin se cansó de escuchar lo lenta que era la página de búsqueda de comerciantes, así que fue y la arregló
  • Cada recuadro de la pantalla se convirtió en su propio endpoint. Al cargar, todo lo que estaba above the fold empezaba a obtenerse, y cuando una cosa terminaba de cargar entraban más requests
  • El tiempo de carga de la página pasó de varios minutos a menos de un segundo

Dos formas de desacoplar

  • Justin pudo hacer eso porque esta base de código no tenía un plan maestro
  • No había un plano general al que el sistema tuviera que ajustarse, ni un formato esperado para la API, ni un sistema de diseño documentado, ni un comité de revisión de arquitectura que garantizara consistencia
  • La aplicación era un desastre total. Nadie podía arreglarla, así que nadie lo intentaba. En vez de eso, construíamos nuestros propios pequeños mundos de cordura
  • Esta app monolítica fue creciendo en los bordes, por pura necesidad, como un microcosmos de buenas apps pequeñas
  • Cada persona encargada de mejorar una parte de la app inevitablemente renunciaba a intentar deshacer esa telaraña, encontraba un rincón bueno y pequeño donde construir algo nuevo, y luego actualizaba lentamente los enlaces para apuntar a lo nuevo y dejar huérfano lo viejo
  • Esto puede sonar desastroso. Pero era sorprendentemente agradable trabajar ahí. Desaparecía la preocupación por la duplicación de código, también la preocupación por la consistencia, y también la preocupación por la escalabilidad
  • El código se escribía para usarse, tocando lo menos posible las áreas de alrededor y de forma que fuera fácil reemplazarlo. Nuestro código estaba desacoplado porque simplemente era más difícil acoplarlo

Después de eso

  • Nunca más en mi carrera he tenido el privilegio de trabajar en una base de código tan maravillosamente fea
  • Todas las bases de código feas que conocí después no lograron trascender la necesidad de consistencia
  • Tal vez porque los desarrolladores "serios" abandonaron la base de código hace mucho tiempo. Lo único que quedó fueron pasantes desordenados y desarrolladores junior
  • O tal vez porque no había una capa intermedia entre los desarrolladores y los usuarios. No había traducción, ni levantamiento de requisitos, ni tarjetas. Solo estabas parado frente al escritorio de una persona de servicio al cliente preguntándole cómo podías mejorar su vida
  • Extraño esa conexión directa. El feedback rápido, no tener que hacer planes grandiosos, la conexión entre problemas simples y código
  • Tal vez sea solo nostalgia ingenua. Pero así como a veces quiero volver a algunos de los peores años de mi juventud, cada vez que me enfrento a los "patrones de diseño empresariales", mi mente vuelve a esa base de código hermosa y terrible

Opinión de GN⁺

  • Este texto puede dar empatía y consuelo a desarrolladores que lidian con sistemas legados. Muestra que incluso una base de código imperfecta puede tener valor y mucho que enseñar
  • Pero no se deben romantizar los problemas de esta base de código. Cuando la deuda técnica se acumula, la velocidad de desarrollo cae mucho y el mantenimiento se vuelve difícil. A largo plazo, cuesta más
  • Renunciar a mejorar la base de código y seguir apilando parches no es la respuesta. Hace falta una estrategia para mejorar gradualmente o migrar el sistema legado
  • La cultura y los procesos de desarrollo también importan. Seguir buenas prácticas de ingeniería, como code review, diseño de arquitectura y documentación, ayuda a construir una mejor base de código
  • La comunicación cercana con los usuarios y el feedback rápido son puntos positivos. Lo ideal es fomentarlos con metodologías como Agile sin dejar de gestionar la calidad del código
  • Al final, todo es una cuestión de equilibrio. Más que perseguir la perfección, lo importante es satisfacer las necesidades de los usuarios de forma sostenible y gestionar la deuda técnica

3 comentarios

 
bus710 2024-08-07

En mi primer trabajo, como desarrollador de firmware, la tarea que me dieron fue analizar el código ensamblador extraído del hex de un MCU 8051 de un producto del que no había desarrolladores ni código fuente, y reimplementarlo en C…
Por suerte había un producto que al menos funcionaba, así que entre revisar el código y probar el producto, de algún modo logré sacarlo adelante…
También llegué a escuchar amenazas de que, o lo arreglaba durante un viaje de trabajo a provincia, o me cortara un dedo antes de volver,
y hubo una vez en que un bug inexplicable resultó que en realidad era por un elevador que estaba detrás de la pared donde estaba instalado el equipo,
y también me acuerdo de haber entrado antes de la apertura oficial del recinto de la cumbre APEC en Dongbaekseom, Busan, para instalar varias cosas jaja

 
GN⁺ 2024-08-04
Opiniones de Hacker News
  • En su primera empresa mantuvo una aplicación compleja en VB

    • Había muchas variables globales adaptadas a los requisitos de cada cliente
    • Un bug no aparecía excepto fuera del modo debug, así que instalaban Visual Studio al cliente y le enseñaban a ejecutarlo en modo debug
    • No había control de versiones y el código se copiaba en varias carpetas, lo que generaba confusión
    • Cuando surgía un problema en un cliente, modificaban el código directamente en sitio
    • No había acuerdo sobre una versión final, así que cada cliente usaba una versión distinta
  • En su primer trabajo dio mantenimiento a un producto legado escrito en COBOL y Java

    • Trabajaban haciendo checkout individual de archivos desde el sistema de control de código fuente
    • Para cada cliente había un archivo jar "maestro" que representaba el producto compilado final
    • Después de cambiar el código, ejecutaban un script para actualizar el archivo jar maestro
    • El codebase completo no compilaba de forma integral y se parchaba manualmente
    • Eso generó muchas inconsistencias en el codebase
    • Tardaron 2 años en migrarlo a git
  • Refactorizó un script de Perl de más de 12,000 líneas

    • La persona que lo escribió no conocía los arreglos y usó strings para implementar arreglos
    • Después del refactor, el código se redujo a 200 líneas
  • Sintió la diferencia entre la teoría y la práctica

    • Muchas empresas y proyectos pasan por procesos parecidos
    • Se discuten métodos ideales, pero en la práctica se avanza con lo que funciona
  • El codebase del cliente de Telegram para Android era extremadamente complejo

    • GitHub dejó de renderizarlo por el tamaño de los archivos
    • Todo el renderizado e interacción de mensajes se manejaba desde una sola clase
    • Le dieron permiso para refactorizarlo, pero no pudo hacerlo
  • En su primer trabajo resolvió un problema de memoria en un proceso de reportes

    • El líder del equipo y su jefe se sorprendieron
    • A los otros desarrolladores no les gustaba Linux y querían cambiarse a .NET
  • Le gustó la experiencia de resolver problemas comunicándose directamente con los clientes

    • Hacía prototipos rápidamente y dejaba que el cliente los probara
    • El codebase era desordenado, pero funcionaba bien
  • Construyó un sistema que daba soporte a varios mercados

    • Copiaron el sistema original para crear una versión internacional
    • Cinco años después, los sistemas no estaban separados, sino enredados entre sí
    • El sistema nuevo y el antiguo estaban estrechamente acoplados
  • En su primer trabajo había muchas personas con poca experiencia

    • Después de ganar experiencia, se fue a un trabajo mejor
  • Explicó cómo resolver problemas en SQL Server moderno

    • Personalización por cliente, IDs compartidos, tablas de calendario manuales, particionado de tablas, réplicas de reportes con retraso, etc.
    • Los codebases mixtos de VB y C# son comunes
    • Se pueden usar herramientas de conversión automática
 
reddiana 2024-08-05

La tabla de numeración (SequenceKey) y la tabla de días hábiles (Calendar)
Qué recuerdos. No sé cómo se hace ahora, pero antes eran tablas de uso común. Cuando hacías proyectos de SI, las funciones relacionadas se implementaban en la parte común del negocio.