@ agnasg

agnasg


Es como picar una patilla por la mitad… con las manos

21-08-2011 1:26 PM

Ya he mencionado que tuve un enfrentamiento con la realidad el pasado 22 de julio, así que muchos de mis side projects quedaron congelados por aquélla época. Como lentamente estoy volviendo a la normalidad, he comenzado a revisarlos uno por uno. Lo siguiente aparece como última anotación  en la bitácora de panicputc:

17-07-11 · (P) Implementación de una ventana que permita seleccionar un icono de una lista y que devuelva el código (id) del icono seleccionado. Colocar en CWIndows.

La (P) significa que es una actividad pendiente, por supuesto. Me quedé leyendo aquello varios minutos recordando todo el trabajo alrededor de esta actividad y la importancia que tiene para la continuación del proyecto. El conocedor de cómo funcionan los video-juegos entenderá rápidamente que esto es la piedra angular de las interfases de los juegos modernos. Esta ventana puede ser usada para seleccionar un objeto en el inventario, un hechizo en el libro de hechizos, un arma, una poción, etc. De hecho, puesto que esta es una función que puedo reutilizar en otros juegos sería ideal que esté en una clase multipropósito. Afortunadamente he estado balanceando la necesidad de que las clases sean de uso general y que efectivamente cumplan sin tantos rodeos el requerimiento que tengo, así que la mencionada clase CWindows tiene un diseño razonablemente genérico. Algunos blogguers (yo incluído) han enfatizado la necesidad del delivery: lo que sea que estemos haciendo debe satisfacer  el requerimiento sin dilaciones, sofisticaciones u optimizaciones prematuras. Por otro lado, por mi experiencia, estas clases genéricas  difícilmente van a satisfacer el 100% de los casos, eso ni siquiera lo logra el mejor de los APIs. Así que hay un límite invisible entre estas dos fuerzas, un límite que no debemos quebrantar más, ni siquiera por nuestra búsqueda de la perfección.

Algo que mi bitácora no indica es dónde se supone que esta rutina es necesaria con prioridad. Esto no resultó gran problema pero hubiese sido agradable algún contexto. Descubrí para mi alivio que la rutina ya estaba bien adelantada así que no tuve que pensar mucho. De hecho se parece a otra rutina que hace algo similar, pero devuelve un mensaje del usuario. Ambas rutinas tienen una parte de inicialización similar. Estuvo lista rápidamente, pero presentaba un bug. Solamente se podía invocar una vez.  La segunda vez la ventana no se abría. Dos horas después descrubrí que la rutina requiere que la variable m_status esté inicializada en false. De hecho, la otro rutina tiene un:

m_status = false;

muy ufano al comienzo. ¿Cómo es posible que estuvo ahí invisible durante dos horas? Varias razones:

  • Estaba antes de las declaraciones de las variables, a veces esto resalta las instrucciones, otras veces las oculta.
  • Le dediqué mucho tiempo a perseguir algún error a los IDs de las ventanas pensando que ahí radicaba el error. Esta parte del código es extremadamente asincrónico, dado que el programa se detiene y espera a que el usuario cierre la ventana o presione “OK”.
  • No había una línea de documentación indicando “esto es importante porque …”
  • Transcurrió un mes desde la última vez que estuve tocando este código, realmente había olvidado la importancia de la variable m_status y quedó de última en la lista de cosas por revisar. De hecho, m_status suele ser una variable inofensiva, pero no esta vez.

¿Qué hemos aprendido, mi querido saltamontes?

  • Una buena descripción de la actividad es importante. Si viene acompañada del contexto, mucho mejor. Pero la descripción debe ser breve.
  • Las fuerzas imperiales de la programación a objetos nos obligan a producir clases genéricas y multipropósito. Las fuerzas revolucionarias de nuestro proyecto nos obligan a terminar y cumplir con el objetivo del proyecto lo antes posible. Conseguir una solución diplómatíca y en equilibrio de estas dos fuerzas antagónicas es nuestro trabajo y no lo debemos perder de vista
  • Las instrucciones deben ser colocadas en el lugar correcto. Si están en medio de declaraciones de variables deben ser remarcadas con un comentario. Las declaraciones deben ser retrasadas al máximo para ayudar al compilador a optimizar pero esto no debe comprometer la claridad del código. Una vez más hay dos directivas contradictorias aquí y es nuestra tarea colocarlas en equilibrio.
  • No hay variables inofensivas.