Showing posts with label grito desesperado. Show all posts
Showing posts with label grito desesperado. Show all posts

Tuesday, July 22, 2008

El objeto del negocio

rito (Del lat. ritus).
1. m. Costumbre o ceremonia.
2. m. Conjunto de reglas establecidas para el culto y ceremonias religiosas.

Siempre es peligroso entregarse al mito, pero más aún en los momentos de entusiasmo.
Comisario Inspector Díaz Cornejo
(citado por Leonardo Moledo en 'Los mitos de la Ciencia')



Los ritos y los mitos se mezclan de muchas maneras. Se podría decir que éstos dan origen a aquellos. Es divertido repasar mitos ajenos, como hace el libro de Moledo citado más arriba. Y es un poco inquietante descubrir que los mitos ajenos no no son tan ajenos, como nos recuerda el libro de Moledo citado más arriba.

Los ritos, en la primera acepción según la RAE, pueden ser útiles como una forma de adquirir hábitos benéficos sin que tengamos que detenernos a pensar en su beneficio. Diríamos que lo bueno de los ritos es que pueden lograr que un tonto se beneficie sin que tenga que entender por qué, ni como sucede.

Este efecto benéfico de la ritualización no fue el que había dejado su huella en la aplicación que aceptamos para mantenimiento correctivo y evolutivo (aceptamos es un abuso de la primera persona ni yo ni mis compañeros galeotes decidimos nada), sino más bien todo lo contrario. Digamos que lo que observamos fue el efecto más usual del reemplazo del pensamiento por la ritualización: algo así como el desastre. Podemos rastrear el mito que da origen a los ritos practicados en el diseño de la aplicación de marras, pero eso vamos a dejarlo a los antropólogos.

La gente que escribió esta aplicación era gente de principios. Con convicciones muy firmes. Idealistas. Sabían que había que tener tres capas: presentación, lógica, y datos, a como diera lugar. Su esfuerzo patriótico no iba a cejar simplemente porque no tuviera sentido hacerlo, no. Ellos tenían certezas, y por sobre todo la certeza de que la duda es la jactancia de los intelectuales.

Así, por ejemplo, los objetos de la capa de lógica de negocio son cosas del estilo:

public class CuentaServ implements CuentaServInt {
   CuentaDao cuentaDao;

   public void almacenarCuenta(Cuenta c)
   {
      cuentaDao.almacenar(c);
   }

   public Cuenta obtenerCuentaPorId(int id)
   {
      return cuentaDao.obtenerCuentaPorId(id);
   }

   [...]

}


Cualquier hereje podría preguntar para qué tienen una clase donde todos los métodos tienen una sola linea. Qué valor agrega. Para qué sirve. Pero no ellos: ellos eran gente de fe, gente que sabe que el
progreso humano es una ilusión, que el secreto de la felicidad está en copiar exactamente la conducta de nuestros ancestros, que vivieron armonicamente en una época de sabiduría que nosotros arruinamos con la costumbre de someter su legado a escrutinio crítico.

Mi primera impresión fue decidir que si una clase tiene solo métodos de una linea, si es solo un pasamanos, probablemente no tenga ningún sentido. Al fin y al cabo, si la aplicación no tiene reglas de negocio, no debiera tener una capa que implemente la lógica de negocio.

Pero, vamos a ver: que aplicación no tiene lógica?. Es decir, la lógica en la aplicación es algo que existe, si no está implementada tal vez simplemente no esté implementada. Por ejemplo, dar de baja una cuenta sin preguntar nada suena por lo menos extraño. Asignar un nuevo paquete de servicios a un cliente sin verificar algunas condiciones antes, también.

Me estaba desesperando, cuando encontré métodos de Business Objects que sí tenían más de una linea de código. Un alivio. El patrón estaba justificado. Al final, me decía la vocecita esa que siempre escucho (no, no es la conciencia, es un enanito que se sienta sobre mi hombro y que solo yo veo, porque él tiene poderes mágicos), viste que tenía motivos, que no sos tan vivo como crees?. Acá está la prueba:

public List obtenerCuentasEnRojo()
{
   List l = cuentaDao.obtenerCuentasEnRojo();
   for (Iterator it = l.iterator(); it.hasNext();)
   {
      Cuenta cu = (Cuenta)it.next();
      Cliente c = cu.getCliente();
   }
   return l;
}


Esto se ponía bueno: el críptico cu.getCliente() era para forzar a hibernate a buscar el cliente en la base de datos. Algo doblemente bueno, ya que hacía a mano lo que podía hacer en un join, transformando una única query en tantas como cuentas se obtengan, impidiendo el ordenamiento por nombre si es que se pagina el resultado y, como extra y por el mismo precio, haciéndolo antes de forma que la vista no dispare algún query de hibernate, cosa que se podría haber solucionado con un open session in view (está implementado en Spring)

De la colección de errores, mi preferido es el evitar escribir el join en la base de datos. Debo admitir que la alegria de ver el patrón justificado se vio algo perturbada por el hecho de que implementar a mano un join es una de las cosas más estúpidas que se pueden hacer: es más trabajoso (uno paga dos veces, una por el motor de la base y otra por las horas de desarrollo), suele quedar con más bugs que los que trae el join en la base de datos, tardar más, ser más vulnerable a cambios en el volumen de datos, es más dificil ordenar y paginar por algún atributo de la segunda tabla, y unas cuantas cosas más.

Subyacen a estas prácticas unos cuantos mitos y esperanzas descabelladas: portabilidad entre base de datos (mi preferida, merecedora de un post enteramente dedicada a ella), adaptación al cambio (sí, es muy fácil adaptar un montón de código innecesario), prolijidad (que alguien me explique como se mide). Tal vez, al fin y al cabo, viendo las esperanzas descabelladas que sobreviven por ahí afuera en cuestiones algo más trascendentes que un business object, no tengamos derecho a esperar que estas, nuestras esperanzas descabelladas, desaparezcan en un futuro cercano.

Friday, June 13, 2008

Que maestro!

Me gusta encarar proyectos de reingeniería de aplicaciones: tienen algo de candor iluminista (*) por eso de la confianza en el futuro, no se escucha el solapado o no tan solapado pedido del cliente de arreglá tres horas la mierda que nosotros hicimos en seis meses , y por supuesto, uno supone que se le ocurrirá una idea genial en diez minutos que será mejor que el diseño evolutivo que tiene encima una aplicación que hace quince años corre sin problemas ( tendencia innata al creacionismo, o a la irracionalidad, que es lo mismo, que tiene uno).

La idea de diseño evolutivo está tomada de la idea de la evolución de las especies: una aplicación que está andando, sufriendo cambios desde hace diez o quince años y que pasó por ocho presidentes, dos devaluaciones, cuatro incautaciones de depósitos, siete burbujas con sus correspondientes explosiones, doce cambios importantes en la legislación impositiva y miles de cambios menores ha hecho un fantástico trabajo de adaptación al medio. Claro que, en definitiva, el relojero es ciego, por lo que en el proceso adaptativo se generan características que hoy se revelan imperfectas, o directamente como boludeces. Algunas de estas imperfecciones evolutivas son imperfecciones porque cambió el entorno y lo que antes era una ventaja hoy no lo es. Otras siempre han sido malas pero la desventaja que suponen no ha sido incompatible con la supervivencia, todavía.
Así, haciendo arqueología en una aplicación que estábamos reingenierizando, dimos con una obra, no del relojero ciego, sino del diseñador corto. Llegamos a una tabla que se llamaba algo así como xtmaetr, y sus campos eran algo así como:
  • ID (bien, lógico, normal)
  • XTMAEDECR (puedo deducir que la descripción)
  • XTMAE_1
  • ...
  • XTMAE_9
Los ID eran correlativos, y el resto de los campos no tenían absolutamente ningún patrón: un mismo campo tenía una fecha en un registro, para pasar a tener una sucesión ininteligible de caracteres en el siguiente. Le preguntamos al padre de la criatura, quien orgulloso nos repondió: "esta tabla es el maestro". El maestro de qué? El maestro de todo, el master of the universe, alfa y omega, la real y lo posible, el sonido y la furia. A ver si me explico: esa tabla tenía todos los artículos, todos los clientes, todas las sucursales, todas las provincias, y así siguiendo, con un campo "tipo" que decía si estábamos en presencia de un cliente o de una pieza de repuesto de un motor diesel. Definitivamente, un maestro.

Una pena que no llevaran la idea un poco más allá y se limitaran a tener una tabla, como lo explica Tom Kyte: uno no tiene que diseñar nada, ni saber de diseño, ni conocer las características del software de base que está usando, simplemente tiene que hacer algo genérico.


(*) la entrada de la wikipedia de iluminismo no es correcta. Uso en este post a iluminismo como sinónimo de ilustración.

Tuesday, June 10, 2008

Lóbulo temporal

Quien convenció al mundo, o al menos a algunos IT Architects, que el uso de tablas temporales era una buena idea??!?.

No creo que sea una práctica extremadamente común (el mundo no funcionaría) pero me he encontrado con algunos casos: la última vez, el otro día.

El asunto era más o menos así: una típica aplicación de guarda-recupera-datos, que es lo que hacen, pese a la pretención de los amantes de las multicapas, la mayoría de las aplicaciones comerciales (la existencia de Business Objects que son solo un pasamanos, o peor aún, que implementan cosas que la base de datos hace mucho mejor, será tema para otro post).

La maravilla de la informática con la que mi triste figura dio el otro día tenía un bloque con la siguiente lógica (bueno, sabrán disculpar el exceso del lenguaje que significa llamar 'lógica' a eso):

  • El usuario identificado en la sesión podía ser de tipo A o B
  • Se generaba un número único de operación (con una secuencia)
  • Si el usuario era de tipo A, se obtenian datos de la Tabla A con una condición y se insertaban en la Tabla TMP agregándole a cada registro de la Tabla TMP el identificador generado anteriormente (así no se mezclaban los datos entre sesiones, no vayan a creer que era una chapuza)
  • Si el usuario era de Tipo B, insertaba igualmente en la Tabla TMP pero pero obteniendo los datos de la Tabla B
  • Para finalizar, hacía un join entre la Tabla TMP, filtrando por el ID de operación, y otra tabla, agregando proyecciones y otras cosas para finalizar mostrando unos pocos resultados.
  • Al finalizar, borraba, vía delete, los registros de la Tabla TMP con el ID de operación (obviamente, no podía hacer un truncate porque la tabla la usaban unas cuantas sesiones)
Este portento del ingenio humano en forma de aplicación informática transformaba así una consulta en dos consultas, más unos cuantos inserts, más idéntica cantidad de deletes. Eso sí, la muestra de destreza tecnológica tenía un motivo: la reutilización de código ( no es claro como se reutiliza el último query, más todos los deletes? Que no debieran existir es apenas un detalle que no debe opacarnos la alegría que nos causa reutilizar código), y la lógica de la aplicación, que haría que si esto fuera una única query sería demasiado complicada ( es claro que es mucho más sencillo seguir un código que hace en muchas líneas lo que se podría hacer en una ).

En la contemplación y admiración de tal muestra de capacidad e inventiva pasé unos días, la semana pasada: los gustos hay que dárselos en vida.