14 puntos por GN⁺ 2025-06-26 | 1 comentarios | Compartir por WhatsApp
  • En 1982, el equipo de software de Lisa de Apple introdujo una política para rastrear la cantidad de líneas de código semanales de cada desarrollador con el fin de lanzar el software
  • Bill Atkinson opinaba que la cantidad de líneas de código era una métrica equivocada de la productividad de software
  • Reescribió por completo el motor de cálculo de regiones de Quickdraw, reduciendo alrededor de 2,000 líneas de código y mejorando el rendimiento 6 veces
  • Atkinson escribió -2000 en el formulario de gestión donde se reportaba la cantidad de código
  • Finalmente, los gerentes dejaron de pedirle a Bill que entregara el formulario

El equipo de software de Lisa en 1982 y la política de seguimiento de líneas de código

  • A inicios de 1982, el equipo de software de Lisa comenzó a enfocarse intensamente en lanzar el software dentro de los siguientes 6 meses
  • Algunos gerentes consideraron que rastrear la cantidad de líneas de código que cada ingeniero escribía cada semana ayudaría al avance
  • Para ello, introdujeron un formulario en el que cada viernes los ingenieros debían registrar y entregar la cantidad de líneas de código escritas

La postura de Bill Atkinson sobre los criterios de productividad

  • Bill Atkinson, quien diseñó Quickdraw y la interfaz de usuario, pensaba que la cantidad de líneas de código no podía ser un criterio de productividad de software
  • Enfatizaba que el objetivo era hacer los programas lo más pequeños y rápidos posible
  • Reconocía el problema de que medir las líneas de código podía, por el contrario, fomentar código desordenado e ineficiente

Refactorización y optimización del motor de regiones de Quickdraw

  • Atkinson había reescrito recientemente por completo el motor de cálculo de regiones de Quickdraw con un algoritmo más simple y general
  • Como resultado de la optimización, mejoró la velocidad de las operaciones de regiones hasta 6 veces
  • En el proceso, también se redujeron de forma natural 2,000 líneas de código

El reporte de -2000 líneas de código y la reacción de los gerentes

  • Mientras llenaba el formulario de gestión de la primera semana, Atkinson escribió -2000 en la casilla de cantidad de líneas de código
  • No está claro cómo reaccionaron los gerentes ante esa cifra
  • Unas semanas después, le dijeron a Bill que ya no entregara más el formulario, y él lo recibió con gusto

1 comentarios

 
GN⁺ 2025-06-26
Comentarios en Hacker News
  • El mejor commit que recuerdo fue una vez que borré unas 60 mil líneas de código y reemplacé por completo un “servidor” que guardaba todo el estado en memoria por una lógica ligera de unas 5 mil líneas

    • Me parece una proeza algorítmica, porque ese código era lo bastante liviano como para integrarse de forma natural en otros servicios y además ya no necesitaba estado en memoria
    • Fue el proceso de descubrir que se podía resolver un problema de isomorfismo guiado de subgrafos para un árbol específico, y gracias a eso construir el grafo de salida (árbol) recorriendo una sola vez un digrafo general y rastreando solo con una pequeña pila las rutas desde la raíz de partida
    • Ese “commit de -60,000 líneas” de verdad fue un momento inolvidable, y desde entonces me queda la sensación de no haber vuelto a hacer algo tan impresionante a nivel algorítmico
      • Soy un programador aficionado que hace mucho scripting en el trabajo y siente que domina algunas partes de la programación, pero cada vez que escucho historias así vuelvo a sentir humildad al darme cuenta de lo enorme que es el mundo que desconozco y de que no alcanzaría una vida para aprenderlo todo
      • Me gustaría escuchar más contexto. La idea de convertir un programa con estado en uno sin estado me parece magia, así que me da mucha curiosidad aprenderlo
      • Soy matemático con formación en teoría de grafos y algoritmos, y me pregunto si mis habilidades podrían aplicarse a este tipo de trabajo real. ¿Podrías compartir más detalles?
      • Creo que el hecho de que el grafo objetivo sea un árbol no es tan importante. El punto clave me parece que es la parte “guiada”, que es lo que hace posible una sola pasada
        • Se asume que, al partir de cierto nodo en el grafo original, si existe un isomorfismo entonces la raíz del árbol objetivo también debe corresponder a ese nodo
        • Se puede interpretar el problema como recorrer el grafo original según el patrón del árbol objetivo, devolviendo false si hay un desacuerdo y true si todo coincide. La inferencia es que, incluso si no fuera un árbol, este enfoque podría aplicarse a cualquier subgrafo si el punto de inicio está claramente fijado
      • Un chiste dice que quizá justamente este tipo de programadores fue el origen de esas preguntas de entrevista tipo “invierte un árbol binario”
        • Me interesa la teoría de grafos, pero la terminología es difícil. ¿Podrían dar una explicación sencilla para un desarrollador común?
  • En la universidad trabajé para una empresa cuya política gerencial decía que los recién contratados podían escribir buen código, y al final fueron un caso de fracaso no demostrado

    • Una vez seguía apareciendo el mismo bug incluso después de corregirlo en el código, y al analizarlo descubrí que en lugar de agregar parámetros a una función existente hacían copias del código y las modificaban apenas un poco. El resultado fue que terminé borrando más de tres cuartas partes del codebase, miles de líneas de Turbo Pascal
    • El cliente del proyecto era el departamento de Energy y el programa administraba inventario de material nuclear, así que recuerdo varias noches de insomnio
      • En tono sarcástico, se menciona que una ventaja de copiar código existente es que no arruinas la estabilidad del código previo y además cuidas la métrica de “contribución” del gerente. Y para hacer revert, basta con borrar la copia
      • En nuestro equipo también hay un colega que duplica código con frecuencia, y creo que es el hábito que se forma para entregar resultados rápidos ante pedidos urgentes o gente que hace mucho ruido. En el fondo, el problema es no querer invertir tiempo en refactorizar funciones compartidas y hacer suficientes pruebas
      • Los desarrolladores externos que tuve hace años también mostraban ese hábito, y cuando les señalé que eso podía generar confusión me respondieron: “para eso está Ctrl+F”
      • Alguien pregunta si ese caso ocurrió en la zona de Blacksburg
      • Mi experiencia fue parecida: trabajé en una empresa que operaba portales casi idénticos en varios países del sudeste asiático. El código fuente de cada portal estaba en un repositorio Git separado, y cualquier feature o corrección de bugs que debía aplicarse a todos los portales había que backportearla a mano en múltiples copias del código
        • Pregunté si no podían meter todo en un solo repositorio y manejar las personalizaciones de cada portal con feature flags, pero me dijeron que no era posible
        • Al final, en dos o tres meses unifiqué el código de 4 o 5 portales en un solo repositorio, apliqué feature flags y actualicé el framework, y el despliegue salió sin problemas. Desde entonces fue posible corregir bugs en todos los portales al mismo tiempo, y se sintió como liberarse del sufrimiento del trabajo manual repetitivo
  • Sobre este tema relacionado, alguien recopiló populares hilos de Hacker News sobre “-2000 líneas de código” en este enlace

    • Señala que es una tradición útil que periódicamente se vuelvan a publicar obras maestras del pasado, tanto para usuarios nuevos como para los de siempre
      • Yo soy una persona simple: si veo “-2k lines of code”, automáticamente le doy voto positivo
        • A clientes que intentan administrar la productividad como una métrica de un solo eje les cuento seguido el caso de Atkinson. La verdadera métrica de productividad debería ser la utilidad, y si alguien lograra cuantificarla de verdad probablemente merecería una nominación al Nobel de Economía
  • El proyecto de web UI del que me encargué tenía 250 mil líneas de código, sin contar el backend

    • El desarrollador anterior era inteligente, pero era su primera vez con JS y guardaba todo el estado en atributos personalizados del DOM, con una estructura saturada de addEventListener. Yo bromeaba diciendo que este código es lo que sale si le das a un monje un libro de JavaScript y 10 años de aislamiento
    • Después de varios meses transformando la estructura con web components, eliminé 50 mil líneas, y empecé una reescritura completa. Ahora mismo solo he llegado a aproximadamente el 80% de la misma funcionalidad, pero todo el código pesa unas ligeras 17 mil líneas, sin incluir librerías como Vue/pinia
    • Pronto habré borrado más de 200 mil líneas, y siento que nunca volveré a vivir algo así, como si ya pudiera retirarme
      • Yo viví algo similar: la persona que hizo el original tenía habilidades casi de junior, pero era fundador de la empresa y muy productivo. Como desarrolló sin experiencia de trabajo en equipo ni de colaborar con código ajeno, la estructura tenía todos los code smells imaginables
        • Funciones de miles de líneas, 10 niveles de switch/case/if/else/ternary, SQL mezclado con JS/HTML/HTML con JS incrustado, y cero pruebas automatizadas: así era ese frontend de la era PHP/Dojo
      • Alguien señala que la propia frase “código ligero con solo 80% de la funcionalidad” muestra la trampa de esta comparación. Si todavía implementa solo parte de las funciones, naturalmente no necesita tantas líneas como el código original
  • En una tira de Dilbert hay una escena sobre una estructura de recompensas sin límite: el jefe de Dilbert promete una recompensa monetaria por arreglar un bug, y Wally dice: “¡Hoy yo también voy a programar una minivan!”

    • A esta situación se le llama “Perverse incentive”, y lo explican en este enlace de referencia
    • Mi gerente también tenía esta historieta ( imagen ) pegada en la pared del área de descanso
    • Aparece la duda práctica de qué significa exactamente “minivan”
  • Se comparte un caso real de haber borrado 64 mil líneas en el repositorio dotnet/runtime

    • Se reemplazó el soporte integrado de interop entre C# y WinRT por una herramienta de generación de código, en un cambio estructural que requería la decisión de hacerlo de una vez y de manera contundente. Ver este PR
  • Cada vez que veo estadísticas sobre cuánto han aumentado la productividad de los desarrolladores los LLM, me acuerdo de esta historia clásica

    • Como contraargumento, alguien dice que la IA también es bastante buena para borrar código, y comparte un caso divertido en la comunidad de Cursor donde “la IA borró todo”
    • Últimamente, “¡X% de nuestro código nuevo lo escribe la IA!” es una de las frases favoritas de la industria
    • Si se incluyera incluso el costo de construir y mantener nuevas plantas de energía nuclear, quedaría en evidencia lo absurdamente infladas que están esas cifras de productividad de desarrolladores
  • Yo no estudié CS y trabajo con conocimientos que aprendí en la práctica

    • Nuestro proyecto busca reestructurar live objects para que sean fáciles de leer por humanos
      • La representación final requiere muchos tipos complejos, mientras que la representación inicial es relativamente simple
      • Cuando había nodos de datos similares, había que compararlos y fusionarlos —es decir, extraer métodos y descubrir parámetros— para mejorar la legibilidad
        • Al principio convertíamos primero a los tipos finales y luego comparábamos, lo que hizo explotar la cantidad de combinaciones de tipos hasta volverla casi inmanejable, alcanzando un nivel de complejidad tal que durante años los ingenieros no podían entender la estructura
      • Después conocí un enfoque basado en hashmap, y apliqué una estructura de dos etapas: distinguir los nodos con el mismo esqueleto por su hash, compararlos y fusionarlos, y solo después convertirlos al tipo final
      • Gracias a cambiar de una abstracción centrada en tipos a una centrada en datos, hasta jerarquías de clases absurdas se pudieron manejar fácilmente como propiedades simples
      • En resumen, era una estructura tonta de decompilador multinivel, pero mejoró mucho tanto la velocidad de procesamiento como la legibilidad. No hay bala de plata universal, pero en nuestro caso el problema central eran los “tipos”, y esta forma de resolverlo ayudó muchísimo
  • Antes de la evaluación anual de fin de año vi mis estadísticas en el monorepo de la empresa y descubrí que, en términos netos, me había convertido en una persona con líneas de código negativas

    • Se debía a cosas como eliminar código autogenerado de API y tipos, y retirar APIs antiguas, pero se sentía curiosamente agradable ir a trabajar todos los días solo a borrar código
  • Hace mucho me impactó un caso lamentable de KPI en un gran proyecto, donde los líderes técnicos llevaban a mano y publicaban en la pared la cantidad de bugs por desarrollador, tanto bugs corregidos como bugs causados

    • Yo me salvé porque estaba en un proyecto relacionado, pero un colega, inspirado en la anécdota del director Lars von Trier, que quedó fuera de la “lista de autores” de un burócrata después de recortar la parte de la cruz de la bandera danesa y volver a coserla como una especie de bandera roja comunista, recortó su propia fila del conteo de bugs, la volvió a pegar y protestó públicamente. Al día siguiente la lista desapareció para siempre, y para mí quedó como un recuerdo valioso
      • “¡Porque yo no quiero estar en esta lista!” fue la respuesta simple y directa del colega, y resume muy bien toda la situación
      • También se comparte la dificultad práctica de imaginar cómo se veía visualmente esa bandera y esa lista