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.

1 comment:

AcP said...

No puedo dejar de estar de acuerdo, pero hay sutilezas. Recojo el guante y te respondo en Jaque.
Muy bueno el post, saludos.