← Volver

De qué hablo cuando hablo de programar

Programar no es solo escribir líneas de código: es resolver problemas, servir a otros, abstraer, diseñar para el futuro y crear software con criterio.

ReflexionesCoaching

En breve voy a publicar en GitHub un proyecto en el que he ido trabajando desde hace un año y que da soporte a mi propia plataforma de publicación abierta, Hub de Libros. Se trata de un framework al que le he puesto el nombre de Mantra Framework, escrito en Node.js y que permite crear componentes altamente desacoplados para encarar proyectos grandes y que van a evolucionar mucho, tal y como describo con más detalle técnico en mi último libro, El Arte del Emprendedor Digital.

Confío en basar en este framework muchos proyectos de aquí en adelante, al menos todos los basados en Node.

Tanto a un proyecto como al otro, les dedico todo el tiempo que puedo con la ayuda de algunos colaboradores. En cualquier caso, analizando Mantra Framework, no deja de sorprenderme la naturaleza de una actividad como es la programación después de dedicarme a esto profesionalmente toda mi vida. En mis primeros escarceos todavía tenía tan solo doce años.

Mi actividad profesional se reparte entre atender responsabilidades de desarrollo de negocio, tratar con clientes directamente, dirigir un equipo de desarrollo y también desarrollar y diseñar directamente proyectos como el anterior, además de todo lo relacionado con la publicación de mis libros (que, por el momento, son cinco técnicos y dos novelas).

Cualquiera que haya leído tan solo alguno de mis libros sabrá que todo lo que hago está relacionado directamente con el desarrollo de software, más orientado a productos que a proyectos específicos y particulares para clientes. Esto es: paso parte de mi tiempo programando, de ahí estas reflexiones sobre el acto de programar y las sutilezas que esconde esta actividad y esta profesión.

Ciertamente, programar es una actividad poliédrica que puede considerarse sencilla, pero también puede ser muy compleja. Como suele ponerlo como ejemplo, no es lo mismo construir un chamizo que un rascacielos, ni tampoco construir algo pensado para durar unas semanas que algo que deba aguantar años. Y, sin embargo, paradójicamente, puedes tener éxito afrontando el software desde un lado y desde el otro, aunque el coste sea diferente, como veremos a continuación.

A menos que te lo propongas, cualquiera puede aprender en un curso de fin de semana algunas nociones y comenzar a hacer cosas útiles, mientras que los más experimentados no dejamos de tener nuevas percepciones y descubrir nuevos detalles que nos sorprenden en algo que llevamos haciendo años: “¡ah!, mira, nunca había reparado en esto o en las consecuencias de hacer esto otro de este modo, curioso…”.

Del mismo modo que un autor siempre escribe para contar algo que sea de utilidad a otros (entretenimiento, formación, cultura, crítica, opinión, etc.), en esencia, programar consiste en resolver algún tipo de problema utilizando algún dispositivo para dar también utilidad a otros.

Esto es: salvo que programes por puro juego y divertimento, como hago a veces para experimentar, programamos para servir a los demás. No importa el modo, el entorno, el lenguaje de programación, si lo hacemos dentro de una pequeña o gran empresa o como freelance: siempre programamos para ofrecerle algo a alguien. En mi opinión, esta es la actitud esencial que deberíamos tener los desarrolladores profesionales, cierta vocación de servicio de cara a nuestros clientes, usuarios de nuestros proyectos y productos y cualquiera que consuma lo que hacemos. En otras palabras, nuestro cliente final es lo más importante, mientras que en ocasiones esto se nos olvida en el día a día.

Por llevarlo al terreno de lo concreto: hace años enfocaba proyectos personales centrándome en lo que a mí me gusta y que confundía con lo que podían necesitar otros. Corregí a tiempo, me sumergí en toda la cultura lean (Lean Startup, de Eric Ries) y está claro que ahora, en todo lo que hago, me centro no solo en un tema que me apasiona (como todo lo relacionado con la literatura y la publicación abierta), sino que lo enfoco desde la perspectiva del usuario final o del cliente. Nos guste o no, esto afecta a nuestra forma de enfocar el software porque cambia la naturaleza y la prioridad de los requisitos.

Por otra parte, no solo servimos a una comunidad, sea la que sea, sino también a nuestros propios compañeros que algún día heredarán nuestro código. Esto es: programamos también para hacerle la vida un poco más fácil a otros programadores cuando continúen con tu trabajo.

Tu misión como programador consiste en que otros entiendan tu trabajo de la forma más rápida y sencilla posible. Es más, cuanto mejor hagas esto, más podrás delegar y centrarte en aquello en lo que aportas más valor.

En cierto modo, cuanto más útil es lo que hacemos y para más personas, mejor nos irá. Por tanto, no se trata de trabajar más, de programar más y más proyectos, sino de centrarlo todo en escalar la utilidad que ofrecen al mayor número de personas posible.

Programar requiere de un nivel de abstracción que, me temo, no todo el mundo es capaz de desarrollar, porque se deben resolver problemas traduciendo la solución usando un lenguaje de programación con sus propios recursos y también con sus limitaciones. Evidente, pero no lo es tanto que el código generado y su calidad dependen mucho de ese nivel de abstracción. Observemos tan solo cómo cambia una solución implementada funcionalmente frente a una escrita con un lenguaje orientado a objetos: no solo cambia el resultado de lo que se genera, sino la forma de pensar del desarrollador para enfocar el problema. Esto viene a ser algo así como un paradigma mental de trabajo que te hará resolver las cosas de un modo u otro totalmente diferente. En ocasiones, el desarrollador no es que sea malo; es que no ha cambiado aún de paradigma.

Debemos abstraer, sí, pero solo señalo que esta es una habilidad más que debemos tener los desarrolladores, y que no por eso nos convertimos en personas especiales, ni mucho menos.

Opino que programar es sencillo: cualquiera que se lo proponga puede hacerlo. Pero también pienso que programar bien no es fácil, de ahí que me cause cierta sensación extraña esos cursos de dos semanas que prometen hacerte experto de la noche a la mañana. Lo sé, es un simple recurso comercial, claro está.

Programar tiene también connotaciones artísticas además de las técnicas. Pensar solo con las segundas y sin las primeras conduce siempre a una mala solución. Lo digo desde la perspectiva de que, para programar con éxito, necesitamos desplegar muchísima imaginación y creatividad, más allá de conocer las técnicas y buenas prácticas que sabemos que tenemos que emplear. En muchas ocasiones, la creatividad consiste en encontrar una solución sencilla a un problema que no lo es.

A diferencia de otras disciplinas, algo que también puede resultar extraño es que cuando programamos, tenemos que pensar mucho en hacerlo de un modo que podamos detectar y corregir errores más adelante. Piénsalo: el diseño del código cambia cuando pensamos en el mantenimiento del mismo, del mismo modo que se puede diseñar un coche pensando en que la reparación de sus averías sea sencilla años más tarde. Por alguna razón, esta cuestión cuesta que cale profundo en muchos desarrolladores con los que me cruzo, y si extrapolo, no tengo más remedio que pensar que es algo extendido en nuestro sector.

Inevitablemente, por mucha experiencia que tengamos, por muchas miles de líneas de código que hayamos escrito, siempre programamos cometiendo errores, que bien son detectados por mala sintaxis en tiempo de compilación o en tiempo de ejecución en lenguajes interpretados, además de los bugs que se producirán aunque el código sea perfecto. No conozco ninguna otra actividad en la que se avance creando algo nuevo pero al mismo tiempo corrigiéndolo continuamente.

La consecuencia de esto es que no nos podemos fiar de nuestro código y, por eso, tenemos que respaldarlo con tests necesariamente en la medida de lo posible; incluso hay una disciplina, TDD, que programa planteando los tests antes que el código de producción.

Imagina que un electricista, haciendo la instalación de un nuevo edificio, toca en alguna caja de registro y se equivoca en el cableado: evidentemente, no se va a caer ninguna pared ni ninguna ventana se va a romper. Pero en software sí. En software, un error en algún sitio puede terminar provocando errores en el lugar más insospechado, de ahí la necesidad de plantear tests de integración, pruebas de validación y más.

Por resumirlo de algún modo: la actividad de programar lleva intrínseca la realización de tests.

Sorprendentemente, hacer tests no es un gasto, sino una inversión que te permitirá avanzar más rápido. Algo contraintuitivo, sí, pero sutil de captar.

Cuando programamos, nos cuesta fijarnos en lo que yo llamo el horizonte temporal. Lamentablemente, y ojalá me equivoque, la mayoría de los desarrolladores solo se preocupan por implementar lo que sea para que funcione cuanto antes y entregarlo al cliente; a otra cosa. Sin embargo, la naturaleza de muchos proyectos consiste en que deben durar en producción muchos años y, más importante aún, van a ser modificados radicalmente y van a sufrir mucha evolución, sin mencionar la cantidad de actualizaciones de librerías o dependencias de terceros que probablemente provocarán más cambios en el código de producción.

De nuevo, enfocar el software a corto o a largo plazo tiene efectos impresionantes tanto en su arquitectura como en su diseño. Lo curioso de este aspecto del desarrollo es que el esfuerzo es similar; la única diferencia está en la experiencia del desarrollador y en las ganas que tenga de hacer las cosas mejor.

También resulta un tanto extraño cómo los pequeños defectos que vamos dejando por el camino (malos nombres de clases, redundancias, mala organización, funciones o métodos largos, demasiados parámetros, objetivización deficiente, etc.), por pequeños que parezcan, tienen un efecto acumulativo demoledor: si no se vuelve atrás a mejorarlos continuamente, tarde o temprano la calidad del proyecto se resentirá. Esto es lo que en nuestro mundo se denomina deuda técnica.

Un aspecto que me gusta mucho de la programación es que un proyecto software nunca se termina, aunque cumpla con los requisitos del cliente. Quiero decir que siempre vas a encontrar qué mejorar, qué simplificar, cómo hacer tal cosa de mejor modo, nuevos tests, etc. De ahí que, sin ir más lejos y a modo de ejemplo, hoy mismo me haya instalado la actualización más reciente de Visual Studio Code.

Y este aspecto para mí es una buena noticia, porque me aligera del peso de tener que resolver algo de la mejor manera posible en un momento específico, y me permite avanzar en otros puntos del proyecto porque sé que habrá un momento de volver a él, una y otra vez, tantas como uno mismo quiera. Eso sí, no me olvido de indicar todas las mejoras pendientes en una lista de tareas.

Programar es una actividad incremental: poco a poco, agregando esto, después aquello, luego mejorando algo que no funcionaba del todo bien, limpiando otra parte, en un proceso kaizen infinito. Es decir, afrontamos un proyecto complejo mediante iteraciones: ahora esto, después aquello, y en la siguiente esto otro.

Sin embargo, algunas de esas iteraciones se deben dejar para mejorar de algún modo todo lo realizado hasta el momento. Esto puede parecer una pérdida de tiempo; sin embargo, aligerando un poco la deuda técnica de la que hablábamos antes y mejorando los cimientos y la forma en la que se avanza en el proyecto —lo que parece un paso atrás—, lo que conseguimos es aumentar la velocidad de desarrollo y consolidar más la solución en las iteraciones siguientes.

Pero incremental también implica que programamos funcionalidad de forma jerárquica, algo que en ocasiones se nos escapa o se nos olvida: construimos funcionalidad sobre otra funcionalidad, que a su vez está construida sobre otra, y así varios niveles o capas más. Este aspecto, quizá algo más sutil, tiene también un profundo impacto en lo que se viene en llamar la arquitectura de la solución. Al margen de esto, lo que quiero recalcar es que si la base de un proyecto no es sólida, lo demás se caerá por su propio peso.

Otra sutileza: la función de la capa o nivel n es permitir que la capa n+1 se pueda implementar de la forma más sencilla posible. Piénsalo por un momento en algunos casos prácticos que se te ocurran.

Programar también consiste en utilizar ciertas recetas para problemas típicos de nuestra industria: desde buenas prácticas de arquitectura hasta patrones de diseño y todos los temas relacionados con la usabilidad. Diseñar software, al igual que construir una casa, exige dominar ciertos principios para que la solución final no sea improvisada ni frágil.

La industria del desarrollo de software es muy madura a estas alturas, no así la calidad del software que se produce en general, me temo. Contamos con muchísima documentación acerca de las buenas prácticas de todo tipo. Siguiéndolas, tu trabajo como programador tiene un color distinto; sin embargo, esas buenas prácticas se ignoran continuamente, tanto en pequeños como en grandes entornos corporativos. Está en nuestra naturaleza de programador dejar a veces las cosas sin hacer del todo bien, aún sabiendo que se puede mejorar. En ocasiones es por la presión del tiempo; en otras, por pura pereza. Y tarde o temprano eso nos pasará factura.

Para mí, programar es una de las pocas actividades que me permiten entrar en ese estado de fluir (flow), término definido por el psicólogo Mihaly Csikszentmihalyi. Esto me ocurre desde que era joven, y me ha llevado a pensar que esta actividad es una de mis pasiones y vocaciones. Si algo no te llena del todo, nunca entrarás en ese estado mental del que hablo, al menos no tan a menudo.

Un diseño pobre, ineficiente y que genera una solución con poco rendimiento, en ocasiones se soluciona añadiendo hierro al despliegue: más máquinas virtuales o contenedores, más recursos, bases de datos más escalables, etc., cuando lo que ocurre es que el diseño y la arquitectura del software es deficiente. Con esto quiero decir que una mala solución tiene un impacto económico directo cuando la tratamos de enmascarar con más hardware. Los tests de rendimiento, así como todas las técnicas de profiling y métricas de calidad de software, nos ayudan a detectar este tipo de problemas tan comunes.

Programar es también una actividad altamente colaborativa. Como bien sabemos, muchos proyectos fracasan no porque sus desarrolladores no sean suficientemente buenos o no estén comprometidos, sino porque fallan aspectos de trabajo en grupo, entornos quizá tóxicos, enemistades, política laboral deficiente o la imposición de plazos imposibles de cumplir salvo con auténticas porquerías. De modo que un buen programador tiene que saber también colaborar de un modo u otro con otros, y las empresas, por su parte, deberían crear una cultura corporativa atractiva y motivadora. El mismo desarrollador, puesto que lo que hace es una actividad eminentemente creativa, puede rendir deficientemente en un entorno en el que no se siente a gusto y ser un crack en otro que le motive. ¿Y qué ha cambiado? El entorno, las dinámicas de trabajo, la naturaleza de los proyectos, etc.

Puedes programar como hobby en tu tiempo libre, pero hacer de esta actividad tu carrera profesional es otra cosa totalmente distinta. Para ello necesitas ciertas habilidades y actitudes que se denominan soft skills. Por muy bueno que seas técnicamente, si no cuentas con esas habilidades, las cosas sin duda te irán peor. Hablo de algunas de ellas en uno de mis libros, The Coder Habits: Los 39 hábitos del programador profesional.

Del mismo modo, y esto es algo que a día de hoy no termino de comprender bien, programar es una actividad que a ciertas personas les da alas para desplegar actitudes egoicas y sentirse mejor o por encima de otros desarrolladores. ¿Por qué? Ni idea. Lo que sí sé es que además de ser esa una actitud infantil y de personas seguramente con baja autoestima, los mejores programadores que he conocido (ingenieros o no) siempre han compartido un talante muy humilde en su profesión. En una ocasión viajé a las instalaciones de Microsoft en Seattle y pude charlar con algunos de los líderes de equipos que en ese momento desarrollaban .NET Framework. Hablaban de una forma tan sencilla y humilde de cómo lo iban evolucionando que me sorprendió.

Estamos en la era del emprendimiento e incluso el movimiento F.I.R.E. (financial independence, retire early) tiene cada vez más adeptos. Vivimos una migración de todo hacia lo digital, como no podía ser de otro modo, y por tanto, programar es el lenguaje transnacional que permite todo lo anterior. Como programadores, lo tenemos mucho más fácil que otros sectores para emprender. Por eso no comprendo por qué la mayoría de desarrolladores siguen prefiriendo empleos de nueve a cinco como única posibilidad de desenvolverse laboralmente, aunque esto lo digo solo como apreciación muy personal.

Por último, no deja de sorprenderme cómo un mismo entorno de desarrollo se puede utilizar para realizar proyectos tan diversos, desde juegos hasta ERP, aplicaciones web o cualquier cosa que se te ocurra. Aprendemos a programar en un entorno concreto y lo podemos usar para hacer virtualmente cualquier tipo de solución. ¿No es maravilloso?

Con las pinceladas anteriores, espero haber dado una idea clara de que programar, al menos profesionalmente, va mucho más allá de escribir líneas de código de cualquier modo.

Salvando las distancias y con todo respeto por el mundo animal, como me dijo una vez un antiguo profesor: hasta un primate puede pintar un círculo en un lienzo, pero de ahí a que tenga valor artístico… ;-)