Resulta que estoy trabajando en un sistema bastante moderno, .NET 2005, SQL2005, winforms, y está a la mitad de su tiempo de desarrollo.
Durante un refactoring, me dí cuenta de todo el desperdicio que estabamos haciendo con funciones con mil parámetros para búsquedas. Parámetros sobre como usar los otros parámetros, etc, pero estaba confiado que no había un camino fácil de escape para este particular problema, así que intenté un nuevo truco viejo.
A pesar de todas las posibles soluciones que un framework como .NET 2.0 provee, y a pesar de todas las cosas que uno aprende de arquitectura, diseño de software, técnicas ágiles, bla bla bla, uno termina apreciando la formación matemática y todo ese sufrimiento que te hacen pasar por la universidad durante todos esos distintos ramos, con aritmática binaria y cálculo de máscaras de red y todas esas cosas que uno piensa en su momento que jamas, JAMÁS en su vida va a usar porque hoy no se programa a ese nivel…
No es tan así. Lo que necesitaba era una solución ninja, algo que fuera consecuente desde la capa de interfaz de usuario hasta la misma capa de procedimientos almacenados en la base de datos.
Pensando esto, se me ocurrió derrepente “flags binarios”. Era genial. Repentínamente tenía (en mi mente) resumidos 5 ó 6 parámetros en 1, junto a una elegante enumeración para la capa de presentación.
La aventura fue luego, aprender como demonios se hacía eso en un lenguaje de alto nivel y no pensado para cosas ninjas como lo es Visual Basic .NET, pero mi sorpresa fue mayúscula cuando finalmente logré escribir el código y quedó bastante bién.
El concepto es: Quieres obtener un conjunto de objetos de negocio desde la capa de datos (mediante una capa de acceso a datos, por supuesto) y el proceso pasa por un procedimiento almacenado que recibe los parámetros de búsqueda y retorna los resultados.
La clase a la cual pertenecen los objetos, tiene alrededor de 10 propiedades públicas, algunas objetos anidados que a su vez tienen un par de otras propiedades, y el usuario mediante la interfaz, tiene un formulario para utilizar todas sino la mayoría de ellas como filtro a su búsqueda.
Complejidad añadida, es que la mayoría de estos campos se busca por rango (inicio-término) , y muchos tienen valores por defecto, y no se puede hacer el truco de “si no viene X no quiere buscar por X ni X+1″.
Bueno, haciendo el cuento corto largo un poco menos largo….
Así, el formulario tiene un conjunto de groupbox con checkboxes que le permiten al usuario indicar si ese rango va a ser usado como filtro, lo que nos deja un montón de parámetros a usar sólo como configuración, y otros muchos como datos.
Lo que hice fue hacer una enumeración de estos parámetros de búsqueda, asignarle valores potencias de 2 a cada elemento en la enumeración y guardarlos en una sola variable integer, utilizando el viejo truco del “OR”.
Lo entretenido es que en Visual Basic, el OR lógico y el OR binario son el mismo. Es un operador sobrecargado. Lo mismo sucede con And, XOR y NOT.
Lo no tan entretenido, es que todo el código tuvo que estar muy comentado y quedó menos legible de lo que se acostumbra en Visual Basic.
Lo práctico fue que no solo redujo el código el la aplicación (en UI y BL) sinó que también redujo notablemente el código en el procedimeinto almacenado, ya que las sentencias where sólo necesitaron de un verificador con operacion “And” (que en TSQL es &) y luego una simple comparación dependiendo del parámetro. (en comparación a lo que era antes, con un montón de IF BEGIN – ELSE IF – END IF)