Los errores más vergonzosos en mi carrera de programación (hasta ahora)

Los errores más vergonzosos en mi carrera de programación (hasta ahora)
Como dicen, si no te avergüenzas de tu antiguo código, entonces no estás creciendo como programador, y estoy de acuerdo con esta opinión. Empecé a programar por diversión hace más de 40 años y profesionalmente hace 30 años, así que cometo muchos errores. mucho. Como profesor de informática, enseño a mis alumnos a aprender de los errores: los suyos, los míos y los de otros. Creo que es hora de hablar de mis errores para no perder el pudor. Espero que le sean útiles a alguien.

Tercer lugar: compilador de Microsoft C

Mi maestra de escuela creía que Romeo y Julieta no podían considerarse una tragedia porque los personajes no tenían culpa trágica: simplemente se comportaban estúpidamente, como deberían hacerlo los adolescentes. Entonces no estaba de acuerdo con él, pero ahora veo una pizca de racionalidad en su opinión, especialmente en relación con la programación.

Cuando terminé mi segundo año en el MIT, era joven e inexperto, tanto en la vida como en programación. En el verano, hice una pasantía en Microsoft, en el equipo del compilador de C. Al principio hice cosas rutinarias como soporte de creación de perfiles, y luego me confiaron trabajar en la parte más divertida del compilador (como pensaba): la optimización del backend. En particular, tuve que mejorar el código x86 para declaraciones de rama.

Decidido a escribir el código de máquina óptimo para cada caso posible, me lancé de cabeza a la piscina. Si la densidad de distribución de los valores era alta, los ingresaba en tabla de transición. Si tenían un divisor común, lo usaba para hacer la tabla más ajustada (pero sólo si la división se podía hacer usando cambio de bits). Cuando todos los valores eran potencias de dos, hice otra optimización. Si un conjunto de valores no cumplía mis condiciones, lo dividía en varios casos optimizables y utilizaba el código ya optimizado.

Fue una pesadilla. Muchos años después me dijeron que el programador que heredó mi código me odiaba.

Los errores más vergonzosos en mi carrera de programación (hasta ahora)

Lección aprendida

Como escriben David Patterson y John Hennessy en Computer Architecture and Computer Systems Design, uno de los principios fundamentales de la arquitectura y el diseño es, en general, hacer que las cosas funcionen lo más rápido posible.

Acelerar los casos comunes mejorará el rendimiento de manera más efectiva que optimizar los casos raros. Irónicamente, los casos comunes suelen ser más simples que los raros. Este consejo lógico supone que usted sabe qué caso se considera común, y esto sólo es posible mediante un proceso de pruebas y mediciones cuidadosas.

En mi defensa, traté de averiguar cómo se veían las declaraciones de rama en la práctica (como cuántas ramas había y cómo se distribuían las constantes), pero en 1988 esta información no estaba disponible. Sin embargo, no debería haber agregado casos especiales cuando el compilador actual no podía generar código óptimo para el ejemplo artificial que se me ocurrió.

Necesitaba llamar a un desarrollador experimentado y, junto con él, pensar en cuáles eran los casos más comunes y tratarlos específicamente. Escribiría menos código, pero eso es algo bueno. Como escribió el fundador de Stack Overflow, Jeff Atwood, el peor enemigo de un programador es el propio programador:

Sé que tienes las mejores intenciones, como todos nosotros. Creamos programas y nos encanta escribir código. Así estamos hechos. Creemos que cualquier problema se puede solucionar con cinta adhesiva, una muleta casera y una pizca de código. Por mucho que a los programadores les cueste admitirlo, el mejor código es el código que no existe. Cada nueva línea necesita depuración y soporte, es necesario comprenderla. Cuando agrega código nuevo, debe hacerlo con desgana y disgusto porque todas las demás opciones se han agotado. Muchos programadores escriben demasiado código, lo que lo convierte en nuestro enemigo.

Si hubiera escrito un código más simple que cubriera casos comunes, habría sido mucho más fácil actualizarlo si fuera necesario. Dejé atrás un desastre con el que nadie quería lidiar.

Los errores más vergonzosos en mi carrera de programación (hasta ahora)

Segundo lugar: publicidad en redes sociales

Cuando trabajaba en Google en publicidad en redes sociales (¿recuerdas Myspace?), escribí algo como esto en C++:

for (int i = 0; i < user->interests->length(); i++) {
  for (int j = 0; j < user->interests(i)->keywords.length(); j++) {
      keywords->add(user->interests(i)->keywords(i)) {
  }
}

Los programadores pueden ver inmediatamente el error: el último argumento debería ser j, no i. Las pruebas unitarias no revelaron el error, ni tampoco mi revisor. El lanzamiento se llevó a cabo y una noche mi código fue al servidor y bloqueó todas las computadoras en el centro de datos.

No pasó nada malo. A nadie le salió nada mal, porque antes del lanzamiento global el código se probó en un centro de datos. A menos que los ingenieros de SRE dejaran de jugar al billar por un tiempo y retrocedieran un poco. A la mañana siguiente recibí un correo electrónico con un volcado de memoria, corregí el código y agregué pruebas unitarias que detectarían el error. Como seguí el protocolo (de lo contrario, mi código simplemente no se ejecutaría) no hubo otros problemas.

Los errores más vergonzosos en mi carrera de programación (hasta ahora)

Lección aprendida

Muchos están seguros de que un error tan grave definitivamente le costará el despido al culpable, pero no es así: en primer lugar, todos los programadores cometen errores y, en segundo lugar, rara vez cometen el mismo error dos veces.

De hecho, tengo un amigo programador que era un ingeniero brillante y fue despedido por cometer un solo error. Después de eso, fue contratado en Google (y pronto ascendido); habló honestamente sobre el error que cometió en una entrevista y no se consideró fatal.

Esto es lo que decir sobre Thomas Watson, el legendario director de IBM:

Se anunció un pedido gubernamental por valor de aproximadamente un millón de dólares. IBM Corporation, o mejor dicho, personalmente Thomas Watson Sr., tenía muchas ganas de conseguirlo. Desafortunadamente, el representante de ventas no pudo hacerlo e IBM perdió la oferta. Al día siguiente, este empleado entró en la oficina del Sr. Watson y colocó un sobre en su escritorio. El Sr. Watson ni siquiera se molestó en mirarla: estaba esperando a un empleado y sabía que era una carta de renuncia.

Watson preguntó qué salió mal.

El representante de ventas habló en detalle sobre el avance de la licitación. Mencionó errores cometidos que podrían haberse evitado. Finalmente dijo: “Señor Watson, gracias por permitirme explicarle. Sé cuánto necesitábamos este pedido. Sé lo importante que era”, y se dispuso a partir.

Watson se acercó a él en la puerta, lo miró a los ojos y le devolvió el sobre con las palabras: “¿Cómo puedo dejarte ir? Acabo de invertir un millón de dólares en tu educación.

Tengo una camiseta que dice: “Si realmente se aprende de los errores, entonces ya soy un maestro”. De hecho, cuando se trata de errores, soy doctor en ciencias.

Primer lugar: API de App Inventor

Errores verdaderamente terribles afectan a un gran número de usuarios, se vuelven de conocimiento público, tardan mucho en corregirse y son cometidos por quienes no podrían haberlos cometido. Mi mayor error se ajusta a todos estos criterios.

Cuanto peor, mejor

Yo leo ensayo de Richard Gabriel sobre este enfoque en los años noventa como estudiante de posgrado, y me gusta tanto que se lo pregunto a mis alumnos. Si no lo recuerdas bien refresca la memoria, es pequeño. Este ensayo contrasta el deseo de “hacer las cosas bien” y el enfoque de “peor es mejor” de muchas maneras, incluida la simplicidad.

Cómo debería ser: el diseño debe ser simple en implementación e interfaz. La simplicidad de la interfaz es más importante que la simplicidad de la implementación.

Cuanto peor, mejor: el diseño debe ser simple en implementación e interfaz. La simplicidad de la implementación es más importante que la simplicidad de la interfaz.

Olvidémonos de eso por un minuto. Desafortunadamente, lo olvidé durante muchos años.

Inventor de aplicaciones

Mientras trabajaba en Google, fui parte del equipo. Inventor de aplicaciones, un entorno de desarrollo en línea de arrastrar y soltar para aspirantes a desarrolladores de Android. Era 2009 y teníamos prisa por lanzar la versión alfa a tiempo para que en el verano pudiéramos realizar clases magistrales para profesores que pudieran utilizar el entorno al enseñar en el otoño. Me ofrecí como voluntario para implementar sprites, nostálgico de cómo solía escribir juegos en la TI-99/4. Para aquellos que no lo saben, un sprite es un objeto gráfico bidimensional que puede moverse e interactuar con otros elementos de software. Ejemplos de sprites incluyen naves espaciales, asteroides, canicas y raquetas.

Implementamos App Inventor orientado a objetos en Java, por lo que solo hay un montón de objetos allí. Dado que las bolas y los sprites se comportan de manera muy similar, creé una clase de sprite abstracta con propiedades (campos) X, Y, Speed ​​(velocidad) y Heading (dirección). Tenían los mismos métodos para detectar colisiones, rebotar en el borde de la pantalla, etc.

La principal diferencia entre una bola y un sprite es qué se dibuja exactamente: un círculo relleno o una trama. Dado que implementé sprites primero, era lógico especificar las coordenadas xey de la esquina superior izquierda de donde se encontraba la imagen.

Los errores más vergonzosos en mi carrera de programación (hasta ahora)
Una vez que los sprites estuvieron funcionando, decidí que podía implementar objetos bola con muy poco código. El único problema fue que tomé la ruta más simple (desde el punto de vista del implementador), indicando las coordenadas xey de la esquina superior izquierda del contorno que enmarca la pelota.

Los errores más vergonzosos en mi carrera de programación (hasta ahora)
De hecho, era necesario indicar las coordenadas xey del centro del círculo, como se enseña en cualquier libro de texto de matemáticas y en cualquier otra fuente que mencione círculos.

Los errores más vergonzosos en mi carrera de programación (hasta ahora)
A diferencia de mis errores pasados, este afectó no sólo a mis colegas, sino también a millones de usuarios de App Inventor. Muchos de ellos eran niños o completamente nuevos en la programación. Tuvieron que realizar muchos pasos innecesarios al trabajar en cada aplicación en la que estaba presente la pelota. Si recuerdo mis otros errores con risas, este me hace sudar incluso hoy.

Finalmente solucioné este error recientemente, diez años después. “Parcheadas”, no “reparadas”, porque como dice Joshua Bloch, las API son eternas. Al no poder realizar cambios que afectarían los programas existentes, agregamos la propiedad OriginAtCenter con el valor falso en los programas antiguos y verdadero en todos los futuros. Los usuarios pueden hacer una pregunta lógica: ¿a quién se le ocurrió colocar el punto de partida en otro lugar que no fuera el centro? ¿A quien? Para un programador que era demasiado vago para crear una API normal hace diez años.

Lecciones aprendidas

Cuando trabaje en API (lo que casi todos los programadores tienen que hacer a veces), debe seguir los mejores consejos descritos en el video de Joshua Bloch "Cómo crear una buena API y por qué es tan importante"O en esta breve lista:

  • Una API puede traerle grandes beneficios y grandes daños.. Una buena API genera clientes habituales. El malo se convierte en tu eterna pesadilla.
  • Las API públicas, como los diamantes, duran para siempre. Dalo todo: nunca habrá otra oportunidad de hacer todo bien.
  • Los esquemas de API deben ser breves - una página con firmas y descripciones de clases y métodos, que no ocupa más de una línea. Esto le permitirá reestructurar fácilmente la API si no resulta perfecta la primera vez.
  • Describir casos de usoantes de implementar la API o incluso trabajar en su especificación. De esta forma evitará implementar y especificar una API completamente no funcional.

Si hubiera escrito aunque fuera una breve sinopsis con un guión artificial, lo más probable es que hubiera identificado el error y lo hubiera corregido. Si no, uno de mis colegas definitivamente lo haría. Cualquier decisión que tenga consecuencias de gran alcance debe reflexionarse al menos durante un día (esto se aplica no sólo a la programación).

El título del ensayo de Richard Gabriel, "Lo peor es mejor", se refiere a la ventaja que supone ser el primero en llegar al mercado (incluso con un producto imperfecto) mientras otro pasa una eternidad persiguiendo el producto perfecto. Al reflexionar sobre el código del sprite, me doy cuenta de que ni siquiera tuve que escribir más código para hacerlo bien. Digan lo que digan, estaba tremendamente equivocado.

Conclusión

Los programadores cometen errores todos los días, ya sea escribiendo código con errores o no queriendo probar algo que mejore sus habilidades y productividad. Por supuesto, puedes ser programador sin cometer errores tan graves como yo. Pero es imposible convertirse en un buen programador sin reconocer tus errores y aprender de ellos.

Constantemente me encuentro con estudiantes que sienten que cometen demasiados errores y, por lo tanto, no están hechos para programar. Sé lo común que es el síndrome del impostor en TI. Espero que aprenda las lecciones que he enumerado, pero recuerde la principal: cada uno de nosotros comete errores: vergonzosos, divertidos y terribles. Me sorprenderé y enojaré si en el futuro no tengo suficiente material para continuar con el artículo.

Fuente: habr.com

Añadir un comentario