1 puntos por GN⁺ 2024-03-25 | 1 comentarios | Compartir por WhatsApp
  • A principios de 1982, bajo la presión de lanzar en seis meses, el equipo de software de Lisa intentó medir el avance por la cantidad de líneas de código semanales de cada ingeniero
  • Bill Atkinson consideraba que la cantidad de líneas no reflejaba correctamente la productividad y que además iba en contra del objetivo de crear programas pequeños y rápidos
  • Al reescribir el motor de cálculo de regiones de QuickDraw con un algoritmo más simple y general, las operaciones sobre regiones se volvieron casi 6 veces más rápidas y el código se redujo en unas 2,000 líneas
  • En el primer formulario de gestión, en el campo que preguntaba cuántas líneas de código había escrito esa semana, Bill anotó -2000, dejando en evidencia la falla del método de medición
  • Unas semanas después, los gerentes ya no le pidieron a Bill que llenara ese formulario, y la anécdota muestra cómo la gestión basada en líneas de código puede pasar por alto mejoras reales

Medición de líneas de código en el equipo Lisa

  • A principios de 1982, el equipo de software de Lisa intentaba acelerar el trabajo para lanzar el software dentro de los siguientes seis meses
  • Algunos gerentes querían seguir el avance según la cantidad de líneas de código que cada ingeniero escribía por semana
  • Los ingenieros recibieron un formulario para entregar cada viernes, que incluía un campo para anotar la cantidad de líneas de código escritas esa semana

El -2000 de Bill Atkinson

  • Bill Atkinson, autor de QuickDraw y uno de los principales diseñadores de la interfaz de usuario, desempeñaba un papel importante en la implementación de Lisa
  • Bill consideraba que la métrica de líneas de código no medía correctamente la productividad
    • Pensaba que el objetivo de un buen software era escribir programas lo más pequeños y rápidos posible
    • Una métrica que premia aumentar la cantidad de líneas podía incentivar la escritura de código descuidado, inflado y defectuoso
  • En ese momento estaba optimizando el motor de cálculo de regiones de QuickDraw
    • Reescribió por completo el motor de regiones con un algoritmo más simple y general
    • Después del ajuste, las operaciones sobre regiones se volvieron casi 6 veces más rápidas
    • Al mismo tiempo, el código se redujo en unas 2,000 líneas
  • Al llenar el primer formulario de gestión, miró por un momento el campo de líneas de código y escribió -2000
  • No se sabe con certeza cómo reaccionaron los gerentes, pero unas semanas después dejaron de pedirle a Bill que entregara el formulario

1 comentarios

 
GN⁺ 2024-03-25
Opiniones de Hacker News
  • Me recuerda el caso del choque por la cantidad de líneas de código entre Microsoft e IBM
    En la serie de TV de PBS basada en Accidental Empires, de Bob Cringely, hay una escena en la que Steve Ballmer describe su experiencia desarrollando OS/2 junto con IBM
    Microsoft tenía una actitud de empresa chica, enfocada en terminar las cosas, mientras que IBM estaba concentrada en métricas internas, en particular en medir la productividad de los programadores en KLoC (miles de líneas de código)
    Ballmer dijo: “Lo único que les importaba era KLoC, KLoC y más KLoC”, y parece que IBM se fijaba más en la cantidad que en si el código era bueno
    https://ubiquity.acm.org/article.cfm?id=1022357

    • IBM no era la única. Hace unos años trabajé en un gran proyecto cuyo contratista principal era una gran consultora internacional, y cuando la base de código superó 1 millón de líneas, hicieron una fiesta para todo el equipo
      Quienes sabían lo que pasaba recibieron esa “celebración” como si fuera un funeral
    • La serie de TV a la que se refieren aquí es Triumph of the Nerds, y sigue siendo excelente hoy. Quizás incluso valga más la pena verla ahora
  • Contar líneas de código como métrica de productividad es realmente absurdo
    Una vez arreglé con una sola línea de código un bug de 20 años que no se había podido resolver, y recuerdo haber solucionado un bug de 3 años con un solo order by. ¿Cómo se puede medir el impacto de una línea de código? Según mi experiencia, los malos programadores escriben mucho más código
    Tampoco puedo olvidar la historia[1] de un desarrollador de Microsoft que reescribió código de IBM de 33 mil caracteres y lo redujo a 220. Como resultado, la cantidad de trabajo de Microsoft quedó en “negativo” y eso desató una guerra
    [1] https://archive.org/details/bigbluesunmaking00carr/page/4/mode/2up página 101

    • Usar métricas de productividad en sí suele ser una tontería, y es una forma fácil de hacer que los desarrolladores optimicen las métricas en vez de hacer buen trabajo
      Un ejemplo actual son las empresas que usan el “impacto”, es decir, el lanzamiento de nuevos productos, como criterio de ascenso. Eso facilita que aparezcan montones de productos fallidos que nadie mantiene
    • Seguramente hay ingenieros que corrigen un bug crítico cada pocos meses y generan millones de dólares de valor, pero en general los buenos ingenieros producen mucho, y los ingenieros que producen poco muchas veces no son tan buenos
    • A largo plazo, creo que hay cierta relación entre las líneas de código y el resultado de ingeniería
      Entre los grandes científicos de la computación e ingenieros hubo personas con una producción enorme de código, y creo que eso se traduce directamente en impacto de alguna forma. El problema aparece en el momento en que las líneas de código se convierten en la métrica de desempeño
      Ahí aplica la ley de Goodhart: “cuando una medida se convierte en objetivo, deja de ser una buena medida”
    • Como muestran los ejemplos, una de las razones por las que las líneas de código son una mala métrica de productividad es que representan bastante bien el tamaño de la carga que asumen quienes mantienen la base de código
      Desde el punto de vista de una métrica de productividad, el código se clasifica como un activo, pero una visión más cercana a la realidad es que la funcionalidad es el activo y el código en sí es una deuda
  • Este tema aparece con frecuencia. Las discusiones anteriores son estas:
    https://news.ycombinator.com/item?id=33483165 (2022)
    https://news.ycombinator.com/item?id=26387179 (2021)
    https://news.ycombinator.com/item?id=10734815 (2015)
    https://news.ycombinator.com/item?id=7516671 (2014)
    https://news.ycombinator.com/item?id=4040082 (2012)
    https://news.ycombinator.com/item?id=1114223 (2010)
    https://news.ycombinator.com/item?id=1545452 (2010)

  • Al principio de mi carrera, una vez optimicé un programa en C de más de 10 mil líneas que había heredado y lo dejé en menos de 500 líneas. Era un programa en C que hacía llamadas SQL a una base de datos Sybase
    No fue por una gran revelación, sino por la simple suposición de que quizá mi antecesor no sabía usar funciones ni parámetros para insertar datos variables en consultas SQL. En efecto, había escrito la misma sentencia SQL en línea una y otra vez, cambiando solo algunos valores
    Reescribí el código de las llamadas SQL como llamadas a funciones e hice que las variables bind se pasaran como parámetros de función. El código en línea repetido fue reemplazado por una llamada a la función dentro de un loop, tomando de un arreglo los valores bind que cambiaban

  • El mayor impacto a veces viene de hacer una pregunta simple como “¿Cómo vamos a manejar X?”, y así evitar que algo se construya por completo.
    Si ese algo ni siquiera habría tenido la oportunidad de funcionar correctamente, entonces te ahorraste todo el costo de intentar construirlo.
    Esto no solo es imposible de medir con métricas numéricas, sino que también puede ganarte enemigos. Aun así, aplaudo a quienes se atreven a hacerlo.

    • Por eso les enseño a los recién llegados a tener ese loop en la cabeza y a no empezar por teclear rápido.
      Las personas que ven la programación como algo parecido a tipear rápido tienen una similitud interesante con los LLM: escriben todo el código mal planteado, lo borran, lo vuelven a escribir y lo vuelven a borrar.
    • Cuando gestionaba software en una gran empresa, tenía una caja de lápices sobre el escritorio.
      Más o menos la mitad de las solicitudes de información que llegaban al departamento siempre venían con el tono de “es muy importante, lo necesitamos ahora mismo y puede generar o ahorrar mucho dinero”, pero la respuesta obvia era: “Calcúlenlo con la información que ya tienen. Tienen calculadoras y hojas de cálculo. ¿Les presto un lápiz?”.
      Es mejor evitarlo que hacer que el sistema maneje X. Los casos especiales que quizá se usen una o dos veces inflan el sistema, y nadie sabe si esos casos especiales o programas existen, ni qué hacen realmente. Aunque estén bien documentados, nadie dedica tiempo a aprender qué es posible. Por eso, la mayoría de esas funciones especiales terminan siendo una pérdida de tiempo.
  • Como experimento mental correspondiente, se puede pensar en la situación opuesta. Si un gerente leyera este artículo y decidiera medir simplemente por la cantidad de líneas de código eliminadas, ¿las cosas mejorarían o empeorarían?

    • Según la empresa y la forma de medir, podría manipularse con más facilidad. Bastaría con pedirle a llama que genere código plausible, agregar un poco de código para que no tenga efecto real y commitearlo, y luego borrarlo más adelante.
      Este tipo de medición es casi inútil si no existen prácticas de revisión de código sólidas en general. A diferencia de lo que la gente aquí quiere creer, esas prácticas son raras. Pero si hay buenas revisiones, también se detectan el bajo rendimiento y la manipulación de métricas, así que hay menos razones para introducir este tipo de métrica en primer lugar.
    • Sería un poco peor, pero quizá no tan desastroso como uno pensaría. La industria ya tiene impulsos miope similares en esa dirección.
      Por ejemplo, existe desde hace tiempo la idea de eliminar por completo a los ingenieros de software y el texto de código incomprensible, y reemplazarlos con gerentes de producto que dibujen diagramas especiales o diagramas de flujo para crear resultados “low-code” o “no-code”.
    • Hay que desconfiar de todas las métricas basadas en cantidad de líneas, pero ΔSLOC probablemente sea de las menos malas.
      Contaría por separado las líneas agregadas y eliminadas, de modo que un parche +50,-150 se calcularía como 200 ΔSLOC.
      No es una buena medida de productividad, y menos aún por sí sola. Aun así, como métrica de cálculo aproximado para estimar el volumen de cambios, es razonable. Que un desarrollador con ΔSLOC alto sea más productivo que un colega que no tuvo ningún ΔSLOC durante 1 o 2 semanas depende de qué esté haciendo ese colega, pero sí es claro que el primero está modificando más la base de código durante el período medido.
    • Empeoraría. No es deseable convertir toda la base de código en un objetivo de code golf.
    • Definitivamente no habría funciones nuevas.
      Si el producto ya estuviera “terminado”, podría ser igual o incluso mejor. Si no, los cambios con líneas de código negativas no llegarían a producción.
      Pero la mayoría de los productos siguen evolucionando. Por eso podemos permanecer años en el mismo proyecto, y una contribución que solo elimina cosas al final no agrega nada.
  • La historia real es que, cuando se inicia un proyecto, a veces no se sabe exactamente hacia dónde se va.
    A medida que avanzas, entiendes mucho mejor el problema y la respuesta que quieres, y entonces puedes arrancar bloques grandes y reemplazarlos por algo más pequeño y mejor.
    Y no hay que olvidar que estas personas tenían que meterlo todo en una ROM de 64 KB, incluyendo -2000 líneas de código, incluso código en ensamblador. La presión por hacerlo más pequeño era muy fuerte.

  • Es Bill Atkinson, famoso por el dithering de Atkinson. https://beyondloom.com/blog/dither.html

    • Bill Atkinson creó QuickDraw, la biblioteca gráfica que fue la base de la UI de Lisa y la Mac, además de MacPaint y HyperCard.
      En ese proceso tuvo que seguir inventando nuevas formas en que funcionaba la interfaz de usuario y maneras de escribir software para resolverlas. Optimizó al mismo tiempo para que “pudiera ejecutarse rápido en el hardware de la Mac” y para que “ofreciera una gran experiencia de usuario”, y esa sinergia dejó su huella en toda la estética de las antiguas Mac en blanco y negro. Ese estilo de dithering también es otro ejemplo de la combinación de genio algorítmico y sensibilidad estética.
      Esa sensibilidad también se ve en cosas como el borde de selección “marching ants” (https://en.wikipedia.org/wiki/Marching_ants). Lo mismo ocurre con gran parte del feedback de la UI clásica de Mac, que se expresaba invirtiendo píxeles: la selección de texto, el resaltado de menús, la forma en que se veía un botón mientras se mantenía presionado el botón del mouse, los bordes al arrastrar una ventana, etc. Dibujar encima en modo XOR era una muy buena manera de crear esos efectos.
      La forma en que QuickDraw combinó estas herramientas llevó a que la famosa conversación con Steve Jobs sobre los rectángulos redondeados (https://www.folklore.org/Round_Rects_Are_Everywhere.html) terminara, en la práctica, haciendo que dibujar rectángulos redondeados en QuickDraw fuera tan fácil como dibujar rectángulos, y eso hizo que aparecieran rectángulos redondeados por todo el sistema operativo.
      El éxito de la UI de la Mac no se debió solo a que se viera bien. En gran parte fue porque Bill Atkinson creó un conjunto de herramientas pequeñas e inteligentes que facilitaban hacer cosas que se veían bien.
      Los excelentes íconos de Susan Kare tampoco se recordarían con tanto cariño si Bill no hubiera creado herramientas que permitían insertar fácilmente en la UI bitmaps de máscara de 32x32 píxeles e invertirlos al hacer clic.
  • La lección es que, aunque seas tan inteligente como Einstein, al final eres empleado, y como empleado tienes que hacer lo que te corresponde.

    • Si Einstein hubiera estado bajo presión por métricas, nunca habríamos escuchado su nombre.
  • Nunca entendí por qué, cuando la gente habla de líneas de código escritas, siempre las calcula como “líneas agregadas - líneas eliminadas”.
    Que yo haga una carrera de 10 km y vuelva al punto de partida no significa que corrí 0 km.

    • En parte, quizá sea porque herramientas de diff tontas pueden registrar como un gran cambio incluso mover líneas de un lado a otro, aunque el cambio funcional sea limitado.
      Por ejemplo, cambiar una forma if cond { ... return; } ... por if cond { ... return; } else { .... }.
      Aun así, esa explicación no lo abarca todo.