Aunque podríamos decir que hoy en día programar es más difícil que cuando enviamos el hombre a la luna, hay muchas cosas que podemos aprender de esos pioneros de la programación y del programa espacial en su conjunto donde muchas veces no había segundas oportunidades que no implicaran un coste muy alto, incluso en vidas humanas.

En estos dos posts, Diomidis Spinellis discute los errores y aciertos del programa espacial soviético tanto del cohete N1 como del más conocido Soyuz (que ilustra este post). Veamos las principales lecciones que él saca de los fracasos (la historia del N1 se puede resumir como un conjunto de intentos de lanzamiento fallidos) y éxitos (el programa Soyuz sigue en funcionamiento después de más de 60 años desde su concepción inicial) de estos modelos.

Lecciones aprendidas del programa espacial que todo programador debería tener en mente

Define componentes que sean fáciles de testear. Si tu componente está lleno de dependencias externas, métodos gigantescos, entradas no deterministas,… vas a ponérselo muy difícil a los testers que van acabar haciendo los tests mínimos para cumplir el expediente. Y al revés, todo componente que sea fácil de testear va a estar plagado (en el buen sentido) de unit tests con un alto nivel de “coverage”.  Asegúrate también de facilitar una generación de datos de tests razonablemente parecida (en términos estadísticos) a la realidad si tu componente bebe de fuentes externas que escapan a tu control. El N1 era tan complejo que había partes que la primera vez que se testearon fue durante el lanzamiento. Ya sabéis como esto acabó.

No te olvides de los tests de integración. Un montón de tests unitarios no garantizan que cuando hagas el ensamblaje de todos los componentes no hayas interacciones no previstas ni deseadas. Deberías tener un entorno de testing que sea lo más parecido posible al de producción donde ejecutar estos tests (aún mejor si lo haces como parte de un proceso de integración continua).

Ejemplo de test de integración fallido

Dos tests unitarios. Cero tests de integración

Apunta al 80 por ciento. Ya hemos hablado de las ventajas de utilizar la regla de Pareto como concepto clave en el desarrollo de software. Limitar el alcance del proyecto y su complejidad desde el inicio tiene un gran efecto en el futuro éxito y longevidad del mismo. Soyuz siempre ha sido una “solución 80%”. No era lo que sus diseñadores, ni mucho menos sus usuarios, tenían como ideal. Por ejemplo, su capacidad era mínima comparada con el Shuttle (¡que ya no vuela!). Y tampoco podía lanzar satélites ni hace muchos experimentos pero esto mantuvo a raya la complejidad, facilitó su mantenimiento, mantuvo los costes de operación bajos y permitió su adaptación a nuevos requisitos.

shuttle vs soyuz

Cúrate en salud. Deja márgenes de maniobra. Los requisitos siempre van a cambiar. Y lo que ayer era clarísimo que funcionaba con unos parámetros, hoy responde con otros (por ejemplo, el tiempo de respuesta garantizado de un servicio externo, te garantizo que va a cambiar). Asegúrate que tu diseño deja margen para poder adaptarse a estos cambios imprevistos.

Si algo funciona no lo toques. Es fácil ver fallos en el diseño pero no tan fácil estar seguro que no hay alguna razón (no documentada en ninguna parte) que justifique lo que parece una clara deficiencia. Es aún más difícil estar seguros de que si lo tocamos el resultado final va a ser mejor. La mejora incremental es siempre más segura que cualquier cambio radical que puede fracasar incluso por aspectos que no tengan nada que ver con el rendimiento tecnológico (por ejemplo, en el caso de una interfaz, la opinión de los usuarios que estaban acostumbrados al viejo diseño).

Diseño modular. El diseño modular de Unix, que permite encadenar multitud de herramientas sencillas para solucionar el problema exacto que tenemos, es una de las grandes razones de su popularidad. Define tu diseño de forma tan modular como sea posible y con unas interfaces bien formalizadas que permitan cambiar cualquier pieza de la arquitectura por otra mejor o más especializada al entorno concreto donde lo tengas que desplegar.