La productividad de un equipo de trabajo en ocasiones viene dada por pequeños detalles que en sí mismos pueden parecer insignificantes pero sumados marcan una gran diferencia. El Libro Negro del Programador habla intensivamente acerca de cómo desterrar malos hábitos e incorporar buenos precisamente para aumentar la productividad. En ocasiones se entiende ésta exclusivamente como echar más horas: yo digo que trabajar con productividad tiene más que ver con usar herramientas correctamente, tener un equipo de trabajo bien organizado y buenos procedimientos.

Uno de estos procedimientos que pueden ahorrar muchísimo tiempo de esfuerzo inútil es subir correctamente al repositorio de código los últimos cambios introducidos. Como en muchas ocasiones, los mejores hábitos y técnicas son precisamente los más sencillos.

¿Cuánto tiempo hemos pasado resolviendo conflictos de código introducido al mismo tiempo o después de nuestros últimos cambios?. Demasiado si se tiene en cuenta que ese es tiempo no productivo y, en ocasiones, frustrante.

La siguiente técnica busca minimizar las posibilidades de generar conflictos; cuanto mayor sea el número de desarrolladores en un equipo, más posibilidades habrá de generar este tipo de problemas.

Para reducir las posibilidades de conflicto en el código cuando vamos a introducir un nuevo cambio:

  • Obtenemos la última versión (lo que nos garantiza que no vamos a usar en ningún momento código obsoleto).
  • Introducimos los cambios o nueva funcionalidad.
  • Ejecutamos todos los tests; deben pasar el 100%.
  • Obtenemos de nuevo la última versión. De este modo vemos si nuestros cambios han introducido algún error de compilación con los cambios introducidos por otros (o al revés).
  • Antes de subir, volvemos a ejecutar todos los tests.
  • Ahora sí que subimos los cambios.

De este modo reducimos radicalmente la posibilidad de conflictos.

Hay diversas opiniones sobre la frecuencia de subir los cambios (cada X horas, cuando se termina una funcionalidad completamente, etc.). Esto dependerá de la naturaleza de cada proyecto. Personalmente me siento cómodo con subir frecuentemente (varias veces al día).

Lo mejor es acordar entre los miembros del equipo el procedimiento a seguir en este proceso (check-in process): ¡mejor uno aunque no sea el mejor que ninguno!.

Cuanto más tiempo viva tu aplicación, más probable será que tenga que cambiar; así de sencillo y contundente.

En ocasiones me han preguntado por qué parezco obsesionado por programar y diseñar de la manera más simple y legible posibles, para qué preocuparse ahora por aquello que puede o no necesitar cambiar en el futuro. La pregunta en sí ya encierra cierta candidez acerca de los artefactos que generamos en nuestra profesión.

Una de las verdades sobre nuestro trabajo, entronada a modo de ley, nos dice que cuanto más tiempo viva nuestra aplicación, programa, sistema, plugin, framework, etc. más probable será que necesite cambios, mejoras, correcciones, etc. Ley o no, lo que sí puedo decir es que ningún software en el que he participado ha permanecido inmutable más de seis meses...

¿Tenemos presente en nuestro día a día esta realidad?. ¿Nos preocupamos realmente en refactorizar y mejorar a pequeños saltos continuamente?. ¿Nos esforzamos en encontrar la solución más simple a cualquier problema?.

Es cierto que podemos dejar las cosas tal y como nos salen la primera vez que las hacemos (total, funcionan, ¿no?); sin embargo, si vamos dejando cabos sueltos, duplicidades, errores conocidos y toda una estela de debes, con el tiempo se formará una montaña que nos caerá encima inevitablemente (o enterrará el producto en el olvido).

Cualquier software va a necesitar cambios en un futuro necesariamente: cualquier producto que se lance al mercado va a morir si no se renueva con mejoras continuamente (continuous delivery), cualquier cliente consolidado que tengamos nos pedirá mejoras o cambios con toda seguridad, por mucho esfuerzo que hayamos dedicado a probar nuestro código, finalmente el cliente encontrará nuevos errores o pequeños bugs, cuando no nos encontramos con el consabido problema de haber entendido mal algún requisito en concreto. En otras ocasiones, la evolución del mercado o tipología de clientes al que se dirige nuestro software determinará el tipo de cambios a introducir.

Demasiadas razones para no programar centrando nuestro trabajo en la sencillez de las soluciones; esta casi nunca se consigue a la primera, sino que poco a poco, mediante pequeñas refactorizaciones, auscultando el trabajo con tests y a medida que la aplicación crece, vamos mejorándola en todos los aspectos. Tampoco podemos obviar que el coste de evolucionar una aplicación debe ser el mínimo posible, de lo contrario estaremos fuera del mercado antes de lo que nos gustaría.
 

"Aunque suene paradójico, programar profesionalmente significa también estar dispuesto a destruir parte del trabajo realizado ¡precisamente para mejorarlo!. Si nuestro software no puede ser modificado y mejorado fácilmente, estará perdiendo rentabilidad y oportunidades de competir."

 

En una etapa laboral anterior, sufría a menudo el típico ataque inesperado según el cual un manager o jefe de proyecto venía a pedirme a mí y a mi equipo la corrección o puesta en producción de algo que por arte de birlibirloque se había convertido ese día en crítico. A lo mejor lo tenía en el cajón olvidado hasta que le explotó en las manos.

Nada peor para un programador que tener que resolver un bug o incluir una nueva característica con la presión del tiempo, sobre todo si no estaba previsto.

Esto puede parecer a excusa, pero cuando trabajamos excesivamente presionados vamos dejando atrás las buenas prácticas, los buenos hábitos y el formalismo de probar y probar por el camino; cuando el tiempo aprieta aligeramos nuestro trabajo sin darnos cuenta de que esto tiene un precio tremendo y en ocasiones los resultados son catastróficos: se actualizan cosas que suponemos que funcionan bien y creemos que no deben dar problemas (sin imaginar algún tipo de efecto secundario), olvidamos los rigores de la gestión de versiones (claro, nos han dicho que es algo crítico) y además apenas tenemos tiempo de probar todo el sistema, por poner sólo unos ejemplos. Para resumir, cuando tenemos encima de la mesa algo crítico lo olvidamos todo y nos centramos en el problema.

La cuestión no está tanto en poder gestionar estas situaciones ocasionalmente sino cuando estas se convierten en crónicas y el modo habitual de trabajar; en ese caso el software resultante será de pésima calidad. Es tema recurrente en El Libro Negro del Programador, así que dejad que os recuerde que código de mala calidad es igual a problemas: soluciones inmantenibles, más costosas por las dificultades de introducir nuevos cambios, incapacidad de ser asumidas con facilidad por nuevos miembros del equipo y, en definitiva, programadores frutrados que dedican más tiempo a depurar que a crear código de valor.

Trabajar bajo la presión de problemas no previstos por nosotros constituye el típico escenario en el que quien presiona no tiene ni idea de software: sólo ve programadores cuyo trabajo debe ser igual que conectar cables, o están bien puestos o están mal puestos, no hay más. Personalmente considero que quien lidera un equipo de desarrolladores debe tener profundos conociemientos de software.

Siempre, y lo digo taxativamente, siempre que me he encontrado en esta situación el diagnóstico ha sido el mismo: gestores de proyecto mal planificados y con una organización pésima; el problema es que esta falta de trabajo eficaz termina trasladándose a los miembros del equipo de desarrollo. Tampoco podemos excusar a clientes que de un día para otro encuentran un bug crítico que hará temblar su organización: si se ha hecho bien el trabajo, esta situación no se debe dar.

En cualquier caso, si nos encontramos en esta tesitura y detectamos que para llegar a tiempo tenemos que dejar cabos sueltos y entrar en una zona de riesgos, debemos notificarlo adecuadamente a los managers; basta un simple correo que con sutileza pero con contundencia debemos advertir de la falta de tiempo para probar exhaustivamente o implementar los cambios solicitados (esto es una manera de delegar responsabilidades).

También es una cuestión de actitud: ¿estamos para que viertan sobre nosotros la mala organización de quienes jerárquicamente están por encima?, ¿es esto profesional?. He visto cómo algún proyecto ha fracasado no por la falta de pericia y buen hacer de los desarrolladores, sino por problemas de gestión.

El saber decir "lo siento, esto no se puede hacer de aquí a mañana" tiene efectos positivos que debemos considerar: estamos honrando nuestro trabajo (no nos pagan por trabajar, el profesional busca hacer un buen trabajo, que no es lo mismo) y, además, uno o dos noes de este tipo hará recapacitar a quien lo provoca e intentará evitarlos en el futuro (para lo que simplemente tendrá que organizarse mejor).

Este tipo de situaciones demuestra también una falta total de productividad: cuando se convierten en crónicas entonces ya sabemos en el tipo de compañía en la que trabajamos. Cuando identificamos un manager cuya idiosincrasia de trabajo es el caos, entonces la salida que nos queda es intentar cambiar de grupo de trabajo, departamento o compañía: un profesional se hace profesional precisamente haciendo un magnífico trabajo, éste es su currículum y su manera de progresar.

Como desarrolladores que nos debemos ganar la vida desde la calidad de nuestro trabajo debemos considerar como máxima que la mayor parte de nuestras actividades deben estar correctamente planificadas, debemos tener un roadmap claro aunque incluyamos un pequeño percentaje de nuestro tiempo para deviaciones e imprevistos.

Resulta sorprendente cómo pequeños pasos y hábitos consiguen con muy poco mejorar muchísimo la calidad de nuestro código; cuando hablamos de calidad entendemos también legibilidad, es decir, la facilidad o no de poder entender un pedazo de código leyéndolo tal como leemos un relato corto. Yo siempre digo que si se consigue entender de una o dos pasadas lo que hace un pedazo de código, entonces es que este apunta a estar bien hecho.

Ahora bien, ¿qué hacen por ahí esos trozos de código comentados que, lógicamente, no se van a ejecutar?.

Este es uno de los malos hábitos que debemos quitarnos de encima; el dejar rastros de código obsoleto va en contra de que este sea legible y fácil de entender.

Cualquiera que retome vuestro trabajo y se encuentre con él, lo primero que va a pensar es, ¿será esto un bug resuelto, lo habrán dejado ahí por alguna razón, será importante?. Este tipo de interrupciones en la lectura de líneas de software distraen del resto y crean dudas.

La razón por la que solemos dejar código comentado es obvia: nos cuesta mucho eliminar trabajo previo, pero es que precisamente esa labor de destrucción (eliminar algo que no está bien) y reconstrucción (re-crearlo para mejorarlo) es lo que aporta calidad a nuestro software. Entonces, ¿para qué dejar rastros de lo anterior?. Otra razón es que en ocasiones dudamos y no estamos seguros de las modificaciones que queremos introducir. Este último caso es fácil de resolver: una buena batería de tests nos deben indicar la solvencia o no de lo que cambiamos.

Por otra parte, ¿para qué está el repositorio de código?. Si modificamos algo y eliminamos un bloque, siempre lo podremos recuperar más adelante si hacemos una buena gestión en nuestro sistema de control de código fuente.

No es que haya que caer en extremismos; el desarrollar software tiene un componente lúdico y tampoco debemos ceñirnos rígidamente a las reglas, prácticas y buenos hábitos que sabemos que son necesarios para hacer un buen trabajo. Lo que indico aquí es que un software de producción y que debe ser mantenido y revisado, no debería tener bloques de código muerto.

"No dejemos código comentado: esto distrae a un futuro lector de nuestro trabajo y ensucia la solución"

10:00 de la mañana; tienes por delante una tarea que estimas en dos horas para hacerla bien y darla por terminada. Te preparas ante tu entorno de trabajo y comienzas a desarrollar código; poco a poco tu mente va dejando las divagaciones de la charla del café anterior y se mete de lleno en el problema a resolver. No es raro entrar en ese estado de fluidez definido por Mihaly Csikszentmihalyi en su famoso libro de psicología positiva.

Tomar decisiones de diseño, desarrollar una clase o refactorizar un conjunto de pruebas, por poner unos ejemplos, requieren de concentración y cierta paz mental para que las decisiones tomadas sean las correctas.

Esto parece evidente, pero pocos entornos laborales fomentan esta tranquilidad y capacidad de estar concentrados.

Una vez leí que cuando estamos en ese estado de fluidez completamente abstraidos y somos interrumpidos, necesitamos al menos veinte minutos para volver a un estado similar de concentración, es decir, a lo largo de varias semanas esto significa muchas horas de trabajo perdido, así de simple y así de abrumador.

Hay muchísimos momentos en los que somos interrumpidos y sacados a la fuerza de ese estado de fluidez.

Están los que yo llamo los vampiros de tiempo: personas e incluso buenos amigos que se sienten con el derecho de acercarse a tu puesto de trabajo para preguntarte de sopetón cualquier cosa que en ese momento necesitan o aquellos que creen que su tiempo es más valioso que el tuyo.

Clientes a los que se les ha acostumbrado a llamar por teléfono porque es más cómodo que describir un problema por mail.

Reuniones espontáneas y no planificadas porque a tu jefe o manager le ha entrado cierta urgencia o ansiedad que ahora va a intentar trasladar al equipo por falta de una mínima organización. Esto es lo que yo llamo el síndrome del jefe ansioso (y es una patología porque traslada ese estado al resto de su equipo).

Espacios abiertos en donde los teléfonos sonando o el rumor de conversaciones son constantes, hasta aquella chica que con sus hermosos tacones va dejando una sinfonía de pisadas que la identifican (y te irritan).

Un día cualquiera hace un par de años decidí contar el número de veces que era interrumpido y molestado a lo largo de la jornada laboral: conté catorce veces, incluidos unos quince mails irrelevantes para mi trabajo y responsabilidad.

Lo peor es que la mayoría de estas interrupciones se producen porque alguien necesita algo ti y eso que necesita es completamente ajeno a tu trabajo: no nos damos cuenta de que nos quitan precisamente el tiempo y tranquilidad necesarios para hacer un trabajo de calidad y no dejar bugs que nos pasarán factura más adelante.

Un desarrollador profesional evita estas innumerables e inútiles interrupciones. Aquí indico algunas sugerencias que para mí particularmente me han resultado efectivas:

  • Identifica a los vampiros de tiempo: ante la insistencia de estos, quítatelos amablemente de encima poniendo el mínimo interés en sus peticiones. Con el tiempo dejarán de ir a por ti.
  • Si tu jefe, coordinador o manager se acostumbra a trabajar con reuniones imprevistas, indícaselo claramente: seguramente no se de ni cuenta del impacto que esto puede tener para el trabajo. Puedo contar la experiencia con cierta persona de perfil comercial que aprovechaba las reuniones para hacer el trabajo directamente sobre una hoja de cálculo...
  • Si tienes clientes que atosigan por teléfono, indícales amablemente que reporten las peticiones por mail o por el sistema de ticketing que uséis. Con el tiempo os lo agradecerán porque no hay nada mejor que describir un problema para entenderlo completamente.

Desde que comencé a aplicar esas sencillas técnicas tanto para mí como para el equipo que dirigía en ese momento, conseguimos un ambiente laboral mucho mejor y por tanto pudimos hacer un trabajo de mejor calidad. Gané de paso algunos conocidos que comenzaron a verme, digamos, algo mal, pero mi jefe notó al poco tiempo el cambio y la mejora en la productividad del equipo.

"No digo que tengamos que trabajar en un convento de clausura, sólo aplicar el sentido común en estas circunstancias y tener en cuenta que hay límites intolerables en la cantidad de interrupciones diarias, lo que revela una falta general de organización y productividad en el trabajo"

Los programadores por naturaleza afrontamos muy mal aquellas tareas que más nos cuestan y casi siempre comenzamos por las que más nos gustan o aquellas que más nos apetecen en el momento, esto es así porque tenemos la opción de elegir qué hacer de entre todo el trabajo que tenemos por delante.

Un desarrollador neófito o júnior comienza siempre por lo divertido, mientras que un programador profesional elige siempre en primer lugar lo más difícil o aquello que le causa especial incertidumbre. Las consecuencias de esta elección son evidentes.

El primero comienza el trabajo divirtiéndose en aquello que más le apetece, pero sin darse cuenta de que va a ir acumulando tareas y problemas para más adelante sin sospechar que estos siempre van en aumento: al final se verá agobiado y lo que es más difícil de resolver terminará por hacerlo rápido (y seguramente mal).

No obstante, el profesional sabe que esto es así, de modo que lo primero que evita es que los problemas se acumulen a medida que se termina el tiempo estimado para realizar el trabajo: por esa razón afronta siempre lo más difícil o aquello que aún no sabe bien cómo resolver al principio del sprint o la fase de trabajo.

Esta es una cualidad más del desarrollador profesional: la experiencia le ha mostrado que nunca es buena idea dejar para el final la incertidumbre; si esta se elimina justo al principio se afrontarán el resto de tareas de una manera mucho más tranquila y relajada, estados mentales imprescindibles para realizar un desarrollo de calidad.

Por lo menos a mí me pasa, no puedo trabajar con un mínimo de tranquilidad si tengo ese ronroneo mental continuo con aquello que aún no sé cómo hacer o esa otra parte del trabajo que todavía no tengo ni idea de cómo voy a resolver.

"Un buen desarrollador siempre busca trabajar con tranquilidad; para ello, la incertidumbre hay que eliminarla al comienzo, no dejarla para el final"

Cualquier proyecto software comienza cargado de problemas e incertidumbres, se desarrolla con problemas e incertidumbres y se entrega con... pues eso.

Cuando programamos estamos resolviendo problemas, al menos algunos de los que conocemos y nos agobiamos precisamente por aquellos que desconocemos.

Todo sería un poquito más fácil si asumiéramos que cualquier proyecto software tiene en su naturaleza tres verdades que al conocerlas bien nos pueden hacer nuestro trabajo más asumible y cómodo. Son las siguientes.

No hay ningún proyecto software que recoja completamente los requisitos al principio.

Nos han enseñando que como primera parte de un proyecto se debe afrontar una toma de requisitos. Esto en sí mismo ya es un tema de estudio profundo y empresarialmente un tema que casi siempre comienza mal: en ocasiones quienes recogen esos requisitos no poseen las competencias necesarias para trasladarlos al papel para que sean entendibles por el equipo que implementa el proyecto; en otras quien se encarga de esta tarea no está comprometido con el proyecto, por lo que le da igual especificar bien, cuando no pocas veces entender lo que el cliente quiere es más un tema de psicología que de tecnología.

En cualquier caso, por una razón u otra la realidad es que recibir requisitos completos es una utopía y cuanto antes aprehendamos esto nuestro trabajo podrá ser enfocado con un mayor grado de flexibilidad. No entramos aquí en técnicas ágiles que afrontan esta laguna inicial con reconsideraciones continuas del catálogo de requisitos, lo cual es la manera correcta de enfocar el problema, pero en muchos casos el contexto laboral te impide poner en práctica una metodología ágil.

Por muchos requisitos que se haya conseguido obtener al principio, éstos cambiarán con total seguridad.

No podemos basar completamente las decisiones de diseño que se toman e implementan en requerimientos iniciales: cualquier proyecto software va a ver modificado lo que se espera de él con el tiempo. En cuantas ocasiones he vivido eso por parte de un cliente igual que los "pues ya que...", sin entender las consecuencias desastrosas que puede tener para la solución software el esperar que un vehículo de cuatro ruedas ahora tenga que volar...

Sólo si aceptamos que en cierta medida nuestro software se debe adaptar a cambios entonces programaremos con un enfoque más abierto: modularizaremos mejor, desacoplaremos bien las partes funcionales del producto, nos esforzaremos mejor por hacer clean code, permitiremos un alto grado de configuración y particularización, etc.; sólo podremos hacer esto si nos inculcamos el hábito de programar para el cambio.

Cualquier software que no permita evolucionar ni ser modificado se tirará a la basura más pronto que tarde.

Siempre habrá muchas más cosas que hacer de las que nos permite el tiempo y el dinero.

A medida que avanzamos en la ejecución del proyecto las posibilidades de desarrollo, mejora e ideas se irán abriendo y ampliando en forma de árbol: exponencialmente.

Tenemos que asumir que siempre vamos a tener más cosas de las que realmente podemos afrontar y hacer. Si aceptamos que esto es así entonces podremos priorizar mejor y determinar qué es lo importante para el proyecto y qué lo accesorio, nos evitará divagar entre tareas sin terminar sin cerrar niguna al 100% y nos evitará ir dejando una technical debt que nos pase factura meses más tarde.

Simple pero efectivo: tres verdades sencillas de entender pero que tantas veces he visto totalmente incomprendidas en muchos de los proyectos que he participado.

Fuente (aparte del sentido común), el valiosísimo libro de Jonathan Rasmusson The Agile Samurai: How Agile Masters Deliver Great Software.

Las reglas para desarrollar buen software son en ocasiones de un total sentido común y están al alcance casi de cualquiera que se proponga realizar su trabajo en condiciones.

No hace mucho re-descubrí un conjunto de sencillas preguntas que nos dicen si tenemos un buen equipo de trabajo y trabajamos desarrollando software con un mínimo de calidad: es el test de Joel que resumo a continuación y que no es más que sentido común aplicado a nuestra actividad diaria:

  1. ¿Usas un repositorio de código?
  2. ¿Puedes realizar la compilación de tu aplicación en un único paso?
  3. ¿Realizas compilaciones diarias?
  4. ¿Trabajas con una lista o herramienta de gestión de errores?
  5. ¿Corrijes errores pendientes antes de escribir nuevo código?
  6. ¿Trabajas con una planificación actualizada?
  7. ¿Tienes una especificación de lo que tienes que hacer?
  8. ¿Tienes lo programadores unas condiciones de trabajo convenientes?
  9. ¿Usas las mejores herramientas que te puedas permitir con tu presupuesto?
  10. ¿Tienes testers en el equipo o, en su defecto, existe al menos tal rol?
  11. En las entrevistas de nuevos candidatos, ¿escriben código?
  12. ¿Compruebas la usabilidad del código que desarrollas con la opinión de otros desarrolladores?

Lo ideal, según el autor de este sencillo test, es responder a todo con un SÍ, pero si respondemos a diez o menos de estas preguntas afirmativamente, entonces tenemos serios problemas en nuestra manera de enfocar el desarrollo de software.

Podemos cumplir más o menos con la lista de preguntas del test o la podemos cumplir horriblemente mal, y, al mismo tiempo, podemos entregar una aplicación que funciona, nuestro jefe estará contento y seguramente nuestro cliente también, pero... ¿a qué coste?. ¿Cuánto tiempo habremos perdido resolviendo compilaciones rotas?, ¿cuánto tiempo habremos dedicado a resolver este error que surgió hace dos semanas?, ¿será nuestro código mantenible cuando el mismo cliente nos pida nueva funcionalidad?, ¿podremos recuperar la versión X de una clase porque hemos introducido cambios desastrosos?, ¿trabajamos eficientemente sin una mínima planificación?, ¿sabemos exactamente qué hay que hacer si no existe una especificación clara?. ¿Somos productivos si no tenemos un entorno de trabajo productivo?.

La mayoría de estas cuestiones las deben resolver y responder los responsables, coordinadores y jefes de los desarrolladores y no éstos, aunque sí es fundamental que los mismos programadores alerten de estas carencias a sus responsables de equipo.

A las preguntas del clásico test de Joel, yo añadiría además las siguientes:

  1. ¿Está el código suficientemente respaldado por pruebas?
  2. ¿Existe una correcta gestión de la configuración?
  3. ¿Se sigue algún tipo de metodología?
  4. ¿Se esfuerza el equipo por simplificar y mejorar continuamente la estructura y el diseño de la aplicación?
  5. ¿Es el código que se desarrolla suficientemente simple?
  6. ¿Es bajo el esfuerzo que tendría que hacer un nuevo miembro del equipo para realizar código nuevo de producción?

¡Hola a tod@s!

Hoy es un día importante porque esta web queda publicada; la edición de este libro es un proyecto personal que comencé en el verano de 2012.

Ahora sí. En aquellos meses, y dado que desde hace mucho me gusta escribir y reflexionar sobre ciertos temas que afectan a nuestra profesión, me pregunté ¿y por qué no pongo todo esto en un libro que pueda compartir con la gente?.

Así nació esta idea y así se está desarrollando; aunque mucho de los capítulos y apartados del libro los tengo escritos desde hace mucho, con esta web quiero compartirlos y darles una forma más o menos definitiva antes de su publicación.

Pero, ¿de qué trata el libro?

Páginas

¿Por qué leer El Libro Negro del Programador?

Adquirir desde:
Amazon (kindle eBook / papel)
CreateSpace (papel)
PayHip (epub / mobi / pdf)

El libro negro del programador.com
Segunda Edición - 2017

Archivo

Trabajo en...

Mis novelas...