Hay que tener mente abierta, mente abierta siempre
Varias veces he tenido que hacer un programa Windows para ejecutar alguna tarea o para algún cliente. Desde 1998 he usado directamente la librería Win32 sin ningún wrapper o librería especializada en GUIs. Ya he hecho media docena de estos programas, pero todos han sido simples, con un menú de “Archivo” con las operaciones básicas de “Guardar”, “Guardar Como”, “Salir”, etc.. Nada complicado. Pero desde hace unas semanas he estado pensando en un programa que me ayude a hacer páginas web estáticas. He estado evaluando para este propósito WebsitePainter pero está lleno de problemas y la única vez que lo utilicé para una página real (para un cliente, utilizando los 30 días de evaluación) terminé editando la página html directamente, lo cual fue realmente doloroso porque WebsitePainter utiliza <div> con style “position:absolute”. No una mala idea si tienes un programa que haga el posicionamiento, pero una pesadilla si lo tienes que hacer a mano.
Intento fallido.
Así que decidí hacer un programa que haga esta tarea por mí, pero que lo haga correctamente:
- Impidiendo que un div se sobreponga sobre otro.
- Colocándolos en el mismo orden en que están en la pantalla.
- Y permitiendo más styles (o cualquier style) sobre estos div’s
Pero no iba utilizar mi “low level” framework basado en Win32. Necesito un generador de GUIs para esto. Las opciones obvias e inmediatas son QT y wxWidget (hay otra solución basada en Java descartada por razones obvias). Sin embargo, no obstante, a pesar de que eran obvias, decidí comenzar evaluando una cuarta opción poco conocida. Ultimate++.
No he terminado la evaluación y no sé si voy a utilizarlo, pero si quiero mencionar algo sobre el proceso de acercamiento a un nuevo API. Porque nosotros como programadores debemos tener una mente muy abierta y dispuesta a estudiar un nuevo API. Debemos estar dispuestos a analizar 6 nuevos APIs antes de desayuno. Una mente muy abierta es lo más importante. Y eso se traduce en esperar lo inesperado y visualizarlo desde el punto de vista del API, no desde nuestro punto de vista. Ultimate++ tiene una idiosincrasia muy particular. A veces nos parece que está forzando la sintáxis de C++ al límite. Por ejemplo esta puede ser una típica rutina:
[cce lang=”c” width=”480″]
int version = 0;
s / version;
SerializePlacement(s);
files.SerializeSettings(s);
s % dir;
s % splitter;
[/cce]
¿Me perdí de algo aquí? ¿Qué se supone que va a suceder con esa instrucción “s % dir”. Todavía no tengo idea. Pero lo que quiero comentar es esta sencilla instrucción:
[cce lang=”c” width=”480″]
w.DrawImage(40, 240, CtrlImg::save());
[/cce]
“w” es el parámetro a la función “Paint”, y DrawImage () es uno de sus métodos. Pero qué es “CtrlImg::save()”? A mi me parece una llamada a un método en el espacio o clase CtrlImg. Algo así como cuando hacemos std::setw(20) para establecer el ancho de una salida en una operación sobre “cout”, la salida por defecto en C++. Entonces, ¿qué estamos guardando con esa llamada a “save()” si en el contexto no hay nada que guardar?. Por eso decía que hay que tener la mente bien abierta cuando entramos en contacto con un nuevo API, porque es como cuando entramos en contacto con una civilización extraterrestre: lo que nos resulta normal es anormal para ellos, y lo que es normal para ellos es anormal para nosotros (“Los oscuros años luz” de Brian Aldis… ¿alguien?) Pues para no estirar demasiado el suspenso esa oscura instrucción es en realidad una constante, o definición, o una etiqueta: CtrlImg::save() retorna un apuntador a la imagen del ícono de “save”, “guardar”. Lo normal en cualquier API o librería es colocar eso en mayúsculas o al menos colocar un comentario en alguna parte (este ejemplo lo estoy sacando de los tutoriales) donde se indique de qué se trata (o en la documentación la cual olvida por completo mencionar algo sobre el tipo de cosas que normalmente se pasan como parámetro a DrawImage). Claro, esto se hubiera resuelto si hubiese conseguido la documentación de DrawImage, antes de que mi mente comenzara a especular (al final conseguí la declaración: DrawImage(int x, int y, const Image& img)). Hay que tener mente abierta, mente abierta siempre.