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.)

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…

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