Tinselcity

¡Ay, ay, ay, Agile!

Ay, ay, ay, Agile es una pequeña colección de escenas cotidianas, fragmentos de retratos de programadores. Todo es real. Ojalá tuviera imaginación para imaginar estas cosas y no las viviera en la realidad. No pretenden ser humorísticas. Tampoco pretendo humillar a nadie, ni protestar o quejarme de nada. Son simples retratos.


George recibe una tarea que consiste en añadir uno de esos tutoriales/demostraciones embebidos en la aplicación para resaltar e informar de una nueva funcionalidad. En la tarea no viene ninguna explicación sobre qué debe mostrar o decir el tutorial. Mirando en la tarea original de la funcionalidad no viene tampoco ninguna explicación sobre cómo se usa la funcionalidad o qué debería ser lo más representativo o destacable.

George pregunta a la persona que implementó la funcionalidad pero esta, aunque le explica de qué trata, tampoco le sabe decir qué debería poner en el tutorial. George se lamenta en voz alta diciendo que podrían estar un poco más definidas las tareas.

- Agile significa menos documentación - le recrimina Karen desde la mesa de enfrente.

Sorprendido, George insiste en que le parece normal saber por lo menos qué es lo que tiene que hacer.

- Agile significa documentación menos detallada y más abierta, porque la documentación no vale nada. Lo que tienes que hacer es trabajar en equipo - le corrige Karen.


Una mañana me dice Tom:

- Oye. Mira, yo intento ir mejorando las cosas que veo en los JSPs cuando tengo que modificar algo pero ya es la cuarta vez que Karen me echa la bronca por limpiar algo. Lo siento, pero no voy a seguir haciéndolo porque no quiero que me eche la bronca otra vez.

Le he dicho que no se preocupe, que no pasa nada; que no lo sienta, que ya lo siento yo.


- Bueno, esto son las promesas de jQuery. No sé si las conoces. Es para manejar la asincronía - el Arquitecto siempre asume que nadie sabe nada


- Edward, tienes un desajuste de 14 minutos en las imputaciones del mes de Septiembre. Por favor arréglalo cuanto antes. - el jefe, que algunas semanas antes aseguraba que aquí no se venía a hacer horas y que los tiempos eran simplemente informativos, para vosotros mismos.


En la reunión “explicativa” de antes de empezar el sprint donde nos cuentan lo de Agile:

- Una vez que empecemos el sprint, no se quita ninguna tarea del sprint. Repito, no se quita ninguna tarea del sprint. - dice enfáticamente Karen.

Semana y media después, en medio del sprint:

- Frank, desasígnate esta tarea porque la sacamos del sprint. - oigo a Karen decir.

- ¿Qué? Pero ¿así sin más?

- Sí. Y si ya has imputado algún tiempo a esa tarea, bórralo. - dice Karen dando la conversación por terminada.


En una reunión, dos personas que han sido contratadas explícitamente para mejorar la calidad del proyecto describen el horror que han visto en el código. Es todo tan desorganizado que no se siguen ni siquiera unos mínimos básicos de orden y limpieza, así que están proponiendo implantar un proceso de “buenas prácticas” con, al menos, unas normas simples y fundamentales para dar algo de consistencia y coherencia al código.

El Arquitecto es el responsable directo del proyecto desde su inicio. Su aportación en la reunión es:

- Yo es que como soy Fullstack no tengo problemas con las buenas prácticas. Estas cosas a mi me salen de forma natural ya. Pero es cierto que, claro, el resto del equipo igual le cuesta más.


En un cierto formulario de una sección de la aplicación, se introducen hasta 5 direcciones de correo electrónico de contacto. Estas direcciones se validan en servidor originalmente. Se envía el formulario, se valida apoyándose en la infraestructura de validación de Struts y, si hay errores, se redirige de vuelta al mismo formulario pero con un mensaje de error.

Cuando se desarrolla esto, XHR (“AJAX”) ya existe y se usa en todos sitios desde hace años. Validaciones simples hechas en cliente llevan existiendo muchísimo más tiempo, claro. Aún así, tardan 3 años en decidir que tener que hacer la petición completa, ir y volver del servidor y repintar la página entera por un error en una dirección de correo electrónico es una experiencia mejorable. Se les ocurre, ¿por qué no validar en cliente?

El Arquitecto construye una expresión regular en JavaScript y una función validarEmail. Durante los siguientes 6 años, la aplicación funciona de esta forma:

  1. Cuando el usuario ha introducido las direcciones de correo y pulsa el botón de aceptar, las direcciones de correo pasan por la función validateEmail.
  2. Si una dirección no es válida, se escribe en un campo oculto el número del campo no válido.
  3. El formulario se envía a servidor de todos modos.
  4. En servidor no se validan las direcciones de ninguna forma. Lo que se hace es mirar si el campo oculto está relleno.
  5. Si lo está, entonces se redirige de nuevo al formulario igual que se hacía antes, marcando la dirección errónea gracias al campo oculto.
  6. Sólo hay un campo oculto, así que si hay varias direcciones erróneas, solo se marca como errónea la última. Si el usuario sólo corrige esa, que es lo más natural, se vuelve a repetir todo el proceso, con petición y recarga de toda la página cada vez.
  7. Además, la expresión regular que tienen no está demasiado bien y deja pasar por buenas muchas direcciones claramente erróneas. Después de todo el proceso, aún es posible introducir direcciones malas en el formulario y que se acepten porque en servidor ya no se validan.

(Nota: Sí, al encontrar esto lo he arreglado y lo he dejado bien xD)


En una reunión sobre el funcionamiento del “equipo”, estamos la mitad del equipo. Estamos “los desarrolladores” pero no están “los analistas”. Michael, el jefe, nos aclara con mucha insistencia:

- No son “ellos” y “nosotros”. Somos un equipo. ¡Estamos todos trabajando juntos! Os tenéis que meter esto en la cabeza de una vez. Tenéis que cambiar vuestra forma de pensar.

Exactamente dos minutos después, Michael dice:

- Ya hablaré con ellos cuando sea oportuno, ahora de lo que se trata es de cómo trabajáis vosotros.

Unas horas después, según salgo hacia casa uno de los analistas me ve algo decaído y me dice:

- Mira, tienes que entender un poco la dinámica que hay aquí en este proyecto. Por un lado estamos nosotros, que estamos aquí desde el principio y tenemos una relación más o menos cordial. Luego está el otro grupo, que vinieron hace unos 8 años.


Hay un componente que permite ejecutar diferentes comandos sobre lo que haya seleccionado en un listado. Se configura pasando los varios comandos como funciones de JavaScript y el controlador este proporciona también una serie de opciones adicionales sobre su funcionamiento. En particular, podemos proporcionar una función de callback que puede interceptar el proceso antes de que se ejecute la operación y realizar tareas adicionales (por ejemplo, rellenar un campo oculto con cierto dato, o comprobar que la selección es adecuada para esa operación) y puede decidir que la operación se cancele.

Al principio del código del componente está la explicación. Hay un:

var OPC_CANCEL = true;

Y la explicación dice:

/**
 * ...
 * - preExecOpCB (opcional): callback que se ejecuta  antes de comenzar la ejecución de la operación.
 *   Este callback puede devolver return OPC_CANCEL (true) para cancelar la ejecución del execOp
 * ...
 */ 

En el código, hay alrededor de cien ocasiones donde se usa esto. En todas ellas aparece:

    return OPC_CANCEL (true);

Y obviamente en todas ellas da un error porque OPC_CANCEL no es una función. Esto ha estado así siempre, durante 10 años. Nadie se ha dado cuenta nunca. Es más, hay un punto concreto en el código donde alguien, muy optimista hace:

    return OPC_CANCEL (false);

Que tampoco funciona, claro.

Dos meses después: Karen ve el cambio y le pregunta al Arquitecto si sabe de qué va esto. El Arquitecto no sabe. Dice “¿Había algún error quizá? No sé.” El Arquitecto nunca se preocupa de si su equipo hace las cosas como se deben hacer. Tampoco de explicarles nada.


- No, no, no. Te estás complicando. No hay ningún servicio para modificar. Solo hay dos servicios. El servicio de crear registro nuevo y el de anular que antes borraba pero ahora anula. Entonces si cambia el estado a anulado, tú llamas a anular. Si cambia a reactivado, tú llamas a crear uno nuevo y el de crear uno nuevo si encuentra uno existente anulado, lo reactiva. Pero si el usuario no tiene permiso para ver los anulados, cuando intenta crear uno nuevo, el de insertar lo detecta también pero no lo reactiva, le da un error. Y si mueves de fecha un registro entonces primero llamas a anular el viejo y luego a crear uno nuevo en la otra fecha. Y si hay uno anulado en esa fecha que no puedes ver, entonces te da un error, pero el otro se deja anulado también. No te compliques.

Minutos después, por e-mail, dice:

- Hay que crear el servicio de modificar fecha, que llama a baja y a insertar.

Los registros, por cierto, no tienen clave. Se buscan por fecha y se confía en que no puede haber dos registros en un mismo día. Obviamente existen registros en el mismo día.

Al día siguiente descubro que el servicio de borrar que antes borraba pero ahora anula ni borra ni anula. No se usa desde hace años y hay que hacerlo nuevo. Sin complicación, claro.


- Eso lo dirás tú. Porque yo he estado leyendo muchísimo sobre Agile últimamente y Agile dice que no documentación.


Voy a ver a la analista…

Una pregunta muy concreta. El tema es que es estoy haciendo ConfirmarBajaCosa…
Eso ya está hecho.

Ya bueno, pero hay que rehacerlo con el cambio este.

Sí, pero ya existe. No es hacerlo; solo es modificarlo. Ya tienes el esqueleto y todo, solo es cambiar un poco.

Bueno, cambian los parámetros de entrada, cambian las validaciones, cambia que antes era un delete y ahora es un update, cambia la salida porque antes no se devolvía nada y ahora sí.

Pero ya existe, solo es una modificación.

Eh… vale… En fin, la pregunta es que cuando el estado…

Sí, eso está en la documentación.

Sí, sí, pero a eso iba. Es que lo que pone en la documentación…

Sí, es muy sencillo. Si eres gestor, se pone a 2 (propuesta_anulada) y si no a 4 (aceptado_anulado).

Eso. Pero es por confirmar, porque…

Sí, sí, pues así es como tiene que ser.

…pero estaba pensando en el caso en que eres gestor pero está en estado 3 (aceptado)…

Sí, sí, si eres gestor se pone a 2.

Lo digo porque si está en estado 3 (aceptado) pasaría a 2 (propuesta_anulada) y parecería más lógico que fuera 4 (aceptado_anulado).

… Ah, sí, en ese caso sí. Claro. ¿No está puesto así en la documentación?

No, está lo que decías antes.

Bueno, pues ahora lo corrijo, pero vamos sí, es evidente. De 1 pasa a 2 y de 3 pasa a 4.

He ido guardando algunas preguntas para Gunther, el experto en BBDD, que contrataron para ver si ponía orden en el infierno de PL/SQL. Después de un par de dudas le pregunto por una práctica muy habitual en el proyecto.

- Esto, ¿hasta que punto es normal?

- Mira, yo no lo he visto nunca. Bueno, quizá alguna vez algo parecido pero así nunca.

Hay unas tablas generales. Son tablas que contienen generalmente configuraciones o valores casi-constantes. Por ejemplo provincias o tipos de comunicación con un servicio externo. Que son casi constantes porque aunque parezca que algunos pueden cambiar no han cambiado en 20 años. Hay 3 tipos de comunicación. Ya está es lo que hay. Estas tablas no tienen nombre, se llaman cosas como M123 o A77 o D154, porque, sí, no son una o dos tablas genéricas, son unos cuantos cientos de tablitas.

Ahora resulta que tienes en otra tabla una columna tipo de comunicación, algo como tipo_comunicacion_el. Y entonces es cuando aparece otra columna: tipo_comunicacion_tb a su lado. Esta columna contiene el nombre de la tabla en la que se encuentra tipo_comunicacion_el. En algunos casos esto significa que en un proceso hacen una llamada en plan “busco una cierta fila, cojo el nombre de la tabla y con eso voy a buscar en la tabla general algún dato extra sobre, en este caso, el tipo de comunicación”. Esto, en realidad, no se hace prácticamente nunca. Porque el contenido de esa columna es fijo. Es decir, tipo_comunicacion_tb es M144 para todos los registros de la tabla original. No es que pueda cambiar de unas filas a otras. Vamos, que en una tabla con 1000000 de filas, se guarda M144 un millón de veces.

¿El resultado? M144 aparece escrito a fuego en unas cuantas decenas de sitios. Nunca se lee realmente el valor de las tablas, se escribe en el código directamente. Cada vez que se escribe un registro nuevo, se acompaña con M144, a fuego, que unas veces viene en el proceso almacenado y otras viene desde la llamada externa desde Java, y así M144 también aparece a fuego unas cuantas decenas de veces más en el código Java.

No todo son desventajas1). Esta generalidad de las “tablas generales” ha permitido que se escriban ciertas utilidades de forma genérica. Esto significa exactamente esto: Que en cliente, en JavaScript pueda haber también algunos miles de códigos como M144 a fuego.

Lo peor de todo es cómo lo tienen tan asumido que se saben muchos códigos de memoria. “¿Familia de artículos? Mmm… La tabla D104.”


La parte de Java está muy bien. La parte de front es un caos. Y la parte de los PLs también. Pero la parte de Java está bastante bien porque es lo que más he hecho yo. El Arquitecto

A la vez…

La parte de front llega hasta los PLs.

Es decir, que la parte que está muy bien… ¿es parte del caos? ¿O qué?

Mientras tanto en otro tiempo y lugar…

Vamos a hacernos unas utilidades para pasar de Array a List y viceversa porque Collections.toArray y Array.asList solo existen desde hace 10 años y no los conocemos. Y además, esos podrían servir con cualquier tipo de contenido pero nosotros vamos a hacer uno que solo nos sirva para Strings porque todo lo que manejamos son Strings2) porque todo lo sacamos así de base de datos. Eso sí, ya que lo hacemos nosotros, nos vamos a asegurar que si el array o lista original están vacíos no devolvemos una lista o array vacíos sino que devolvemos null, porque así evitamos errores, ¿no?

La parte de Java está muy bien.


Cada vez que dicen que una tarea es “de Arquitectura” lo que significa es que es algo que no saben hacer. Nada más.

Hoy:

Te voy a pasar una tarea de Arquitectura, de la parte de front, claro.

La tarea: escribir un PL en el que se devuelva un array. Los PLs también son front.


El Arquitecto nos convoca a una reunión a las 11:00. Y así, a las 11:20, en una sala, nos reunimos para una presentación de “lo que será la nueva Arquitectura que hemos pensado para próximas aplicaciones a desarrollar alrededor del proyecto principal”. Quieren que sea común para todo lo que hagan en el futuro. Yo estoy en la reunión porque quieren mi opinión, dice. Hay un par de desarrolladores más que, aparentemente, ya saben todo esto.

Ojo, tenemos una pizarra…

Dibuja una caja en la que escribe “Rest” y al lado “API”. Dentro de la caja, bajo “Rest”, garabatea algo que se parece a “Spring Boot”.

Esta parte no me preocupa. Ya está decidido y está bien.

Dibuja otra caja. Encima escribe “Front”, dentro “HTML5, JS, CSS”. Al lado IONIC.

Básicamente lo que hemos pensado para la parte de front es usar HTML5 con Ionic para todo.

Los siguientes 30 minutos pasan contando pequeñas anécdotas sobre aplicaciones con las que han tenido alguna relación en el pasado, pero que en principio no tienen por qué ser iguales a las que se desarrollen en el futuro.

La pregunta para mi es si estoy de acuerdo o no. O más bien que esté de acuerdo, que valide su decisión. Pregunto si sabemos qué tipo de requisitos van a tener esas futuras potenciales aplicaciones. No está claro, algo general, “algo normal,” - dicen - “; si hay algún requisito muy demandante o especial, seguramente esta arquitectura común a todo, no aplique pero serían casos muy puntuales”.

Me vuelve a explicar que quiere saber si estoy de acuerdo o si tengo alguna pega. O más bien que estoy de acuerdo y no tengo pegas. En mi cabeza estoy contestando que me trae sin cuidado si eligen Ionic o Bubonic o lo que quiera. De mi boca sale algo más comedido.

Hombre, así sin saber qué tipo de requisitos, qué planes hay, cómo son esas supuestas aplicaciones futuras, es un poco difícil y no creo que haya mucha diferencia entre elegir Ionic o elegir otra cosa.

Intento explicar que lo que hay que saber es qué es lo que van a querer desarrollar con eso, no qué librería elijan, pero noto que desde ese “así sin saber…” de antes, ya no me escucha, solo intenta interrumpirme para hablar él.

Dejo que me interrumpa y me explica de nuevo que serán “cosas normales” durante unos cuántos minutos. Y vuelve a explicarme que la reunión “es un poco para que dé mi opinión y diga qué me parece”. Es decir, que quiere que diga su opinión y diga que me parece bien.

Finalmente digo que me parece bien Ionic pero que no creo que suponga ninguna diferencia elegir eso o elegir otra cosa. Pero que sí, que me parece bien.

El Arquitecto da por terminada la reunión con éxito, anunciando “próximos pasos” que por algún motivo incluyen instalarme a mi VSCode. Lo dejo pasar teniendo claro que eso no ocurrirá.

Según vuelvo hacia mi mesa, oigo que uno de los desarrolladores pregunta al Arquitecto a qué tarea imputa el tiempo de la reunión.


Hoy es día de visita. Vienen directores, responsables de áreas, coroneles, mandamases.

Hoy se disimula. Hoy no hay música de chiringuito de fondo todo el día taladrando y acompañada del tipo que se cree que sabe silbar. Hoy el desayuno se adelanta un poco y se acorta a su duración oficial para que no quede esto vacío cuando vengan las visitas. Han desarrugado la persianilla de la ventana que siempre está arrugada; sigue hecha una pena pero un poco menos arrugada. Los caballetes con papel que nadie usa pero decoran las reuniones, hoy no están en un rincón sino listos y preparados para que nadie los use de todos modos pero parezca que sí, que habitualmente se usan.

Hoy es todo mentira. Hoy todo es teatro.


Me habían avisado y no quise escuchar. Karen es “vengativa y rencorosa”, me dijeron. Lo ignoré porque la mayoría de comentarios y cotilleos así es mejor ignorarlos.

Hace unos días hice un cambio masivo. En realidad, comparado con otros que he hecho, este era relativamente pequeño: 25 páginas. Lamentablemente rompí una sin darme cuenta. Así que ayer Karen, alterada me amenazaba diciendo que no podía hacer esos cambios masivos, que esto iba a tener que cambiar.

Arreglé el problema en unos minutos, pero eso es irrelevante. Lo relevante es que hago estos cambios porque son necesarios, porque me contrataron para hacer estos cambios, porque viven entre la basura y, a veces, que haya pequeños fallos momentáneos (ni siquiera en producción, en los entornos de pruebas, que están para eso) es el precio que hay que pagar por sacar la basura. La mirada de Karen me decía que no estaba de acuerdo. Karen nunca está de acuerdo con nada, de todos modos.

Hoy, Karen me dice “está cerrado trunk”, y “te voy a pasar algunos errores”. Y me empieza a pasar cualquier error que se le ocurre. Resuelvo unos cuantos pero está cerrado trunk así que no los puedo subir. Se lo comento a Karen y me dice que está cerrado trunk (que sí, que ya) y que vaya resolviendo y mañana los revisaremos y los subiremos.

Insiste en que está cerrado trunk, pero al rato me entero -ninguna sorpresa, la verdad- que no es así. Que está cerrado para mi. Que otros pueden subir cosas pero yo no.

Le explico a la gente que sus errores críticos que no les dejan trabajar, están en espera. No les doy más detalle, pero es en espera de que alguien se eche la siesta que necesita.

Al día siguiente, poco antes de que se vaya a hacer el despliegue en los entornos de pruebas, Karen se va a desayunar durante media hora. Yo sigo “castigado”; los arreglos de los errores críticos no podrán subir hasta dentro de unos días.

Mientras yo estoy bloqueado, el Arquitecto sube un cambio que rompe todas las páginas. Le quita importancia bromeando:

Bueno, culpa mía no. Culpa de Steve por haber hecho el despliegue. Ja, ja.

La mejor estrategia frente a los juegos de poder y control es no jugar. Al final se juegan ellos solos.


Me han contratado con la idea de tener por fin a alguien que sepa bien de JavaScript.

El Arquitecto está explicando un poco malamente a un analista que mejor setTimeout que setInterval “porque es mejor con eventos asíncronos”. Se lo explica para que él a su vez se lo explique a la desarrolladora que siempre me recuerda que ella no es desarrolladora, que le dieron un cursillo y le soltaron una aplicación hecha con Dojo.

Aparentemente tienen un problema por el que, a veces, se bloquea el navegador al intentar abrir una ventana en la que se carga un visor de mapas. El Arquitecto habla con gran seguridad:

Puede que sean los setInterval… Bueno, es que hay errores que nunca se sabe…

Evidentemente, a pesar de mis ofrecimientos, a nadie se le va a ocurrir pedirme ayuda a mí. Y, la verdad, me siento afortunado con esa situación. Es una función que escribió ayer un desarrollador que ha declarado abiertamente que no quiere saber nada de lo que pueda decirle y que está llena (la función) de estupideces con this innecesarios.

El Arquitecto ahora está hablando de lo mucho que le gustaría probar a hacer esto usando postMessage porque, dice, “nos ahorramos todos los problemas de comunicación entre dominios”. El visor que se carga está en el mismo dominio, pero eso es irrelevante. Al Arquitecto le gustaría probarlo, aunque no tenga nada que ver con el problema actual.


El GlassFish ese me suena que es un servidor nuevo de Oracle. El Arquitecto, Noviembre 2019


Tenemos una convivencia en la oficina con unas reglas no escritas normales de no matarnos y esas cosas.

Ahora mismo estoy escuchando tres músicas diferentes porque hay a quien le gusta escuchar la música con altavoces. También hay a quien le gusta silbar aunque no sepa hacerlo y a quien le gusta canturrear como si fuera un perro abandonado llorando.

A todos ellos les gusta hacer estas cosas con un volumen suficiente como para que oiga toda esta cacofonía de músicas y lamentos aunque me ponga los auriculares.

Por unos instantes pienso que esas reglas de no asesinar quizá se podrían revisar.


Dos semanas después, sigo castigado sin acceso al SVN. Y no es solo a trunk; tampoco puedo subir nada a la rama de desarrollo.

Como demostración de fuerza sería bastante impresionante3), si no fuera porque me da igual.


Este de aquí es un find. Este de aquí es una búsqueda. Este de aquí es este de aquí. El Arquitecto, explicándose meridianamente.


Están haciendo un proyecto que debería ser ejemplo de cómo hacer las cosas.

“El campo fechaFin ¿es obligatorio?” - pregunta Geoffrey.
“No lo sé. No sé cómo lo he puesto. Haz un test unitario pasándolo a null y mira a ver qué pasa” - dice el Arquitecto.

Me hace recordar que así es como hacen los “tests unitarios”4) cuando los hacen. Escriben código, y al día siguiente escriben tests para ver qué es lo que hicieron ayer.

Los tests están desactivados en el build, obviamente. Hay unos 20 test. Tardan unos 15 minutos.

Es un proyecto que debería servir como ejemplo. A nadie se le había siquiera ocurrido ponerle un readme, unas instrucciones básicas de instalación, una mínima guía de desarrollo.


Long idCode = null;
idCode = idCode.parseLong("612");

La parte de Java, que “está bastante bien”.


Están haciendo pruebas de carga…

“Está el WebLogic a tope de memoria” - dice Marcus, el departamento de sistemas. “Está con las pruebas de la subida de ficheros.”
“Bueno, es normal. Eso lo optimicé para máximo consumo de memoria” - responde el Arquitecto. “Hace 5 pasadas al XML por cada petición…”

“Pero está a tope con solo 5 subidas simultáneas. Y si se ponen a subir a la vez cien usuarios…?”

“Nah, eso no va a pasar. Además blablabla así que en todo caso será un problema de red.” - No dice literalmente blablabla, pero sus palabras suenan muy parecido, aunque mucho más largo.

Semanas después…

No hemos pasado las pruebas.

La obsesión por el tiempo… Llegar y encontrar un correo explicando que la celebración navideña que hicieron una mañana hay que imputarla a la tarea tal y cual.


¿Me puedes echar una mano con un tema de JavaScript?
Claro, cuéntame.

…(me cuenta el problema)… Lo primero que he pensado es usar una promesa. Y entonces he hecho… (me explica su solución)

Ya veo. Pero no hace falta usar una promesa. Puedes hacer esto otro mucho más sencillo.

Ah, vale, sí,, es buena idea. Pero por curiosidad ¿por qué no me funcionaba?

(…explicación larga de promesas, eventos, asincronía…). Espera, ¿tú las promesas qué tal las llevas?

Ah, no, yo ni idea. Sé que hacen como que se espera o algo pero la verdad es que ni idea.

No se lo he dicho porque en el fondo no es culpa suya pero… si no sabes usar algo, no pienses en ello como lo primero que se te ocurre para solucionar cualquier cosa.


El Arquitecto, que sabe un montón de Java, que ha hecho todo bien en la parte de Java, acaba de comentar así casualmente que no tiene ni puta idea de cómo funcionan… los niveles de log en log4j.


Hay un concepto que al Arquitecto le rehuye. Estoy convencido de que hay bastantes conceptos que lo hacen, pero uno muy concreto es el de “terminar una conversación”. El Arquitecto no termina las conversaciones tanto como las agota, las exprime y destroza hasta dejarlas secas y muertas. Ya he contado alguna vez cómo es frecuente que insista repetidamente en algo hasta que le den la razón. Pero esto va algo más allá.

Hoy, 7 minutos antes de la hora de irme, me pregunta por un tema de acceso al portapapeles del sistema desde JavaScript. Como es habitual, había hecho una chapucilla y buscaba aprobación. Y me he acordado de una escena que ocurre muy a menudo.

El inicio de la escena tiene algunas variaciones. En ocasiones el Arquitecto está en su mesa y alguien acude a preguntarle algo. Otras veces el Arquitecto asiste a una reunión con cuatro o cinco personas más. Otra variante común es que el Arquitecto esté haciendo su paseillo mirando entre las mesas, buscando alguien con quien gastar un par de horas sin hacer nada de particular. Sea como sea, la conversación empieza. Y luego continua. Y sigue continuando y continuando, dando vueltas a lo mismo o a cosas nuevas pero sin llegar nunca a una conclusión.

Los demás sí que llegan a la conclusión. Yo mismo he llegado ya muchas veces a la conclusión de que el Arquitecto en realidad solo está hablando delante de ti pero no está realmente hablando contigo. Habla consigo mismo. Pero no, no me referia a esto. Los demás llegan a una conclusión. Después de 30 minutos o de 5 horas, les oyes decir “Bueno, pues entonces hacemos esto” o “Pues voy a hacer esa opción” o “Lo pruebo y te digo algo” u otras cosas que casi rozan el “no queda más que decir; se acabó; damos por concluída la conversación”. No solo eso, sino que terminan la conversación físicamente. Se van. Se alejan del Arquitecto y se van a su sitio. O se levantan de la reunión y recogen sus cosas. O a veces se levantan de su proprio puesto para huir hacia algún refugio como el baño, un cigarrillo, o alguna otra excusa para poner distancia entre ellos.

Y entonces… el Arquitecto va detrás.

Se levanta también y se va detrás y empieza a repetir algo de lo que ya se ha dicho para hacer que la conversación continue, aunque sea en otro lugar. La reunión pasa de la sala al pasillo. O de estar sentados a una mesa a estar de pie a dos metros de esa mesa. Del puesto de trabajo del Arquitecto al de la persona que vino a preguntar. Recuerdo que por lo menos en una ocasión le he visto decir que “ah, pues voy yo también al baño” para continuar la conversación antes, durante y después de hacer sus cosas.

La única estrategia que casi siempre es efectiva es el silencio. Cuando termino de hablar, no digo nada más. Y si él dice algo, yo no. Solo entonces da la conversación por agotada… O casi. Porque como mi sitio está frente al suyo, a veces al cabo de un minuto o así dice algo más y lo dice en un tono y a un volumen calculado perfectamente para que se pueda interpretar tanto como que sigue hablando conmigo como que simplemente hace un comentario casual en voz alta para sí mismo.

Hay que resistir la tentación, por mucho que lo que diga esté -nuevamente- mal. Es hora de irse a casa y por mi se puede quedar todo el fin de semana elucubrando sobre su chapucilla.


Un día el Arquitecto me enseña una de sus chapuzas. Una particularmente mala mezclando Promesas y callbacks cuando en realidad no necesita ninguna de las dos.

Se lo digo, suavemente, sugiriendo una solución mucho más simple. Dice algo como “pero es que es asíncrono; necesito la promesa…”. Se lo enseño, intentanto que no parezca que su código es una estupidez absoluta sino simplemente que se puede hacer más fácil de otra forma.

No se queda muy convencido, pero me dice:

Vale. Entiendo. Claro. Por supuesto la idea es hacer de la mejor forma posible. Voy a darle una vuelta más.

Me giro y me voy a mi mesa, que será una distancia de 1 metro quizá. Puede que dos segundos, tres como mucho antes de que esté sentado en mi silla.

En esos tres segundos, el Arquitecto ya ha hecho commit del código al SVN. En trunk por supuesto.

Unos minutos más tarde le oigo presumiendo ante otro desarrollador sobre su cosa.

Y es asíncrono, así que tuve que usar una promesa y unos callback aquí. Bastante follón ha sido resolverlo, sí.

Cuando llegué, había en la sala dos tablones Ágiles. En realidad, eran simplemente unas cuantas láminas de papel de buen tamaño puestas juntas y sujetadas en la pared con cinta de pintor. Sobre ellas, algunos post-its.

Uno era el panel de kanban del equipo de desarrollo. Otro el del equipo de “oficina técnica”, que básicamente son Karen, el Arquitecto y los trajes. Este tiene tres secciones: pendiente, en curso, completo y está en la pared justo detrás de los puestos de Karen y del Arquitecto.

Cuando llegué ese tablón tenía 21 post-its, la mayoría de ellos con una única letra o un par de letras (CJ, P, BD, y así). No sé que tenía exactamente 21 porque los contara en su momento sino porque tras siete meses, sigue teniendo los mismos 21 exactamente en los mismos sitios. Por lo menos hasta esta mañana, que por la noche se ha despegado alguna de las cintas y ha caído una sección entera al suelo.

Al llegar, el Arquitecto ni la ha mirado. Karen sí, la ha visto, la ha apartado a un rincón para que no se pise y ahí se ha quedado. Supongo que otros siete5) meses más.

¿Y el otro tablón, el de desarrollo? Oh, ese tiene un post-it con un jamón, otro con un futbolín y otro reclamando que pongan pizarras.

El tablón, ahora solo tablc


Está Avelino a mi lado con el Arquitecto.

Pues gracias; ya sé por dónde tirar - dice
Pues habría que depurar y blablabla - el Arquitecto sigue hablando

Sí, bien. Ya lo miro yo.

Blablabla - sigue

No hace falta más. Ya lo miro.

Blabla - más

Aha, pero ya lo depuro yo…

Blablabla - le quita el ratón de la mano y añade: - dale Alt Shift P.

. . .


El Arquitecto está con Maxwell mirando algún tipo de error. Al cabo del rato de mirar y tocar, el Arquitecto dice muy serio:

El problema es que ha pasado algo raro.

Por algún motivo, me gusta esta imagen…

Valor para el negocio


Le digo a Lizzie que estoy mirando el problema que me ha comentado pero que voy lento porque esa query parece que tarda mucho…

Sí… tarda un poco…

Y esa es toda su explicación. Tarda, sí. Y ya lo sabemos que tarda. Es lo que hay. Tarda aproximadamente una hora y cuarto. Click, hora y cuarto, listado. Así es la vida.


Karen habla con Montgomery, que se sienta a mi izquierda. Yo tengo los cascos puestos para huir un poco de la cacofonía de música de chiringuito, aire acondicionado industrial y conversaciones diversas. Aparentemente no oigo lo que dice Karen. En realidad hace un rato que he apagado mi música y oigo todo.

Luego Karen se levanta y va acercándose a varios desarrolladores y les va diciendo lo mismo que a Montgomery. Llega a Lizzie y a Steph que están justo detrás de mi. Karen no susurra pero sí habla uno o dos tonos por debajo de lo que acostumbra y les cuenta a ellas también lo mismo que a los demás. Karen dice:

Vamos a abrir el repositorio por si tenéis algo que subir de alguna tarea o incidencia que hayáis terminado. Mañana a primera hora subimos.

Karen cree que no la oigo. Yo tengo un par de arreglos que subir, sí, pero a mi no me abren el repositorio. Mis arreglos, por el motivo que sea, tendrán que pasar unos días más, quizá una semana más, esperando en mi ordenador a que a Karen le parezca bien.

Al día siguiente… Me pregunta la persona que abrió las incidencias que si no había subido mis arreglos porque no lo veía arreglado. Le digo que no, claro. Le explico que Karen ha debido considerar que no había que subirlo.

Pues voy a hablar con el jefe, porque esto es un error que está en producción y debería haber subido.

Se va. Habla con el Traje. Al rato el Traje habla con Karen. Hablan los tres, luego el Traje y Karen. En ningún momento nadie habla conmigo. El arreglo esperará unos días más. Supongo.

En la siguiente subida, dos días después, finalmente puedo subir el arreglo. Quizá sea solo casualidad pero en el momento de decirnos que podemos subir las cosas pendientes Karen no está. Le ha dicho a Tricia que nos avise mientras ella se va un momentito justo ahora a hacer algo.


¡Oh, no! ¡Horror! ¡Miedo!

Ha ocurrido algo tan grave, tan sumamente grave, que nos convocan absolutamente a todos a una reunión de forma inmediata.

El Arquitecto cuenta una conmovedora historia sobre versiones de Oracle y su soporte por los DATE, TIMESTAMP, y java.sql.date y cómo, por motivos que nada en absoluto tienen que ver con él y que él no podía haber intuido en los últimos 5 años, ahora hay algunos problemas en la aplicación porque algunos PLs no tienen en cuenta si algo debe ser solo una fecha (sin hora) o un timestamp (con hora, minutos, segundos, etc).

Es algo inesperado, impredecible, totalmente culpa de Oracle; no es culpa de haber decidido conscientemente aprovecharse de un bug para hacer las cosas mal, no. Pero no nos preocupemos, el Arquitecto sabe los que hay que hacer. Será trabajo para los analistas y para los desarrolladores; será pesado y aburrido, pero es los que toca. Nos cuenta muy por encima la “solución”: usar DATE donde se deba y usar TIMESTAMP donde se deba. Eso es todo.

Karen, a su lado, añade:

Esto, por supuesto, se pondrá en la guía de buenas prácticas, en el wiki, para que quede documentado cómo se debe hacer y lo podáis mirar.

Cuando lo dice sé inmediatamente que eso no va a pasar. Dos semanas después, como esperaba, no ha pasado.

Otras dos semanas después y Gunther me confirma que el problema que parecía tan urgente y tan grave, lo están mirando los analistas, con calma, según van teniendo tiempo. Que va para largo. Y en el wiki, incluso pasadas ya seis semanas, no hay nada sobre esto, obviamente.


Gunther, el experto en la parte de datos, me confirma con cierto escándalo y vergüenza:

Sí, sí… Las migraciones de datos las hacen los analistas a mano, porque prefieren hacerlo ellos. Lo llaman plumeros.

Eh. Pequeños engranajes que se creen importantes para la máquina.


function alerta(a){alert(a);}


Existe una tendencia muy clara de los desarrolladores del equipo a no interesarse lo más mínimo por las herramientas que usan. No intervienen en su instalación, ni en su configuración, ni en nada.

Hace un rato Reginald ha ejecutado Maven y le ha dado un error. Ha avisado a la persona “de sistemas” para que se lo arregle y mientras se lo arregla ha salido a fumar.


El Arquitecto siempre habla del código como si todo lo hubiera hecho él. “Cuando pasa esto hago esto otro.”, dice cuando describe una condición en algún proceso.

Siempre… Menos cuando hay problemas. “A ver si es que habéis metido un bucle infinito…”


Eso se hará automáticamente cuando estén todos los cambios. Pero claro, cuando digo automáticamente no significa que se haga todo zas y ya está. Hay que ir uno a uno haciéndolo a mano.

Karen, redefiniendo las palabras.


Montgomery me pide ayuda. Montgomery no sabe pedir ayuda. Me dice solo “¿Puedes venir un momento?” y yo, claro, dejo todo y voy un momento. No me explica el problema, solo empieza a hacer cosas en la página aparentemente esperando que yo entienda. La realidad es que no sabe explicar el problema, y por eso no lo explica.

Finalmente, tras un buen rato y varios tira-y-aflojas, entiendo: quiere algo imposible. Quiere que un componente que es demasiado grande para el hueco que tienen, quepa en el hueco, sin hacer este más grande ni el componente más pequeño. Pero él no sé da cuenta de la inconsistencia.

Pasamos un rato buscando otra solución, voy tirando del hilo poco a poco. Vamos acercándonos a una solución y, de pronto, un golpecito en su hombro.

Qué se van a almorzar.

Y se va. Me dice que seguimos luego y se va. No vuelve hasta hora y media después.


Hay unas pocas gráficas hechas con Highcharts, una librería de JavaScript bastante clásica. Obviamente es una versión sin actualizar desde hace 6 años, pero en este caso eso no es un problema muy grande.

No se usa directamente Highcharts sino una cosa6) que lo ata al sistema de ventanas horrible de la librería horrible DHTMLx. Esto hace que solo se saquen gráficas dentro de paneles de DHTMLx, por algún motivo.

Franklin está con una gráfica de estas. La tiene que sacar en una ventana de jQueryUI porque tiene que incluir otras cosas y eso de antes solo te permite tener la gráfica y nada más. Así que hay una ventana de jQUI con dentro una ventana de DHTMLx con dentro la gráfica de Highcharts. En fin…

El caso es que para que quepan las cosas un poco mejor, Franklin quiere poner la leyenda de la gráfica debajo, en lugar de a un lado llevándose el 25% del ancho para poner cuatro palabras.

Highcharts en sí es muy flexible y es una operación fácil… Hay unos valores por defecto de posicionado. Luego están las opciones globales que pone nuestra aplicación, que están en otro sitio. Y luego, no sé sabe bien porqué, en el lado de servidor, a la hora de sacar los datos para la gráfica, a alguien se le ocurrió que era buena idea incluir ahí otros ajustes para obligar a que la leyenda vaya en otra posición distinta. Y como Franklin no quiere tocar el código de la parte de Java, entonces, desde hoy, también hay otro sitio más, al recibir la respuesta para pintar la gráfica, donde se ajusta de nuevo la posición de la leyenda, para ponerla en donde dicen los valores por defecto originales.


Una parte de mi trabajo7) es escribir documentación. Voy limpiando mierdas y voy escribiendo la documentación de cómo no volver a meter esas mierdas sino hacerlo un poco mejor. ¿Hay 14 funciones distintas para abrir una ventanita de aviso/confirmación? Pues nada, unificamos y escribimos en la documentación cómo se debe hacer para que todos lo hagan igual. Y ya de paso, a lo mejor, ojalá, para que el Arquitecto deje de meter más funciones para hacer lo mismo con pequeños y molestos errores. Ah… ojalá.

La documentación va en un MediaWiki, en el que lamentablemente no está bien instalado el resalte de sintaxis. Esto al principio me molestaba. Tanto como para pedirle a Marcus, el departamento de sistemas, que a ver si sería posible ponerlo bien no solo para que quede mejor, sino también porque todas las páginas que intentan usar el resalte de sintaxis quedan marcadas como errores. En fin, que estaría bien que eso funcionara en una documentación sobre código. Pero no. No le echo la culpa a Marcus, el departamento de sistemas, porque tiene mucho trabajo, pero se lo pedí hace unos seis meses y nada.

Y mientras pensaba en eso y en que queda mucho mejor la documentación con el resalte de sintaxis se me ocurrió plantearlo de otra forma. Ahora uso Carbon y pongo el código en el wiki como imágenes. Que es algo que resulta odioso, porque no puedes seleccionar el código y copiar y pegar. Pero… vaya, es que realmente no quiero que copien y peguen. Quiero que escriban el código. Así que incluso mejor.

Por ahora nadie se ha quejado de que no puedan copiar y pegar, pero sospecho que es porque de todos modos solo uno o dos miran la documentación.


Hace una semana entera nos llama el Traje a: la maquetadora que se va, la persona con la que ha discutido una cierta idea, una analista que se encargará de revisar, 3 desarrolladores. Nos cuenta la tarea: Poner un enlace. Un enlace estático, sin más. Nos lo cuenta con mucho detalle, con tanto detalle que después Brendan comentará “Y para esto, ¿tanta cosa? ¿6 personas imputando media hora por un enlace?”.

La tarea, decidimos, la haré yo, porque a los otros no les entusiasma trabajar en una tarea que viene directamente del Traje.

En una semana envío un par de propuestas sobre cómo poner el enlace. La respuesta tarda un par de días. Pido que me den la URL del enlace unas pocas veces, pero la respuesta no llega. Veo que todos se lo toman con calma, así que yo también.

Lunes. Pasada ya casi la mañana entera. El Traje. Hay que subir el enlace esta misma mañana, de hecho ahora mismo ya. No tengo la URL -comento- pero si me la dais tengo todo lo demás. La URL además va en el fichero de configuración así que ni siquiera la voy a poner yo8). La tendrá que poner la persona que hace los despliegues. “Claro. Estupendo. Tú sube lo tuyo. Ahora pasamos la URL y hacemos la subida.”

Me dan la URL. En local va bien. Subo lo mío. Aviso a la persona que está esperando para hacer el despliegue que ya está todo listo. Y le doy la URL que hay que poner en el fichero de configuración. ¡Adelante!

Entre una cosa y otra, cuando finalmente está desplegado, es casi hora de irme… y la URL está mal.

Al día siguiente me explican que es que el sitio al que se enlaza no está todavía. Qué había mucha prisa por poner el enlace pero que sabían que no iba a funcionar hasta que esté lo otro. Que no me preocupe.


Un día el Arquitecto, no recuerdo bien por qué pero probablemente porque dice muchas cosas para que parezca que sabe muchas cosas, comentó en una reunión con los desarrolladores que era mejor si hacían un commit separado por cada fichero que hubieran modificado. Quizá se refería a cuando había varios cambios no relacionados. Quizá. Quizá es que el Arquitecto es así.

Y por algún motivo, algunos desarrolladores se quedaron con esa idea y cada vez que hacen un commit, hacen 3, o 7 o un par de docenas.

Yo ya no digo nada porque nadie quiere que diga nada. En un día normal a lo mejor digo entre 4 y 6 frases, contando “Buenos días” y “Hasta mañana”, aunque hay días en que está última no la digo porque no tengo ánimo para pensar en volver mañana.


He estado dándoles un poco de formación a los desarrolladores. La reciben con mucho interés.

El último día que lo hicimos9), reservé los últimos 15 minutos para que habláramos de la formación, de qué cosas querían que viéramos, de qué cosas podíamos hacer… No sé les ocurría nada que decir. En un momento sugerí un ejercicio juntos -oh, el interés aumentó- pero aclaré que no lo haría yo mientras ellos miraban, que lo tendrían que hacer ellos -interés cero-.

La cosa acabó con el comentario de alguien así de repente.

Hala, ya es la hora. Vámonos.

Así que no creo que haya más formación por mi parte.


Hoy hay una reunión importante. Va a cambiar de forma sustancial el modelo de la base de datos. Es algo que afectará a todo y la reunión es para explicar el cambio y a qué afectará.

La reunión es solo para los analistas. Los programadores supongo que no necesitan saber cosas fundamentales sobre el modelo de datos con el que trabajan.


La aplicación es grande y compleja, y por eso tiene una documentación de ayuda.

La ayuda se hace así: Una (o más) persona la escribe en un Joomla. El Joomla no es accesible para nadie10). A la hora de desplegar la aplicación en producción, el Arquitecto tiene un pequeño crawler, que por supuesto nadie más que él puede usar porque solo lo tiene él en su máquina, y lo lanza contra el Joomla. El programita se baja todo lo que encuentra en él y reescribe los enlaces por el camino. Luego lo copia al mismo servidor en el que está la aplicación.

El proceso para unas pocas páginas de ayuda nuevas que se han añadido, quizá una docena o así, ha tardado casi una hora.


En una reunión informal de pasillo, están hablando sobre el desarrollo de un cambio amplio del modelo de datos que va a empezar en próximas fechas y tendrá, seguramente, varias fases. El Traje dice y repite hasta cuatro veces que no hay que dar mucha información.

Sólo tenéis que explicar lo mínimo para esta parte del cambio. Y sólo a los que vayan a estar implicados directamente. No hay que explicar nada de a dónde queremos ir con esto.

Sigh Flow, el flujo de gestión del código.


Hay una función que está repetida 6 veces en el código y que se llama literalmente miFuncion. Ese es todo el nombre que tiene. Lleva 12 años en producción así. No es el único caso, claro. Por ejemplo, en todas (99.9%) las páginas en las que hay un componente de pestañas, se llama MY_TABCONTROL y cada pestaña se llama MY_TABPAGE1, MY_TABPAGE5, etc. (Y no, no tienen por qué tener números consecutivos siempre.)

Otra cosa que lleva 12 años en producción es una media docena de JSPs de prueba con textos y pruebas variadas que dicen cosas como “My JSP test” o “Bartolo”.

Karen suele decir que el problema es que “la migración11) se hizo muy rápido; ese es el problema”. No, Karen, no. El problema es que no tenéis ni idea de hacer nada bien, ni interés por arreglarlo. Que de aquello hace ya doce años, Karen.


Hablando del componente de pestañas… Cada pestaña es un JSP. Un grupo de digamos 6 pestañas son 6 JSPs. En todos ellos se copia el componente y se cambia cuál es la pestaña activa de ese JSP con una llamada como setSelectedTabPageName( “MY_TABCONTROL”, “MY_TABPAGE4” );, por ejemplo, cambiando el número en cada página, claro. Hasta ahí… Bueno, es mejorable pero whatever.

Hay un par de estos grupos de páginas están hechos ligeramente distintos. Bueno, es casi todo igual hasta aquí salvo que se pasa adelante y atrás un parámetro adicional a todas las llamadas tabPage. Para pasarlo hay un total de unas 2300 líneas de JavaScript -unas 80 líneas repetidas casi 30 veces- en esas páginas. A cambio de esto, en las páginas la llamada para activar la pestaña actual es igual y no cambia: setSelectedTabPageName ( “MY_TABCONTROL”, “MY_TABPAGE${form.tabPage}” ); y así se puede copiar y pegar sin tener que acordarse de cambiar el numerito.

¿Cambiar un numerito o copiar y pegar 80 líneas de JavaScript 30 veces? Uhmmm… Oh, bueno, a cambio de eso y de meter la propiedad tabPage en los varios formularios de Struts de esas páginas, no te olvides. Ah, y cambiar todas las copias de esas 80 líneas si se cambia alguna pestaña, también, que ha ocurrido por lo menos un par de veces en los últimos seis meses, sí.


Oigo al Arquitecto decir a Karen:

A lo mejor deberíamos abrir un Jira para que quede reflejado en algún sitio lo del error este de los informes.

Ese “a lo mejor” significa dos cosas. Primero, que hay muchos otros errores que no quedan reflejados en ningún sitio. Y segundo, que escriba Karen la tarea de Jira porque él desde luego no se va a molestar en hacer ese tipo de labores.


El Arquitecto ha tenido que hacer un despliegue. Al hacerlo ha visto lo que hice para poner un enlace a la ayuda y cómo la URL va configurada en una propiedad el fichero de propiedades de la aplicación. Lo ha visto más que nada porque la persona que hace los despliegues normalmente le ha dejado en las instrucciones que había que poner esa propiedad y a él no le ha gustado tener que hacer esto.

Sin decir nada a nadie -porque el proyecto es suyo y hace lo que quiere-, antes de empezar el despliegue, ha borrado la propiedad y ha puesto la URL a fuego en el enlace en el JSP. En el mensaje de commit ha puesto que…

Así no hay que tocar los properties de los entornos al hacer el despliegue.

El Arquitecto es imbécil.


El tablón, cada vez menos


Hablando con uno de los trajes, me he dado cuenta de una de las causas principales de la situación del proyecto. Nadie, ninguno en todo el equipo, y eso incluye jefes, responsables y Arquitecto, ha tenido experiencia con ningún otro proyecto medianamente grande. Este es el primero para todos ellos.


También vivimos aquí el tema de la epidemia de 2020, claro. Estas cosas sacan, como me decía Stephanie, “lo mejor y lo peor de la gente”. Puede ser.

Aquí lo que ha sacado son algunas cosas concretas:

  • Más confusión. Está claro que no hay una dirección clara, que el Traje, en su equilibrio -seguramente difícil- entre tratar con un cliente complicado y un equipo más complicado aún, elige inclinarse lo menos posible hacia ningún lado. Está claro también que el equipo no es un equipo. Es un grupo de gente que casualmente están ahí, como me dijo uno una vez “llevándose de manera más o menos cordial”12).
  • La evidencia de que es un proyecto “de horas”. Los analistas no son analistas sino operadores. La parte importante de su trabajo es esa, operar como parte del proceso de la aplicación, haciendo a mano lo que en más de 12 años no se ha querido hacer bien. Los desarrolladores no son tanto desarrolladores cuanto parcheadores. Y no hay ninguna intención de mejorar esto. Por eso y no porque sea necesario, hemos seguido trabajando de forma presencial mucho más tiempo del debido.
  • La claridad personal de entender que no saben por qué me han contratado y que, por tanto, cualquier cosa que intente mejorar aquí será, inevitablemente, con la oposición tanto desde “arriba” como -parcialmente- desde “los lados”.
  • Que el “progreso” del proyecto (entendiendo un progreso no de mejora sino de simple continuación) está y estará marcado por el capricho del Arquitecto. Según me comentó el jefe, han intentado13) que el Arquitecto delegue pero él no lo hace. Esto cuadra bastante con el comportamiento que he visto en él todo el tiempo y parece claro que es consciente del “poder” que esto le da y que no está dispuesto a cambiar.

Mientras yo pensaba todas estas cosas, mientras el Traje negociaba con el cliente para conseguir que por lo menos no trabajáramos presencialmente todos y todos los días, mientras el equipo iba perdiendo la calma, Karen y el Arquitecto hicieron “una última subida a producción”. Eran unos parches a la versión de producción que se había decidido fueran los últimos que se harían en esta versión. ¿Por qué los últimos? No lo sé, pero ha resultado ser irrelevante cuando ha resultado que la subida, según el Traje, “ha ido muy mal”. Vamos, que el arreglo subido no arreglaba. Dos días más para -en medio de todo esto- preparar un parche al parche, probarlo14), y hacer otra última subida, que en realidad es ya la tercera o cuarta última subida.


Gestionando la crisis…

Hay dos preguntas que se deberían aplicar a la hora de evaluar cómo se debe seguir trabajando: ¿Es crítico? y ¿Es seguro?

Si el servicio es crítico y seguro, no hay problema, se sigue con normalidad. Si es crítico pero no es seguro, se hace el esfuerzo de solucionar todo lo que se pueda la seguridad mientras se sigue con normalidad o con algunos pequeños cambios. Si no es crítico y no es seguro, se debería interrumpir el servicio. Si no es crítico pero sí es seguro, seguramente se debería continuar con el servicio, aunque se podrían hacer algunas restricciones adicionales para dar mayor tranquilidad.

Estos son unos criterios más o menos básicos y razonables. No son los únicos, por supuesto.

El Traje ha decidido que la máxima prioridad, lo que importa a la hora de evaluar cómo trabajamos en esta situación es… “aparentar ante el cliente que intentamos dar servicio con normalidad”. Así, por ejemplo, ha mandado a 26 personas a Torrejón a recoger cada una de ellas un portátil, por su cuenta y riesgo. Un portátil que sabe que de todos modos no nos permitirá trabajar desde casa porque no tenemos conexión a los sistemas desde allí. Pero eso es irrelevante. Es para que el cliente “vea que hacemos” o que, por lo menos, “vea que intentamos hacer como que hacemos”.

Creo que me queda ya poco que decir aquí.


Más gestión de crisis.

En un intento ingenuo de hacer algo productivo, se me ocurrió enviar un correo electrónico con una propuesta. Básicamente que mientras que no tenemos otras tareas, podemos “rellenar” el tiempo escribiendo una cierta documentación que hace mucha falta y que no tenemos.

Como no tengo ninguna autoridad para aprobar eso, envié el correo como una propuesta. Lo envié a las otras 3 personas “de front” y a 2 jefes: Karen, porque expresamente nos habían dicho que este tipo de cosas las habláramos con ella, y el otro traje, porque es el que ahora está más disponible. Intercambiamos los desarrolladores varios mensajes y detalles de la idea.

En el mensaje inicial puse en negrita que por favor los jefes dijeran si les parecía bien y si lo poníamos en marcha porque son quienes lo deben autorizar o desautorizar. Ninguna respuesta hasta dos días después. La respuesta: que en adelante incluyamos también al Traje en los correos. Nada más.

Pero es normal, no ha estado habiendo comunicación más que de forma muy puntual, ahora que estamos (no-)trabajando desde casa. De hecho… ¿qué comunicación hemos tenido? Que no olvidemos imputar las horas de este mes, que imputemos normalmente, que imputemos las horas, que el código para imputar las horas es este, que no olvidemos imputar las horas.

Edit: Crystal me dice que no me sorprenda. Y que no espere respuesta. Y que si incluyo al Traje en los mails tampoco espere respuesta suya.


No-gestión de la crisis…

Esto me lo cuenta Henry. Crystal nos decía que si acaso nos sorprendía la (no-)respuesta que estábamos teniendo. Henry dice…

¿Sorprendido? Me sorprendí por última vez el martes cuando le pedí a Karen que organizase los turnos para ir a la oficina y me contestó: “A ver, esto es un equipo Scrum; organizaros vosotros. ¡Ya tenéis que saber hacerlo!” y miró complacida a [el otro traje] que asintió con la cabeza. Después me miraron como si hubiera planteado una estupidez. Desde ese momento me van a sorprender ya pocas cosas.

No estaba allí delante pero no necesito ni cerrar los ojos para imaginarme la escena.


Hoy me ha tocado ir a recoger el portátil que no me sirve para trabajar por tantos motivos…

Son unos portátiles que ya han pasado su vida útil, que terminaron su tiempo de renting hace unos años y la empresa del renting ni siquiera quiso que se los devolvieran.

No lo conectes a la red - me dice Marcus, el departamento de sistemas. - Arrancas la máquina virtual y tampoco conectes esa a la red. Es que si no te va a dar problemas el Windows.

Es igual. No hay base de datos. No puedo ejecutar la aplicación. No sé qué pretenden que hagamos pero es como programar en un ordenador de cartón. Eso sí, como llevan el código, el precioso y preciado código15), llevan Bitlocker.

Me lo he traído a casa porque luego, en voz baja, Marcus me recuerda que todo esto es para aparentar, para que parezca que por lo menos intentamos algo.

Antes de volverme a casa, he hecho una foto al otro tablón de kanban, el del equipo de desarrollo, que usamos durante algo menos de un mes. También está empezando a perder trozos…

el otro tablón


(No-)Gestionando por Whatsapp…

Envía Karen un mensaje para que vaya otra tanda de desarrolladores a recoger sus portátiles. Dice:

Sois 7. Os repartís entre el lunes y martes a las 11:00, 12:00 y 13:00. Organizaos vosotros como os venga bien. Escalonados para que no coincidáis y dé tiempo a Marcus a prepararlo bien.

Empiezan a elegir turnos y… sí, obviamente falta un turno. 3 turnos x 2 días = 6 recogidas, no 7. Así que pregunta el que se ha quedado sin silla:

Oye, Karen, falta un hueco. ¿Qué hago, voy a las 10:00 o a las 14:00?

La respuesta de Karen es clara. Se limita a reenviar el mismo mensaje que había puesto antes. Karen es siempre tan útil y atenta…


Creo que estoy perdiendo un poco la paciencia. No contesto mal pero quizá un poquito afilado… Hoy hablando con el Arquitecto:

Te he pasado la aplicación esa. Cuando te venga bien te tendré que contar todo para que sepas cómo instalar todo y cómo arrancarla - me dice.
Ah, gracias. Pero no hace falta. Tiene un README.md y un INSTALL.md que explican todo eso. Los escribí yo.

Perfecto entonces. Si quieres arrancar la aplicación de back dímelo que te cuento cómo va esa parte, que ahí estarás más perdido.

La parte de back también tiene un README.md y un INSTALL.md. También los escribí yo.

No sólo los escribí yo. Es que él no escribe nunca documentación de ningún tipo porque no le interesa. Y además no sabe cómo hacerlo si no es desde dentro del Eclipse y por algún motivo desconocido metiendo la mierda del Lombok. Y cuidado que lo único que hay que hacer es un mvn spring-boot:run, no es que sea algo tremendamente complejo, eh.


Cada vez queda menos y menos


Algunas interacciones aquí son un poco especialitas.

Muchos usamos cascos para escuchar nuestra música y no la del tipo que la pone con altavoces “porque a él le gusta así”. Bueno pues esto pasa con frecuencia: Estoy con los cascos, mirando hacia mi pantalla, tecleando en mi teclado. De pronto alguien está hablando a un lado o incluso casi detrás, y resulta que me está hablando a mí. Me quito los cascos y me giro hacia él. Dice:

Ah, pensaba que me estabas escuchando.

¿Con los cascos? ¿Mientras claramente seguía con mi trabajo? No sé, es de lo más extraño.

En fin… Otros responden ante cualquier cosa con escándalo e indignación. Si tienen problemas para acceder al correo, dirán, casi gritando, “¡Estamos incomunicados!!”. Si alguien no ha hecho una cosa (probablemente porque ni sabía que tenía que hacerla) preguntarán: “Pero, ¿cómo es posible que esto no esté hecho?”. Y así con todo.

Creo que no hay nadie que hable normal.


Reunión con los dos trajes. La premisa básica es: tiene que haber cambios, y cambios profundos en muchas cosas variadas, para que yo continúe aquí. Durante casi tres horas les cuento todos los problemas que necesitan solución.

Su respuesta es, en el fondo, esperada: Ya sabían todas estas cosas. ¿Que el Arquitecto hace lo que le da la gana sin contar con nadie? Ya lo sabían. ¿Que el equipo no es un equipo? Ya lo sabían. ¿Que “lo de Agile” no está funcionando? Ya lo sabían. ¿Que Karen es más un impedimento que una ayuda? Ya lo sabían. Lo único que, aparentemente, no sabían es que la arquitectura de la aplicación está tan absolutamente mal. Pero tampoco pareció preocuparles demasiado.

Saben todos los problemas que hay. Llevan intentando hacer algo durante años. “Pero es muy difícil”. En varios momentos tengo que decir que yo no puedo hacerles su trabajo, porque es eso lo que parecen pretender. En otros dejan claro que no se puede cambiar nada, que no se pueden solucionar los problemas de raíz porque las raíces son intocables. Y con esas restricciones, su conclusión -o por lo menos la que me dicen- es que tengo que involucrarme más, particularmente con ellos y con el Arquitecto. Que lo que he conseguido con el equipo -que no es mucho, pero es algo- no les interesa demasiado. Quieren, en el fondo, que o bien haga magia de alguna forma, o bien yo sea el culpable de que no se consiga nada.

Es hora de ir recogiendo mis cosas.


Muchos de los problemas vienen de abajo, de los propios desarrolladores16).

Pero más allá de que haya quienes responden a los emails que dicen “Por favor no comáis pipas en el puesto de trabajo” sacando su bolsa de pipas y comiéndolas, si es que eso es posible, con más rabia e intensidad, el principal problema es que cada uno hace lo que le da la gana. Recuerdo, tras plantear seguir unas mínimas pautas comunes para organizar los JSPs todos igual, recibir la respuesta de “A mi me parece muy bien lo que dices pero yo voy a seguir haciéndolo como me apetezca”.

Hace ya unas cuantas semanas que decidimos aquello de escribir algo de documentación básica de desarrollo porque no teníamos nada y como una forma de aprovechar el tiempo con algo que podemos hacer los días que trabajamos desde casa.

El inicio tuvo sus pequeñas dificultades pero salimos adelante. La primera dificultad fue que no sabían cómo hacerlo. Ni qué escribir, ni cómo escribirlo. Así que me comprometí a tener lo antes posible una guía sobre qué escribir y cómo y una plantilla para hacerlo los tres igual. Lo escribí, lo compartí con ellos, y les expliqué que, como lo volcaríamos después al wiki, lo mejor era seguir dos pautas fundamentales:

  1. Escribirlo en texto plano. En un .txt sin más. Nada de Word, ni LibreOffice, ni nada. Simplemente texto y ya está.
  2. Usar poco formato. Marcar los títulos con la sintaxis de MediaWiki, negritas y cursivas, si había algo, y bloques de código y nada más.

Con estas dos ideas básicas, pasarlo luego al wiki sería muy sencillo. Habría que subir alguna imágen, quizá, pero poco más. Y siempre es más fácil añadirle luego algo de formato que tener que quitar el exceso. Todos de acuerdo con estas ideas y habiéndolas entendido, nos pusimos a rellenar las horas en que no teníamos otras tareas con esto.

Hoy, Jack me pregunta por el chat que cómo hace para pasar el documento que ha escrito al wiki.

Es que si lo copio y lo pego se pierde todo el formato.
¿Qué?

Sí. Y me había currado unos índices muy chulos y una portada.

Al final, no sin que además haya tenido que solucionarle varios problemas, ha terminado subiéndolo como un fichero ODT.

Seguramente se me pueda culpar de dejadez en este punto, pero sinceramente no he tenido ni siquiera ganas de preguntarle a Jack por qué mierdas dijo que sí, que lo entendía y que estaba de acuerdo y me pidió que escribiera esa plantilla y esa guía si después iba a hacer lo que le diera la gana.

Como recompensa, Jack ha dedicado todo su día de trabajo presencial a ignorar las tareas que no son de documentación. Me dice:

Te las dejo a ti para que lo hagas mañana. Así tienes algo que hacer.

Supongo, por las escasas cosas que se comentan, que Junio de 2009 estaba de lleno en la época de la migración, la re-ingeniería que se hizo para pasar de Natural a una aplicación web. El día 23 de ese mes, se incluyó el siguiente código en dos o tres JSPs17):

	function init() {
		
	}	 
	window.onload(init());	

Así, tal cual. Desde entonces, desde ese día 23 hasta ayer, este disparate ha estado en producción. Por supuesto produciendo un error (window.onload is not a function”). Un error que es solo el comienzo del disparate, porque obviamente init está vacía y no hace nada, y aunque no lo estuviera no se está configurando para ejecutarse en el evento onload sino que se la está llamando inmediatamente.

Pues así. Así ha estado durante 10 años, 10 meses y 15 días. Porque la migración se hizo muy rápido, claro. No es porque no tuvieran ni idea de lo que hacían. Ni porque no hayan tenido casi 11 años para arreglar nada. No, claramente es porque, como dicen los trajes, creemos que es la mejor forma de hacer las cosas.


Ms. Tery Person ha sido desde hace tiempo un pequeño entretenimiento.

Hace ya unos cuantos meses, noté que algunos emails del Arquitecto que enviaba a todo el equipo incluían a Tery. No le di importancia. No sabía quién era, pero no lo pensé más… Bueno, sí, de vez en cuando miraba a ver si estaba o no en la lista de receptores. Pero nada más.

Con el confinamiento y el trabajo remoto, empezamos a usar Teams y al crear el grupo el Arquitecto añadió a Tery como administradora del grupo. Entonces ya sí me llamó más la atención. Nunca me habían hablado de Tery. No es que no me la hubieran presentado, es que nadie la había nombrado nunca. Y coincidió además que quizá un mes antes o así, había aparecido otro nombre, otra persona que tampoco nadie había nombrado hasta ese momento y que resultaba ser mi directo responsable en algunos temas. Así que la aparición de Tery como administradora de Teams (un permiso reservado para los Trajes, Karen, el Arquitecto y Marcus -el departamento de sistemas-, además de la propia Tery), me empezó a intrigar un poco más.

Pregunté. Pregunté primero a uno de los Trajes.

Pues no sé. No me suena nada. No hay nadie en el equipo fuera de nosotros. Será un error. No te preocupes, no hay nadie oculto ni nada.

Uh… dejé pasar un tiempo y pregunté en el propio Teams. Nadie sabía. El Arquitecto optó por no contestar nada. Solo varios días después, en fin de semana, el Traje comentó que Tery era una experta en Teams que estaba ahí para ayudar en la administración de Teams. Pero lo dijo en fin de semana y la respuesta se perdió entre otros comentarios y el lunes no lo vi.

Hoy, un par de lunes después, aburrido, he optado por saludar a Tery directamente. Me ha parecido educado darle la bienvenida al equipo…

Hola, Ms. Tery Person. Bienvenida al proyecto X.
Hola, Flynn. Muchas gracias, aunque no sé muy bien por qué estoy metida en este grupo.

El siguiente fin de semana, el Traje quita a Tery del grupo discretamente.


Creo que será bueno contar lo de los literales en su propia página.


Cambiando el significado de las palabras… Jenny se queja de que parece que algunas personas aquí tienen más privilegios que otras. El Traje se lo explica.

Algunas personas están tele-trabajando porque son “de riesgo”. Podría pensarse que son mayores, o que tienen alguna enfermedad preexistente. Pero todo se entiende mejor cuando el Traje matiza “de riesgo para el proyecto”. Es decir, que no es que estén más en riesgo que otras, sino que se les considera más importantes. “Pero eso no significa que haya gente con más privilegios que otros”, dice.

No me meto en la conversación porque sé que no acabaría bien, pero todos sabemos perfectamente que el Arquitecto está en casa porque es el Arquitecto.

Jenny comenta que lo de hacer turno hasta las nueve de la noche le dificulta mucho cuidar de su hijo y que eso les pasa a varios. El Traje dice casualmente que eso “no es un riesgo para el cliente”. Mirando en el diccionario escum-español veo que la expresión significa más o menos “me importan una mierda tus problemas” o “¿tengo cara de que me importen a mi tus problemas?”, según la entonación.


Lo tiene que probar en tu máquina, claro. Hombre, es que piensa que ahora lo que se sube lo subimos directamente a producción.

Los entornos de pruebas son un mito. Están ahí, pero no están. Las cosas se prueban, sí es que se prueban, en el ordenador del programador. Y luego directamente a producción. “Hay que tener cuidado” - añade; pero sospecho que no tiene del todo claro qué significa tener cuidado.


El tablón de desarrollo, ese que usamos casi un mes entero, ha muerto

El tablón de desarrollo ha muerto hoy… Bueno, no. El tablón lleva muerto desde hace meses. Lo usamos alrededor de un mes y luego ahí se quedó, como recordatorio de un futuro que no podría haber sido y que efectivamente no fue, como retrato de una batalla muy poco violenta entre la ilusión de la organización y la dejadez que venció porque la ilusión solo era eso, una ilusión.

Poco a poco, ha ido perdiendo ese encanto que nunca llegó a tener. Primero con el abandono general, luego con la burla de pegarle post-its con cosas como “Un jamón”, “Futbolín” o “Queremos pizarras”, finalmente con el olvido. Había pasado ya a ser una más de las presencias ignoradas del proyecto. Algo que está ahí pero nadie mira para no tener que reconocer la realidad. Y hoy lunes, finalmente ha amanecido con el tablón arrugado, casi despegado por completo, colgando solo de unas pocas tiras adhesivas que se negaban a soltarse aún.

Luego, a media mañana, como pensando que con esa pinta se hacía más difícil ignorar su decadencia, el otro Traje ha cogido un poco de celo y lo ha vuelto a pegar. No tanto como para que esté bien pero sí suficiente como para que parezca que no ha pasado nada, que seguimos con el mismo nivel de abandono y dejadez que antes, pero sin esta llamada de atención. Por favor, disimulen. Disculpen las molestias… Aquí no ha pasado nada.

Aguantará así quizá otro par de meses. Quizá cuando llegue ese momento alguien se decida a retirarlo del todo y dejarle morir más dignamente. Quizá.


Hubo finalmente una entrega. En medio de todo esto se decidió que no se retrasaba. La fecha es la fecha. La fecha está puesta desde hace meses, años. La fecha se respeta. Se hizo la entrega.

Dos semanas después, una funcionalidad nueva. Se decide que se hace deprisa y corriendo en dos días y que se sube como si fuera un parche de la versión que se entregó. Porque la fecha, en realidad, no se respeta. La fecha es un chiste y si se quiere mucho subir algo, pues se sube.

El otro Traje le cuenta qué hay que hacer en esta nueva funcionalidad a Karen. Se lo cuenta de palabra, claro, porque nada de todo esto quedará escrito en ningún sitio. “La fecha que activo retrasadamente debe ser mayor que el día, pero menor que hoy… de la propia fecha de activación del día, no sé si me entiendes” - dice. Las especificaciones de las tareas son un teléfono escacharrado. Seguro, seguro, que no se han entendido en todos los detalles. Pero da igual porque la definición de tareas es otro chiste.

“Ya luego lo pruebo yo” - dice Karen. Porque no se probará en el entorno de pruebas, sino en su máquina. Porque las pruebas son el siguiente chiste y los entornos de pruebas otro más.

Y ante todo esto recuerdo que el Traje me decía muy convencido que se hacen así las cosas porque “pensamos que es la mejor forma”.


No puedo conectar. No sé por qué.
¿Por qué?

No sé.


Llevo algunos días pensando en esto de las “personas de riesgo para el proyecto”.

Antes de la reunión con los Trajes, esa en que me dijeron básicamente que ya sabían todos los problemas que había muchas gracias pero que es lo que hay, tuve una breve conversación con uno de ellos que fue la que me llevó a tener esa reunión. Esta conversación fue antes de que empezara “todo esto”, hace meses.

En realidad no fue más que acercarme al segundo Traje y decirle que tendríamos que hablar, que las cosas no iban bien, que no veía un futuro razonable. Según le decía esas cosas, no recuerdo muy bien por qué, comenté lo que era el “factor bus”. Creo que fue para resaltar los problemas que había con el Arquitecto. El caso es que lo comenté y no sólo señalé al Arquitecto como un “factor bus 1”, sino también a otra persona, que es la única que trabaja y conoce una parte de la aplicación que es… ese tipo de funcionalidad chula y moderna que sacan en la televisión cuando hacer un reportaje sobre el sistema y tienen que sacar algo chulo y llamativo.

Lo curioso del asunto es que pocos días después fue cuando decidieron que ciertas personas serían consideradas “de riesgo” y se quedarían en sus casas. 4 personas. Casualmente esas dos entre ellas.

No quiero pensar que los Trajes no se hubieran dado cuenta por sí mismos de todos modos. Tampoco creo que hubiera evitado comentar eso si hubiera sabido lo que pasaría. Lo que me preocupa es la facilidad para pervertir un concepto y tomar una decisión como “bueno, pues a estos cuatro merece la pena protegerles” mientras al resto nos exigían seguir trabajando presencialmente, mayormente por mantener la apariencia.

Meh…


Esto se escribe solo.

Unas líneas más arriba contaba el teléfono escacharrado que era la transmisión oral de requerimientos de una tarea. “La fecha que activo retrasadamente debe ser mayor que el día, pero menor que hoy… de la propia fecha de activación del día, no sé si me entiendes”

Hoy, solo tres días después, los mismos protagonistas hablan de nuevo. El tema de las fechas está mal. Sorprendente.


Hace tres meses Stephan abre una incidencia a Martin para que cambie un detalle solo de estilo de un componente.

Hay dos variantes18), una es editable y la otra no. Hace tres meses, Martin en lugar de cambiar el detalle de estilo, hace que la variante no editable sea, repentinamente, editable. Tan alegre, sube el código y da por resuelta la tarea. Luego, Stephan la prueba y la da por correcta y válida.

Hoy, vienen Stephan y Martin y me preguntan si he cambiado alguna cosa del componente porque repentinamente se ha vuelto editable la versión que no debería serlo. Miro los logs del Subversion y miro la tarea a la que indican estos. Se los enseño, ambas cosas. Al que lo ha hecho, Martin, y al que lo ha probado, Stephan, que ni saben lo que hacen ni se acuerdan de ello, pero inmediatamente vienen a preguntarme si yo lo he cambiado.


Ya conté cómo gestionan aquí el flujo de trabajo con Subversion.

Hoy se me acerca Rachel, que se encarga de gestionar el Subversion con Marcus el departamento de sistemas. Están haciendo un merge llevando los cambios de la rama principal a la rama de desarrollo y tiene un conflicto en un fichero y tal y cual. En fin, tonterías sin mayor importancia.

Pero ya que estamos hablando y que están ellos ahí haciendo estas cosas, se me ocurre preguntar. En este ciclo, una buena parte del desarrollo no se está haciendo en la rama “Desarrollo” sino en una rama de una funcionalidad concreta, digamos la rama “Lotes” -porque trata de lotes-. Ha habido varios rumores sobre esto. Cada persona y cada semana me daba una versión distinta. Unas veces la rama Lotes se volvería a juntar con Desarrollo mucho antes, meses antes del final del ciclo19). Otras Lotes se abandonaba por completo. Otras la que se abandonaba era Desarrollo. Todo esto se mezclaba con el uso de identificadores para las versiones que también iban cambiando.

La versión en producción es, digamos, la 3.3.6. Al principio la 3.3.6 iba a llamarse 3.4.0 porque había cambios importantes… pero no los hubo al final, así que 3.3.6. La siguiente versión sí que sería 3.4.0… o casi. Porque esa funcionalidad importante, Lotes, se empezó a llamar como 3.4.1, mientras se planteaba hacer una 3.4.0 sin ese cambio. Pero luego, se empezó a decir que la 3.4.0 nunca existiría porque subiría Lotes a.k.a. 3.4.1 antes y obviamente no tenía sentido subir 3.4.1 antes que 3.4.0 así que se saltaban 3.4.0. Pero luego cambiaban de opinión y sí que subiría una 3.4.0 antes que lotes/3.4.1.

En fin, harto de rumores y confusión, les pregunto a Rachel y Marcus. Y sí, Lotes/3.4.1 será la entrega de este ciclo. “Se convertirá en la rama de Desarrollo” - dicen ellos con sus confusos tejemanejes. Y la rama de Desarrollo, ¿qué pasará con ella? Más que nada porque llevo ya cinco o seis cambios en los últimos días que han ido a esa rama porque así lo han pedido.

Pues no se sabe. Probablemente no desaparezcan. Probablemente -si nadie cambia de opinión- subirán en el siguiente ciclo… el año que viene.


 El tablón ha muerto otra vez.

El arreglo del tablón de desarrollo ha durado dos semanas.

Esta vez parece que se va a quedar así. Porque, siendo sinceros, qué más da. De verdad, a nadie le importa el tablón. Ni siquiera como símbolo de nada ya. Nadie le presta atención ni en un sentido ni en otro. No hay conversaciones de “fíjate, se ha caído”, ni de “da igual, no lo usábamos”. Nada en absoluto.

Y lo entiendo, eh. Es solo una decoración tan inútil como el perchero que tiene a la derecha, un calendario que hay en una esquina de la sala, o los puntos de acceso wifi que instalaron a final del año pasado y a los que nada se ha conectado nunca porque no están configurados.


Hoy, por casualidad, han coincidido los dos Trajes en el mismo turno.

Esta coincidencia trájica20) se ha situado frente al tablón colgante. Dos trajes contra un tablón. El pobre no tenía posibilidades. Entre los dos lo han vuelto a pegar y reconstruir. Lo han alisado y le han añadido más cinta adhesiva, para que se mantenga en su sitio y se comporte como es debido.

Como digo, el tablón ha opuesto poca resistencia. En un par de minutos estaba de nuevo colgado y arreglado…

…pero… …30 minutos después, el tablón, insolente y rebelde, desesperado o suicida, ha vuelto a descolgarse.

La mascarilla tapa mi sonrisa.


Creo que una de las cosas que más me llama la atención del proyecto es la absurda y ridícula consideración que se tiene del tiempo.

Por un lado, se obliga a los desarrolladores y analistas a ficher múltiples veces y a imputar tiempos a tareas teniendo que cuadrar estos tiempos con precisión de minutos en un mes. Vamos, que no puede haber un descuadre de más de un minuto o dos en los tiempos registrados cada mes.

Esto, en sí mismo, es algo que podría, haciendo algo de esfuerzo, llegar a aceptar. Personalmente no creo que sea posible registrar los tiempos con esa precisión, particularmente en un entorno en el que muchas tareas ni siquiera están definidas. Al final lo que ocurre es que todo el mundo rellena tareas. Es decir, los tiempos cuadran pero no son reales en absoluto. Si asumimos esa mentira, bueno, es algo que por lo menos se puede hacer.

El problema es que mientras se exige esta precisión para justificar la dedicación y ocupación, por otro lado ocurren cosas que literalmente impiden que se trabaje. Es habitual, como ya he contado, que el repositorio pase un par de días cerrado cada semana21). Esto, que entorpece enormemente el flujo de trabajo, se considera que es “la mejor forma”. También, de vez en cuando, el Arquitecto bloqueaba el repositorio porque sí, porque el proyecto es suyo y él hace con él lo que le da la gana.

Esta semana, por algún problema indeterminado con una carga de datos en algunos entornos, simplemente no hemos tenido base de datos durante dos días. Y por lo visto, al recuperarla se han perdido muchos datos de prueba que habrá que volver a cargar22).

Entiendo que puede haber problemas, que pueden requerir en ciertos momentos algunos bloqueos, pero es esa actitud de asumir como “la mejor forma” algo que hace perder jornadas enteras de desarrollo, lo que no termino de entender. Y no es solo esto, a veces hay semanas enteras en que algunos desarrolladores tienen que inventarse los tiempos por completo porque nadie les ha dado ninguna tarea porque no hay nadie que planifique nada. No son solo los tablones muertos que cuelgan de las paredes, es que no hay nadie que haga ninguna planificación. No hay comunicación ni organización ni se sabe nunca cuando habrá que trabajar.


Por otra parte, no todos los males vienen de arriba, obviamente. Ni de fuera. Últimamente estoy empezando a notar que pierdo la paciencia.

Pierdo la paciencia con Montgomery. Monty, que se supone23) que es senior software engineer, no solo pregunta las cosas más básicas, sino que luego necesita múltiples explicaciones, porque cree que lo ha pillado, pero luego resulta que no. Montgomery no solo ignora los consejos sino que alegremente llama “lo que a ti te gusta” a cualquier argumento que le pueda dar.

Ha pasado unos 3 días poniendo una imagen en una página. Me dijo que, ya que tenía que poner la imagen, quería limpiar la página porque era un follón. Y lo era, sí. Poner la imagen llega aproximadamente 10 minutos, pero me pareció bien lo de limpiar esa página. Además Montgomery no sabe CSS pero quiere aprender, así que era una buena manera de hacer ejercicio. Pensé que sería bueno darle algunas indicaciones y le hice una lista de 5 o 6 puntos o pautas a seguir. Cosas que había que eliminar y formas de hacer las cosas bien para no volver a liarlo. Como otras veces que le digo algo así, la idea es que primero limpie y luego sitúe la imagen donde debe ir. Como otras veces que le he dicho algo así, Monty ha ignorado esto. Primero ha metido la imagen, ha pasado 3 días intentando conseguir ponerla donde debía ir, y luego se ha dado cuenta de que si se ponía a limpiar la página ahora, tendría que volver a colocar bien la imagen, que llevaba ya 3 días con eso y que ya no tenía ganas de rehacer el trabajo. Así que ha subido lo que tenía y todas esas ganas de limpiar la página, de aprender, de dejarlo bien, nos olvidamos de ellas. Me siento culpable, pero no creo que siga ayudándole.

También pierdo la paciencia con otros temas. Las interrupciones injustificadas. Estaba hablando con Montgomery. Explicándole que lo que había hecho para situar la imagen donde debía ir era añadir más follón a la página y que solo necesitaba 4 propiedades de CSS en un elemento. He tenido que explicarlo varias veces porque él no es mucho de prestar atención cuando parece que presta atención. Y según lo estoy repitiendo una vez más porque de nuevo se había distraído la vez anterior, pasa Johnny.

Eh, Monty! - le dice
Monty! Que salimos a tomar un café! - insiste Johnny y le hace gesto de que salga en cuanto pueda.

Obviamente se ha distraído otra vez. Y yo he perdido la paciencia y le he dicho a Johnny que se vaya a la mierda con su café.

En fin, tengo que trabajar eso de la paciencia un poco más. Por otro lado… Sí, empiezo a pensar que también tengo que dejar de ayudar a quien no lo aprecia.


Hoy ha pasado algo…

 El final del tablón

¡Ya no hay tablón! ¡Aleluya!


Hay una cosa que me encuentro pensando cada poco tiempo en este proyecto.

El otro día tuve una reunión de un tema irrelevante, pero como introducción, el Traje pasó cinco minutos largos justificando la arquitectura actual del proyecto. No es la primera vez que insiste en ello, especialmente si estoy yo delante. El Arquitecto ya ha dejado claro numerosas veces que cree con convencimiento que está muy bien, y -obviamente- más la parte en la que él ha trabajado más24). En conversaciones con otros miembros del equipo, también apoyan que está bastante bien.

Es decir, todos están muy convencidos de que, a gran escala, la aplicación está bien construida.

Para explicar un poco cómo está construida la aplicación, diré: El 90% de la lógica está metido en una ingente cantidad de procesos almacenados en la BBDD. No se hace ningún accesso a la BBDD a través de querys, todo son procesos almacenados. Luego hay una aplicación Java, con Spring y Struts, en la que no hay apenas lógica. Salvo en algún caso muy concreto, lo único que proporciona es una cierta gestión de permisos. La aplicación es básicamente un tubo entre las peticiones que se lanzan desde JavaScript hasta los DAOs que acceden a la base de datos. Tanto es así, que hasta los nombres de los datos en el JS/HTML están ligados a los nombres de las columnas en BBDD.

Pues bien, alguna vez queriendo ser comprensivo y generoso he intentado asumir que todo esto era porque así conseguían un buen rendimiento. Es más, uno de los argumentos que comentaba el Traje en esa justificación daba a entender que eso era lo que habían conseguido y a lo que habían apuntado.

El problema es que… bueno, el rendimiento es muy malo. La mayoría de las peticiones están limitadas a 500 resultados porque si no el sistema no aguanta. Incluso así, una búsqueda más o menos normal, que devuelva un listado con digamos 200 resultados, es fácil que lleve un par de minutos. Más aún, hay búsquedas que llegan a tardar cuatro o cinco veces eso. Algunos resultados se cachean (en BBDD) pero la mayoría no, teniendo que realizar la búsqueda de nuevo cuando refrescas un listado por el motivo que sea.

Un motivo para refrescar listados es, por ejemplo, que has intentado hacer una operación sobre uno de los resultados pero no está permitido25). Es decir: Haces una búsqueda; esperas un minuto. Eliges uno de los resultados e intentas hacer una operación. Se envía la petición que necesita llegar hasta BBDD porque es donde está la lógica, se comprueba que no se puede, se devuelve el error/mensaje. Esto tarda relativamente poco, pero… como se hace con una petición completa a través de Struts que termina redirigiendo a la página en la que estabas, tienes que volver a esperar ese minuto entero para que se vuelvan a traer todos los resultados de nuevo. Y esto en mi estación de trabajo que está a unos diez o quince metros del servidor. No quiero ni imaginarme lo que debe ser en un taller de un cuartel con una conexión no-terriblemente-buena. Y mientras esperas, por si acaso, para que no hagas nada, bloquean las pantallas.

Y lo malo, lo realmente malo, es que están todos ya tan acostumbrados que realmente creen que todo está bastante bien. En fin…


Somos un equipo Agile, Agile con A mayúscula, Agile 100%, Agile pero adaptado a nuestras necesidades como debe ser. Hacemos Agile. Agile del bueno. ¡Qué gran cosa Agile!

Mañana se cierra el Sprint 2. De los 213 JIRAs planificados para el Sprint 2, hay 187 sin terminar, que pasarán al Sprint 3. En el Sprint 3 ya hay unos 40 JIRAs no asignados, que automáticamente pasarán al Sprint 4 mañana.

Esto es lo que ocurre cada tres semanas, con cada nuevo sprint26). No hay, obviamente, ningún tipo de planificación de los sprints. Tampoco hay ningún tipo de revisión al cierre de un sprint. Este mensaje es lo único que marca, de algún modo, un sprint.

Los sprints están agrupados en dos ciclos de entregas anuales. Eso supone que hay aproximadamente unos 8 o 9 sprints por ciclo. No se hace tampoco ninguna planificación con el equipo al principio de uno de estos ciclos. De hecho, el principio de un ciclo queda difuminado por dos detalles: antes de que empiece ya hay gente del equipo trabajando en la siguiente versión; y, después de que temrine sigue habiendo gente trabajando en la versión anterior. Yo mismo he hecho tareas27) de una versión anterior unos 3 meses después de la fecha de entrega de esa versión, y he hecho tareas que estaban planificadas pero no se entregarán hasta dentro de casi un año.

Si no hay nada de esa planificación, ¿cómo ocurren las cosas? Bueno, ocurren porque como equipo Agile no somos ni Agile ni equipo. Cada analista hace su planificación como quiere. Que generalmente significa que no hace planificación en absoluto sino que va directamente al desarrollador con el que suele trabajar o que le cae bien o lo que sea y le dice que le va a pasar algunas tareas y que ya las irán viendo.

No hemos llegado a esto de forma explícita, ojo. Lo oficial, lo último que se estableció aunque nadie lo haga es que por supuesto que existen todas las planificaciones. Se planifica cada sprint con los desarolladores “auto-asignándose” una cantidad dde tareas que ocupe su tiempo, oficialmente. Esto es que no empezó muy bien, porque ya desde el principio se usaban las palabras un poco mal, diciendo cosas como “Stephany, auto-asígnate esta tarea y esta otra. Louis, auto-asígnate estas otras”. Tampoco empezó bien porque la estimación de cuánta tarea coger se basaba en unas estimaciones que no se hacían. No se hacían estimaciones no por una cuestión de estúpidos principios Agiles ni mucho menos, sino porque los analistas acudían a que los desarrolladores hicieran estimaciones antes de saber en qué consistía la tarea, y entonces -obviamente- los desarrolladores no estimaban. Además, las tareas, por supuesto, no están desglosadas en pequeños trozos sino que generalmente son tareas que engloban desarrollos completos de varias semanas… generalmente de más de un sprint.

JIRA tiene todo un sistema de seguimiento de tiempos, de estimaciones, de tiempos restantes, etc. Pero por motivos desconocidos se decidió que no era suficiente y que, entonces, se añadían unos campos personalizados que los analistas y desarrolladores debían usar para gestionar ellos a mano el progreso de las tareas y sus tiempos. Cada mes, los Trajes generan28) unos informes que pasan hacia arriba dentro de la empresa y al cliente.

Una vez, por despiste y costumbre, puse la estimación de tiempos usando la funcionalidad de JIRA. Al día siguiente estaba recibiendo una reprimenda. No puedo evitar pensar que hay malicia detrás de todo esto. Que inicialmente podía ser desconocimiento, ignorancia o falta de experiencia, quizá, pero que claramente, con el tiempo ha terminado siendo algo intencionado lo de ocultar el progreso. Los tiempos computados, los imputados, los asignados, el progreso de las tareas, la dedicación de cada miembro del equipo a cada tarea… nada de eso es real. Todo es inven^H^H^H^H^Hajustado para que cuadre en los informes con lo que se quiere presentar como progreso.

Eso sí, hay algo en lo que sí somos Agiles, muy Agiles. Cada vez que surge cualquier situación en la que hay que ejercer algo de responsabilidad o tomar alguna decisión no-técnica, quien debería hacerlo se lava las manos y dice aquello de “Organizáoslo vosotros, que para algo sois un equipo Agile”.


Hoy era la última subida de esta versión.

A mi me da un poco igual, la verdad, pero creo que si hay unos compromisos de dos versiones anuales, con unas fechas cerradas, pues esas cosas se deberían respetar. Pero no. La última subida será dentro de dos días porque… ya que estamos, vamos a meter un par de cositas más, cositas pequeñas.

Lo que no parecen entender es que “cositas pequeñas” hay todas las que quieras y podríamos estar metiendo cositas pequeñas hasta el año que viene. Y si haces eso, entonces no hay una fecha de entrega de una versión, lo que hay es meter parches continuamente. Porque, claro, se podría pensar que esto no está mal, que podría ser una especie de “entrega continua” con subidas constantes a producción y eso podría tener sus ventajas. Pero no, tampoco es eso porque la fecha sigue estando ahí. Todo esto que se hace de subir parches se hace deprisa y corriendo en las semanas alrededor de la fecha de entrega.

Desde unas semanas antes hasta mes y medio o dos después, todo es “ya que estamos, si da tiempo a hacer esto aunque sea así deprisa, pues lo metemos”.

En fin, no hay planificación alguna. No sé por qué me sorprendo aún.


Monty me pregunta. No sabe preguntar, pero bueno, intenta mejorar en eso. Lo que pasa es que me pregunta algo que no se puede hacer. Es comunmente sabido que no se pueden cambiar varios de los estilos de un elemento <select>, pero eso es justo lo que quiere hacer. Monty es, según su perfil, “desarrollador senior”, aunque pregunta cosas mucho más básicas que esto, como usar un bucle o cosas así.

Le digo que lo del <select> no se puede, que es un tema conocido y no se puede cambiar a no ser que dejes de usar el elemento <select> nativo y te construyas uno tú. Que es una opción porque tenemos también de esos en la aplicación. Pero este es un <select> y Monty quiere cambiarlo pero seguir usando un <select> nativo. Insisto: No es posible. Y sin poder hacer nada, lo dejamos ahí.

Los tres días siguientes Monty los pasa intentando hacer lo que no se puede hacer. Al cabo de esos días le veo que lo está intentando y le pregunto por qué sigue aún con eso. Lo habló con el Arquitecto y este, como no sabía que no se puede hacer, le dijo que lo intentara. Y como Monty no se fía de lo que yo diga, pues tres días perdidos.

Y como no se fía, le paso un trozo de texto sacado de MDN. Y como aún no se fía, sigue intentándolo un día más. Al final, desiste. Y me dice que va a cerrar la incidencia y que si le paso el enlace de MDN para ponerlo.

Yo ya he llegado a mi límite, lo confieso, y le digo que creo que debería ser capaz de buscar una página en MDN. Oh, sí, la buscaré. - dice. Al rato, veo la incidencia cerrada y veo que no ha puesto el enlace. No sé si no lo ha encontrado o si ni siquiera lo ha buscado, pero me da igual.

1)
ahemm
2)
“No como en JavaScript que no tiene tipos” – El Arquitecto
3)
ooooh, aaaah, qué poderío
4)
entre muchas comillas
5)
o más
6)
por no llamarlo código
7)
quizá la única parte de mi trabajo que tiene algo de sentido
8)
Porque por algún muy excelente motivo desconocido, los ficheros de configuración no están bajo control de versiones y se tocan a mano en vivo en el servidor
9)
y que seguramente sea el último porque uno tiene sus limitaciones
10)
en teoría; en la práctica sí porque la seguridad es teatro y ya me dijo Marcus, el departamento de sistemas, que todo está accesible
11)
de Natural a Java
12)
que dado el tono con el que me lo decía se entendía que significaba que “por lo menos no recurren a la violencia”
13)
cuánto no lo sé, pero por lo que intuí más de una y de dos veces
14)
o no probarlo, porque las cosas de PL/SQL las hacen muchas veces “en vivo” o casi
15)
que, siendo sinceros, no vale nada
16)
que sinceramente muchos ni parecen serlo
17)
Y no es por señalar a nadie en particular, pero el commit es de Karen m(
18)
hay casi 50 variantes que me tocó catalogar porque nadie se había molestado en hacerlo en 10 años, pero esa es otra historia para otro día
19)
quedan ahora unos 5 meses y pico
20)
y sí, también un poco trágica
21)
a veces más
22)
y que como eso es algo que hacen los analistas a mano, pues supondrá una buena cantidad de horas más perdidas
23)
porque así lo dice su perfil en la web de la empresa y así lo dice también su perfil de LinkedIn
24)
aunque qué parte es esa es algo que cambia según le conviene
25)
por su estado, por permisos o por lo que sea
26)
Los números son reales, sacados del último mensaje de estos, el de ayer. Y suelen ser números parecidos a estos, sí. La mayoría de las cosas se van arrastrando y he visto tareas que se llevan arrastrando más de dos años sin que nadie se plantee ni hacerlas ni eliminarlas
27)
y digo tareas, no corrección de errores
28)
no ellos personalmente; eso sería mucho trabajo