Advertencia: Cualquier parecido con
la coincidencia, es sólo una sospechosa irrealidad...

uando, meses atrás, se me ocurrió la idea de escribir sobre el
cargocultismo estaba pensando, en particular, en el problema artificial, creado por mis amigos imaginarios, que voy a discutir a continuación. Repasemos la definición: el
cargocultista es el individuo que practica determinados rituales técnicos porque sabe, o ha oído decir, que a otros les funcionan, pero sin comprender realmente cómo se supone que tienen que funcionar.
En el mundo de la programación, uno de esos rituales misteriosos tiene que ver con la creación de gestores especiales para distintos módulos de la aplicación, sobre todo cuando se trata de proyectos grandes. Una aplicación "decente" tiene que definir, por fuerza, un "gestor" de menúes, un "gestor" de excepciones, un "gestor" de formularios... y así hasta el aburrimiento o la bancarrota. Para ser exactos, una parte importante de esta secta de cargocultistas no utiliza la palabra "gestor" sino manager, que se supone que debe darle un poco más de dignidad al engendro.

Como suele ocurrir en todos los casos de cargocultismo, la propia idea de un gestor de menúes y ventanas no es mala. ¡Todo lo contrario! Estos módulos suelen ahorrar mucho código repetitivo, y tienen la bonita propiedad de dejarse reutilizar fácilmente de un proyecto al siguiente. Incluso cuando se utilizan en un único proyecto, nos ofrecen la libertad de hacer cambios notables en la interfaz de usuario sin necesidad de retocar todo el código. Visual Studio, por ejemplo, nos permite elegir entre una aplicación MDI tradicional o una en la que los documentos aparecen en páginas paralelas accesibles por pestañas. Lo verdaderamente malo, es inventarse uno de estos gestores sin saber por qué, para qué o cómo.
Cuello de botella
A diferencia de disparates anteriores, esta vez el problema no está en una simple instrucción equivocada, sino en el diseño global de un módulo. Los problemas comienzan con la decisión, consciente o inconsciente, de esta gente de ignorar el mecanismo preestablecido para la traducción en .NET y de montar un barroco sistema basado en ficheros XML externos. El vínculo entre cada elemento de la interfaz y su correspondiente cadena se realiza manualmente. Supongamos que usted quiere añadir una etiqueta a un formulario que debe decir "Total". De acuerdo a la metodología de estos señores:
- Primero debe ocurrírsele un nombre global para identificar la etiqueta. No se les ocurrió generar ese nombre a partir del nombre del control y del formulario donde se encuentra.
- Luego tiene que ir a cada fichero XML de traducción y crear una entrada que traduzca el identificador al correspondiente idioma.
- Cada formulario tiene un método Traducir. No crea que se trata de un método virtual heredado: la herencia visual es algo desconocido en esta metodología. Tiene que añadir una instrucción manualmente a Traducir en la que asignará a la propiedad Text de la etiqueta, el resultado de una llamada explícita a un método que busca en un diccionario en memoria la traducción correspondiente.
Usted se dirá que... bueno, es bastante trabajo, claro... pero con un poco de disciplina... etc, etc. ¡Ah, cuán equivocado estaría! ¿No le he dicho aún que esta gente trabajaba con SourceSafe, para el control de versiones? Imagine lo que ocurre cada vez que dos programadores intentan programar dos formularios que nada tienen que ver entre sí: ¡se tienen que pegar por el acceso a los ficheros de idiomas!
De todas maneras, aunque no se produjese este increíble cuello de botella, el sistema es inaceptable:
- Microsoft ofrece, de serie y sin coste adicional, un mecanismo idéntico en funcionalidad y sin ninguno de estos problemas: ficheros de recursos y ensamblados satélites.
- El sistema de Microsoft no le obliga a añadir código manualmente en ningún momento.
- El sistema de Microsoft le permitiría, incluso, ahorrar trabajo suponiendo la existencia de un "idioma neutro", para el cuál no tendría que mantener una tabla de recursos adicional.
- El sistema de Microsoft es verificable en tiempo de compilación: si compila, funcionará. En cambio, el invento en cuestión utiliza cadenas como claves en el diccionario. Resulta imposible verificar automáticamente la existencia de errores de mecanografía. Por supuesto, si esta gente hubiese usado enumerativos para las claves, el problema se resolvería... pero los dioses ciegan a aquellos a quienes quieren destruir.
Moraleja parcial: no hay que reinventar la rueda, si además, va a rodar más despacio.
Escarnio de la locura
Pues bien, queridos amiguitos, hay también un menú diseñado de acuerdo a esta locura con sistema. Hay claves con formato de cadenas, que tienen que transmitirse desde el código al fichero externo y viceversa, hay versiones del menú para cada idioma soportado y todo lo demás. Pero me voy a centrar en un aspecto muy concreto: en cómo se maneja la ejecución de los comandos del menú.
Cada vez que se ejecuta un comando del menú principal, se invoca un manejador de eventos situado en la ventana principal. No crea que hay un manejador diferente para cada comando, lo cuál habría sido relativamente sencillo de conseguir: todos los comandos van a parar al mismo método. Y ese método, cómo no, contiene una inmensa instrucción switch, que toma la cadena de caracteres designada como clave del comando para ejecutar el código apropiado.
¿Y en qué consiste ese "código apropiado"? Maravíllese: en una llamada a un método global estático de una clase independiente, a la que llamaremos Acciones, que se encuentra en un gigantesco fichero C#.
- Nuevamente, tenemos un fichero que se convierte en un cuello de botella.
Claro, los conflictos por el acceso al fichero de acciones sólo tendrían que surgir cuando se modificase la estructura del menú... ¿o no? Resulta que no: cuando esta gente tiene que mostrar una ventana que permite una sola instancia, incluye, en el fichero de acciones, un bucle explícito para buscar si existe ya una instancia del tipo de ventanas en una lista global. Si la encuentran, la activan. Y si no, la crean. Y este código se repite tropecientas y tantas veces, una por cada ventana de este tipo, en el fichero de acciones.
- Con un poco de reflexión, el código común se podría haber reducido a una simple llamada.
- Pero mejor aún, el switch original ni siquiera tendría que haber pasado por la clase Acciones, sino que tendría que llamar directamente a métodos estáticos de las clases de ventanas correspondientes. De esa manera, cualquier cambio en la forma de mostrar una ventana, se aislaría dentro del código de la propia ventana.
- Para rematar, esta gente ni siquiera utilizó una metodología uniforme para la creación y activación. A veces llamaban a Show, otras veces combinaban BringToFront, Activate y Focus; a veces cambiaban la forma del cursor, y en otros casos, mostraban una ventana splash con el mensaje "Espere un poco...". Esto complica mucho limpiar el código.
Con todo, lo peor es que a estar alturas todavía les cuesta creer que este sistema sea un error: el cargocultismo susurró en sus oídos que necesitaban un "gestor de menúes" para su aplicación "seria", y ahora tiemblan cada vez que mis tijeras podan porciones cada vez mayores de este cadáver exquisito. Mientras limpio los fluídos putrefactos de mis instrumentos de corte, veo ojos asustados y oigo el coro de plañideras a mi alrededor. Sonrío tranquilizadoramente, pero compruebo que mi sonrisa parece cada día más siniestra.
Y es que uno termina hartándose, ¿sabe?
Etiquetas: C#, cargocultismo, disparates, metodología