Tinselcity

¡Esta es una revisión vieja del documento!


El Alemán

Un día estaba hablando con Fortress. Yo llevaba algún tiempo buscando una forma limpia de poner un poco de orden en el uso de columnas “custom” en el componente de listados que teníamos. Más que nada porque hacer una columna con un contenido “especial” suponía -en aquel momento- repetir un montón de código innecesariamente y encima tocar en tres o cuatro ficheros que a. ya eran bastante enormes y b. eran comunes a toda la aplicación.

Lo curioso es que casi todos los tipos de columna nuevos que habían creado eran… básicamente lo mismo. Cambiando un literal aquí o un número allá. Pero por lo demás casi idénticos. Yo no sólo quería hacer algo más limpio y sencillo que evitara un trabajo innecesario sino que intentaba también comprender cómo y por qué se había llegado hasta la situación actual. Hay un Arquitecto, ¿no? ¿No os ayuda Anfang con este tipo de cosas? Es un tema que afecta a un componente base fundamental en toda la aplicación…

El problema es que… Mira, a Anfang la mayoría de las veces le llamamos El Alemán. Habla y habla, pero no se le entiende nada.

No sería la única vez que alguien del equipo me daría esta explicación. Era muy evidente que Anfang no comunicaba con el equipo y no necesitaba que nadie me lo dijera para verlo. Bastaba hablar con él cinco minutos. No era este el único problema que tenía.

El proyecto es mío

Un mal relativamente frecuente entre cierto tipo de desarrollador es el de creer -y actuar según esa creencia- que el proyecto es suyo. Tienden a apropiárselo de diferentes modos, aunque principalmente a nivel técnico. Anfang era de estos.

De hecho, Anfang asumía con total naturalidad que el proyecto era suyo y que el resto solo estaba ahí para hacer lo que a él no le apetecía. Pero además es que el resto lo asumía de la misma forma. No sólo esos que declaraban abiertamente que no se le entendía nada, sino también los que, aunque tampoco le entendían, no lo declaraban. Los propios gestores del proyecto también. Ni le entendían, ni hacían nada en absoluto por enfrentarse lo más mínimo a los caprichos de Anfang. “Hemos intentado alguna vez que delegue, pero no lo hemos conseguido” - decían.

Esta apropiación llegaba a extremos como bloquear el repositorio de código durante varios días porque tenía que hacer unas cosas; así, sin más explicación. También actualizaba versiones de herramientas sin decir nada. O se guardaba en su propio ordenador otras herramientas para que sólo él tuviera acceso a ellas, o simplemente para que solo él supiera qué herramientas eran.

Este afán de secretismo técnico lo había extendido un poco hacia los gestores. A veces les pillaba discutiendo algún próximo cambio o algún futuro objetivo o lo que fuera y les oía decir cosas como “De esto no les digáis nada al equipo” o “Ya les iremos dando información a los que la necesiten y según la vayan necesitando… pero lo mínimo, eh”. Reconozco que, en parte, esto se debía a que en el equipo había más de uno y de dos muy dispuestos a llevar la contraria en todo. Pero el motivo principal era, sin duda, mantener un control estricto sobre el proyecto.

Experiencia y conocimiento

De Anfang escuché, en general, dos descripciones. Por un lado, algunos le describían como un genio, un portento, una eminencia. Otras descripciones, sin embargo, tenían cierta diferencia sutil: “Debe de saber un montón, seguro”.

Según pude comprobar personalmente, la realidad era bastante distinta.

Anfang, por encima de otras consideraciones, era bastante mediocre a nivel técnico. Pero escondía esto detrás de su hablar en alemán y, por supuesto, del estatus conseguido. Se imponía en cualquier decisión empezando a soltar “palabras complejas” sin demasiada relación con el tema y generalmente inconexas. Cuando esto no era suficiente, entonces simplemente posponía la discusión y luego aprovechaba para aplicar su decisión de forma preventiva antes de que volviera a surgir el tema.

Su conocimiento técnico real era absolutamente decepcionante para alguien en la posición que ocupaba. Después de un par de discusiones con él en las que él mismo se acabó dejando sin ningún argumento real, empezó a evitar hablar conmigo de ningún asunto más.

En una de esas discusiones, Anfang había intentado escribir un diálogo de confirmación. Más o menos. Realmente se trataba de sustituir rápidamente media docena de usos del confirm nativo del navegador por un Dialog de jQueryUI. El cambio que quería hacerse en las llamadas a confirm inevitablemente iba a pasar de ser una llamada síncrona a una asíncrona. Esto era inevitable y de hecho era, en parte, el objetivo. Su código, ligeramente resumido, era algo así:

/**
 * Presenta un dialogo de confirmación y dependiendo de la respuesta del usuario, se llamara
 * a la funcion okCallback o a la cancelCallback
 * @param {*} msg Mensaje a mostrar en el diálogo
 * @param {*} okCallback función a ejecutar cuando el usuario pulsa en aceptar
 * @param {*} cancelCallback  función a ejecutar cuando el usuario cancela el diálogo
 */
function confirmCallback(msg, okCallback, cancelCallback) {
    $.when( confirmDfD(msg) ).then(function(confirm) {
        if(confirm){
            typeof okCallback === 'function' && okCallback();
        } else {
            typeof cancelCallback === 'function' && cancelCallback();
        }
    });
}
/**
 * Muestra un dialogo de confirmación al usuario y devuelve una promesa que resuelve a true o false
 * dependiendo de si el usuario acepto o cancelo el diálogo
 * @param {*} msg
 * @return $.Deferred con resolve a true si acepto el diálogo o a false si lo canceló 
 */
function confirmDfD(msg) {
    var dfd = new jQuery.Deferred();
    var divMsg = "<div style='display:none'>" + msg + "</div>";
    $(divMsg).dialog({
        // ...
        buttons: {
            "Aceptar": function () {
                $(this).dialog("close");
                dfd.resolve(true);
            },
            "Cancelar": function () {
                $(this).dialog("close");
                dfd.resolve(false);
            }
        }
    });
    return dfd.promise();
}

Anfang había descubierto las promesas gracias a jQuery. Y nunca había salido de ahí. Su conocimiento de estas era, siendo objetivo, básico.

Tras escribir ese código me llamó para enseñármelo con cierto orgullo. “He usado Promesas, no sé si conocerás lo que son…” y me explicó que confirmDfD sería una función interna y que la que se llamaría externamente sería confirmCallback. Le pregunté qué necesidad había de escribir dos funciones distintas y de pasar una promesa de una a otra. “Es por la asíncronía.” Asentí, pero insistí: “No necesitas tener dos funciones y no hace falta crear la promesa interna.” De nuevo su respuesta: “Es porque es asíncrono.”

No quise insistir demasiado pero lo intenté una vez más:

Dialog ya es asíncrono y ya te permite pasarle directamente los dos callbacks de ok y de cancel. Simplemente usando Dialog ya podrías hacer algo así…

function confirmCallback(msg, okCallback, cancelCallback) {
    $("<div>"+msg+"</div>").dialog({
        // ...
        buttons: {
            "Aceptar": okCallback,
            "Cancelar": cancelCallback
        }
    });
}

…y de cara a la llamada seguiría funcionando todo igual.

Mientras miraba la pantalla, se le volvió a escapar un “Pero la asincronía…”. Muy probablemente estaba pensando que yo no tenía ni idea y que no había entendido lo que él decía, pero algo le hacía sospechar que era él el que no sabía lo que decía y que tenía que buscar una salida. Me dijo, como buscando tranquilizarme, que “bueno, en realidad se trata de hacer lo que sea mejor, por supuesto”. Luego, con un “Le daré una pensada más”, dio por terminada la conversación para que me fuera.

Antes de que pasaran 30 segundos, Anfang ya había subido el código, su código, al repositorio, se había levantado y había ido a contar a quien le tocaba cambiar los usos del confirm nativo por su ridícula función que había sido “muy complicado; he tenido que usar una Promesa por el tema de la asincronía, claro”.

Conclusiones

No escribo todo esto simplemente para entretenerme señalando a alguien. La idea es aprender a tratar con este tipo de personas, porque si no terminan arruinando completamente el proyecto.

Evidentemente si tenemos la autoridad suficiente -es decir, si estamos en ese puesto de dirección del proyecto- la acción a tomar es clara: Debemos tener el valor de eliminar por completo esta actitud de raíz, antes de que llegue a ser un problema. La forma más clara es evitar dejar toda la autoridad técnica en manos de una sola persona. También ayuda, evidentemente, seleccionar a personas que no tengan aires de héroes que se echan todo el proyecto a los hombros pretendiendo que se están sacrificando cuando lo que hacen es imponer únicamente su propio beneficio. No siempre es posible prevenirlo y no siempre tenemos la percepción adecuada o la autoridad para elegir a los miembros del proyecto, así que a veces nos encontraremos que el problema, inevitablemente, está ahí. La solución puede parecer dramática pero lo único que funciona es quitar a esa persona de forma explícita cualquier autoridad. He visto en más de una ocasión cómo algunos intentan introducir a otra persona que, mágicamente, le “destrone”, pero en ninguna de las ocasiones esto ha tenido éxito. Mientras siga teniendo la autoridad técnica es prácticamente imposible que se pueda solucionar nada.

¿Y si no tenemos esa opción? Y si, por ejemplo, ¿no somos más que otro miembro del equipo técnico por debajo de este arquitecto? Tenemos muy pocas opciones entonces. Obviamente asumir la derrota, ponerle un mote y seguir sufriendo como si nada, es una opción, pero no va a mejorar nunca la situación. Algo que puede tener cierto éxito es construir una realidad -técnica- paralela en el proyecto. Ir insertando mejoras en el código sin consultarle. Ignorar sus chapuzas pero sustituirlas por soluciones más apropiadas.

Claro, esta es una estrategia muy arriesgada; nos crearemos fácilmente un enemigo peligroso. Lo que puede hacer que tenga éxito es que es similar a una guerra de guerrillas, a un desgaste lento y disimulado. No puedo recomendar algo así en general, pero definitivamente es lo que mayor probabilidad de éxito tiene. Eso sí, hay que saber hacerlo con mucha delicadeza.

Cuando Anfang subió las funciones de confirmCallback y confirmDfd yo no dije nada. No me enfrenté a él por ignorar completamente lo que le había dicho. Dos meses y medio después, como si no tuviera ninguna relación, añadí al wiki de documentación y mandé a todo el equipo que, si necesitaban diálogos de información o de confirmación podían hacer algo tan sencillo como…

$.confirm("...mensaje...")
    .on("accept", function() { ... })
    .on("cancel", function() { ... });

Unos días después, como ya no hacían falta, borré las horribles funciones de Anfang. Como digo, no puedo recomendar seguir una estrategia así a la ligera, pero sinceramente creo que es muchísimo peor problema no hacer nada contra una persona así.