De Patrones de Diseño a Teoría de Categorías
Durante los últimos días previos a mis vacaciones tuve el placer de atender al taller de Mark Seemann “De Patrones de Diseño a Teoría de Categorías” (From design patterns to category theory), organizado por Pau López, fundador de la comunidad .NET en Barcelona y profesor del curso de Herramientas Devops en Apium Academy. El taller de Mark me sirvió de inspiración para reflexionar sobre algunos temas que me llevan rondando la cabeza hace ya un tiempo.
Finalmente, hoy es el día en el que me he decidido a revisar mis notas y conversaciones con mis compañeros y compartir con vosotros todo lo que he aprendido, así como mis conclusiones sobre el estado actual de la programación. No esperéis un ejercicio de picar código; a pesar de que hicimos varios ejercicios de este tipo con Seemann, lo que quiero compartir con vosotros son conceptos generales como organización del trabajo, buenas y malas prácticas y, en general, elementos que inviten a la reflexión.
Empezamos el taller con algunas ideas generales sobre nuestro trabajo diario. Teníamos que definir un problema para mirar de resolverlo de forma clara, así que miramos de buscar una base en común – los conflictos que nos encontramos independientemente del lenguaje de programación de nuestro código, la metodología que usemos o el dominio en el que modelamos nuestros proyectos. Olvidémonos por un momento sobre errores de compilación, bugs y demás, y centrémonos en lo realmente importante.
Cuestión de perspectiva
A veces va bien apartarse del IDE para adquirir más perspectiva, para pensar en que es realmente la programación. ¿Es ciencia? ¿Es ingeniería? ¿Es ambas cosas o ninguna de ellas? – Mark nos propuso estas cuestiones. No utilizamos métodos científicos en la industria, y rara vez publicamos artículos basados en resultados de experimentos, preferimos encontrarnos para escuchar el caso particular de alguien. A pesar de que hay numerosas tesis creadas cada año en universidades de todo el mundo que amplían los horizontes del conocimiento conocido, la industria prefiere centrarse en soluciones rápidas y fiables para los problemas del día de hoy, o quizás de mañana, si tienes suerte. O, con mucha frecuencia, problemas de ayer, si tenemos en cuenta los términos de entrega de proyectos de desarrollo, cada vez más y más cortos.
Programar no es una ciencia, pues, pero también está lejos de ser una ingeniería “normal” a la antigua usanza. Cuando digo “normal” me refiero más a SpaceX o Tesla que a PayPal. Ya sabes, la industria “real”: mecánica, construcción, arquitectura, robótica, bioingeniería, química…Quizás la arquitectura sea lo más cercano a nuestra profesión. Tomamos prestados términos propios de esta disciplina, y no es difícil hacer analogías con la arquitectura al explicar nuestro código a aquellos que no programan. Además, está la arquitectura del software, y hay mucho software en la arquitectura moderna.
Un proceso “tedioso”
La mayor parte del tiempo, programar es una tarea manual repetitiva. En multitud de ocasiones debemos aplicar el patrón de diseño más conocido, y realmente no hay nada de malo en ello. Cierto es que hay poca emoción o sentido de la aventura cuando los requerimientos nos definen un componente, vista, formulario o endpoint exactamente igual al de la última vez, pero con un modelo distinto. Como he dicho, no hay que avergonzarse de entrar en la zona de confort – eso es, programación relajada, organizada y sin asperezas. Aunque esta no es la historia completa, pues sí existen ocasiones en las que debemos hacer lo completamente opuesta a la labor manual: razonar y descubrir. Eso que ocurre en cuanto salimos de nuestra zona de confort para hacer algo nuevo. ¿Y no es acaso en estos momentos en que este trabajo brilla de forma más intensa?
El descubrimiento
Creo que siempre ha habido (y siempre habrá) algo nuevo para mi a la hora de programar código. Estoy seguro que siempre habrá más librerías, frameworks y herramientas de las que ni siquiera he oído hablar que no aquellas que ya me son familiares. Y la comunidad lanza, inventa y reinventa más y más items nuevos de forma constante, haciendo que esta ratio de conocido-a-desconocido sea aún más descompensada. Como acostumbraba a decir un antiguo jefe de equipo: “Cuando te contratan, ya sabes cómo hacer tu trabajo, seguramente te valores poco”. No olvidemos que lo desconocido es una parte natural de nuestro trabajo. Es lo que hacemos, forjar lo desconocido e indefinido en workflows. Si todo fuera tan sencillo, estos procesos estarían automatizados ya hace años, y nosotros sin empleo. Lo que sí ha cambiado desde que empecé a programar es: los programadores se acostumbraban a contratar para el departamento de “desarrollo e investigación”, mientras que hoy en día contratamos desarrolladores y creamos departamentos nuevos en su nombre.
¿En qué nos centramos cuando tratamos de medir algo en nuestro trabajo diario? ¿Cuántas cosas se pueden medir en el mundo de la programación? A menudo escucho que debo medirlo literalmente todo en mi entorno de producción. No es una mala estrategia…pero cuando hablamos de personas humanas, es un poco más complejo. Hay un montón de cosas poco cuantificables pero muy importantes. Basta con decir que a todos nos gustaría poder medir el rendimiento o calidad o por lo menos el nivel de satisfacción (de un usuario, cliente o un equipo). La realidad, no obstante, elude nuestros esfuerzos de poner una regla encima de estos elementos y comparar el comportamiento humano con patrones ya conocidos.
Queremos números
A veces hablamos sobre la complejidad ciclomática o la cobertura de código. (Bueno, en realidad nadie habla de complejidad ciclomática…). Pero hacemos un montón de métricas que rara vez se traducen en valores vitales reales de un programador. Muchos son los que han visto un test cubierto casi por completo y, no obstante, han visto cómo sonaba su teléfono a altas horas de la madrugada por culpa de un diseño frágil y poco fiable. O como un bloque de código extremadamente elegante es, a su vez, tremendamente ineficaz o imposible de extender sin re-escrituras. Es fácil crear métricas estáticas. ¿Quién no ha oído hablar sobre story points, velocidades de sprints, número de bugs, turndown charts? El punto en común de todas estas mediciones es que son computaciones post-factum. Tal y como dijo Mark, “una predicción meteorológica que anuncia la lluvia de ayer”.
Velocidad versus Rapidez
¿Y qué hay de todos valores de productividad y efectividad que tanto gustan? En Scrum acostumbramos a medir algunos puntos, dividirlos y multiplicarlos teniendo en cuenta focus factors y número de días festivos en las próximas X semanas. Esto nos da algo que llamamos “rapidez de equipo”. Mi creencia personal es que el progreso se da de forma independiente. De hecho, a lo que nos referimos normalmente como rapidez como equivalente de velocidad es incorrecto – la velocidad es la derivada del desplazamiento respecto al tiempo, lo que traducido significa qué fracción de una historia de usuario se está consumiendo en este momento. Cuando ves que el cuentakilómetros de tu coche marca “80 km/h”, significa que estás yendo a esa velocidad en ese preciso instante y, extrapolando, si mantienes esa velocidad durante 60 minutos estarás exactamente a 80 kilómetros de distancia, pero si la mantienes solo 10 minutos, la distancia será de 13 kilómetros. Lo que realmente medimos en scrum es velocidad, no rapidez. La diferencia puede parecer ínfima o inexistente a simple vista, pero deja que me explique. La “velocidad” en scrum nos dice exactamente nada acerca de cómo vamos en este preciso instante o sobre qué podemos predecir de cara a la siguiente hora, día o semana. Solamente considera la diferencia entre “estamos caminando a 5 km/h” y “ayer hicimos 25 km, y antes de ayer 27”. ¿No explican estos mensajes historias distintas?
No te quiero convencer de que dejes de medir ni quiero prohibir las predicciones. Solo quiero remarcar que no deberías seguirlas a rajatabla. No eres un hámster corriendo en una rueda, no te quedes estancado en un ciclo de planear-daily-demo-retro-repetir. La zona de confort es la muerte de la creatividad. Muchos te intentarán convencer de que los números son lo más importante. No son los números, son su interpretación. Y volviendo a mi punto de inicio, las cosas más importantes ni tan solo se pueden (ni deben) medir! No hay medida para la deuda técnica, no hay una suma total de las horas perdidas intentando arreglar un módulo desfasado que no tenemos tiempo de re-escribir como Dios manda. Y nadie está haciendo un seguimiento de tus niveles de estrés. Debes estar atento a tu bienestar, amigo programador.
Todo cambia
Hay una norma que nunca cambia en el mundo de la programación: todo cambia. Y con todo el mérito que debemos dar al desarrollo actual de la Inteligencia Artificial, la programación, a día de hoy, aún la hacemos los seres humanos. Constantemente añadimos funcionalidades a bases de código existentes o modificamos implementaciones previas. Refinamos constantemente nuestro conocimiento y aprendemos cosas nuevas sobre el negocio de nuestros clientes y sus necesidades. El código que creas difícilmente estará aislado. Es bastante obvio, pero no ha sido hasta hace bien poco que me he dado cuenta de que escribimos mucho menos código del que leemos. Si no eres una máquina infalible en tu toma de decisiones, leerás constantemente tu propio código una y otra vez mientras lo escribes.
De hecho, creo que la mayoría de veces, escribir un código nuevo es más sencillo que leer y entender uno ya existente. Son incontables las veces en que, tras pasar horas tratando de arreglar “una bola de espagueti”, he sucumbido a la locura mientras pensaba “Voy a eliminarlo todo! Lo quemaré todo y empezaré desde cero!”. Una lección que debemos sacar de esto es que deberíamos redactar código que sea fácil de entender.
En palabras del mismo Mike, “escribamos código que sea entendible por los humanos, no las máquinas. Relájate, lo acabarán pillando. No ignores el proceso de pensamiento de las máquinas, pero más allá de lo obvio, escribe un código que sea fácil de leer y de extender. Me lo agradecerás más tarde. Deja que los compiladores sean compiladores, y no nos convirtamos en lobos para nuestros compañeros (y nuestros yos del futuro)”.
Deberíamos centrarnos en cómo escribimos nuestro código y en cómo será visto por otros desarrolladores. Una buena norma es tratar de limitar que el número de “cosas en movimiento” no pase de 7, ya que parece que este el el límite de concentración de la mayoría de humanos. Las cosas, cuanto más sencillas y encapsuladas, mejor.