Haciendo nuestros Data Access Object (DAO) transparentemente transaccionales

Y lo prometido es deuda, aquí­ viene un pequeño artí­culo con una idea para hacer las llamadas a vuestros DAOs transaccionales de forma totalmente transparente.
Hasta ahora por lo que habí­amos visto éramos capaces conociendo y aplicando los patrones DAO+DTO de encapsular nuestras llamadas al modelo de negocio, ordenarlas cada una en su DAO correspondiente, garantizar una íºnica instancia de cada uno de los DAO utilizando un Singleton… y algunas cosillas más.
Pero algo que nos quedaba pendiente resolver era cómo hacer que las llamadas a nuestros DAO se llevaran a cabo de forma transaccional. Es decir, que en caso de que en varias llamadas consecutivas a nuestros DAO (llamdas que alteren el contenido de una entidad de destino), podamos volver al estado anterior en caso de que ocurra un error en la aplicación.
Me explico. Por lo que conocí­amos por ahora podí­amos hacer lo siguiente.
try
{
 // insertamos tres coches
 CocheDAO.GetInstance().Insert(codigocoche1, “seat”);
 CocheDAO.GetInstance().Insert(codigocoche2, “mercedes”);
 CocheDAO.GetInstance().Insert(codigocoche3, “renault”);
 // actualizamos el coche 2
 CocheDAO.GetInstance().Update(codigocoche2, “honda”);
 // borramos el coche 1
 CocheDAO.GetInstance().Delete(codigocoche1);
}
catch (Exception ex)
{
 TratarExcepcion(ex);
}
Y qué ocurre si al insertar el coche níºmero 3 la aplicación falla. Pues que se habrán creado dos coches que quedarán colgados en la base de datos. ¿Cómo solucionamos esto? Creando una transacción. Pero claro, entonces aquí­ viene el gran problema… ¿de dónde narices saco la transacción si no tengo acceso a la conexión de base de datos? Este es el chiste del DAO, que no veo la conexión, es totalmente transparente a mi… entonces… ¿cómo voy a hacer algo transaccional?
Entonces es cuando aparece la idea feliz y nos inventamos unas transacciones propias para los DAO. Algo así­ como un TransactionDAO. Entonces nuestro código anterior cambia un poco y pasa a ser el siguiente:
try
{
 TransactionDAO tran = BaseDAO.BeginTransaction();
 // insertamos tres coches
 CocheDAO.GetInstance().Insert(tran, codigocoche1, “seat”);
 CocheDAO.GetInstance().Insert(tran, codigocoche2, “mercedes”);
 CocheDAO.GetInstance().Insert(tran, codigocoche3, “renault”);
 // actualizamos el coche 2
 CocheDAO.GetInstance().Update(tran, codigocoche2, “honda”);
 // borramos el coche 1
 CocheDAO.GetInstance().Delete(tran, codigocoche1);
 tran.Commit();
}
catch (Exception ex)
{
 tran.Rollback();
 TratarExcepcion(ex);
}
Parece esto una llamada a transaccional tí­pica, ¿no? Pero hay una sustancial diferencia, es que la transacción no es una transacción de base de datos que nos pueda proveer por ejemplo .NET (SqlTransaction) si no que es una transacción propia del DAO y que nos provee para hacer las llamadas transaccionales. El cómo implemente internamente la transacción el DAO ya es problema suyo, y me explico. En el caso que el DAO esté atacando a una base de datos internamente implementará una arquitectura trabajando con SqlCommand y SqlTransaction… pero… ¿y si está llamando a Servicios Web? ¿Y si está atacando a ficheros de texto? ¡¡Pues ya lo definirá internamente!! Eso es totalmente transparente a la capa que llama a los DAO.
En el caso del ejemplo hemos implementado llamadas a métodos BeginTransaction, Rollback y Commit en nuestro BaseDAO, que es el que internamente gestiona las transacciones. ¿Cómo puede funcionar esto internamente? Pues por ejemplo manteniendo BaseDAO una lista genérica de de TransaccionDAO, la cual irá aumentando y disminuyendo a medida que los clientes pidan y confirmen transacciones.
Tal vez quede perfilar un poco más cómo maneja BaseDAO ese pool de transacciones… eso lo haremos en otro artí­culo. Dejo alguna pregunta abierta ¿qué ocurre si creamos transacciones y luego no hacemos rollback o commit de ellas? Deberiamos currarnos la caducidad de dichas transacciones…
Saludos.
Miguel.

Mejorando nuestro DAO y DTO

En uno de los artí­culos anteriores estuvimos hablando de dos patrones de diseño, DAO y DTO.
En esta ocasión vamos a partir de lo que ya conocéis de los mismos y vamos a darle una vuelta más para ver cómo podemos mejorarlo. Si lo necesitáis podéis leer el artí­culo anterior para poneros un poco en situación antes de leer este 🙂
Si descargáis el código fuente correspondiente al artí­culo anterior (Ejemplo DAO) podréis observar que el DAO hereda de BaseDAO que es la clase abstracta que contiene la conexión que maneja el DAO y algíºn otro método más que pueda ser íºtil al conjunto de nuestros DAO.
Además, si seguí­s echándole un ojo, veréis que CocheDAO tiene varios métodos definidos, alguno para insertar, otros para hacer selecciones… y que los nombres corresponden a GetCoche (retorna un CocheBean), GetCoches (retorna una lista genérica de CocheBean)… Si tuviéramos por ejemplo un DAO que nos ayudara a trabajar contra una entidad de datos Gato, tendrí­amos un GatoDAO, el cual por aproximación y estándar de nomenclatura contendrí­a métodos como GetGato y GetGatos.
Esta es una forma con la que se puede trabajar, y llevando un estandar de nomenclatura podemos mantener una estructura clara y fácil de manejar para el equipo de trabajo.
De todas maneras, querí­a también dejar patente que esto es mejorable y que podemos definir mediante una interfaz (a la que llamaremos IDAO) una serie de métodos comunes que deberán implentar todos los DAO… a continuación alguno de ellos:
1) Delete
2) Insert
3) Update
4) GetOne
5) GetAll
6) Count
Todo nuestros DAO deberán implementar almenos estos cinco métodos (por el nombre más o menos se ve de lo que va la cosa).
La duda puede venir en cómo puñetas pasámos los parámetros por ejemplo a Insert y Update… ya que dependiendo de la entidad (me gustarí­a resaltar que en ningíºn momento estoy usando la palabra tabla en este ámbito, ya que precisamente el DAO lo que hace es ocultarnos cómo estamos accediendo a los datos… nadie nos asegura que esté atacando a una base de datos relacional y no lo esté haciendo a un servicio web, o a nada absolutamente) necesitaré pasar una serie de datos diferentes. Por ejemplo para la entidad coche tendrí­a que pasar la matrí­cula y el níºmero de puertas… mientras que para un gato podrí­a pasar su nombre y su raza.
El truco está en utilizar también un interfaz con los Bean (nuestro patrón DTO, que lo llamamos bean en honor a los amantes de java) y al que llamaremos en este caso IBean.
Entonces, nuestro IDAO puede definir los métodos de una forma similar a esta (Código C#).
void Insert(IBean bean);
IBean GetOne();
List<IBean> GetAll();
void Delete(Integer id);
int Count();
Menudo truco, esto nos servirá de forma igual para que lo implementen todos nuestros DAO!
¿Y qué ventajas nos puede ofrecer el añadir Interfaces a toda esta historia a parte de mantener una estructura idéntica en todos los DAO? Pues a entre otras cosas a hacer cosas como estas (Código VB.NET)
dim Lista as List(Of IDAO) = GetListaDeDAOs()
dim total as integer = 0
for each unDAO as IDAO in Lista
    total += unDAO.Count()
next
Otra ventaja es la de poder crear una Factorí­a de DAOs (del patrón Factory hablaremos en su momento también), cosa que podemos necesitar hacer en proyectos que alcancen cierto tamaño. Os dejo también un ejemplo (código java)
// Obtengo condición por teclado
condicion = Teclado.getCadena(“Condición:”);
// Obtengo el DAO de la factoria
InterfaceDAO dao = FactoriaDAO.getDAO( nombreTabla ); 
// La Select devuelve Vector 
Vector vec = dao.select( condicion );     
  Iterator it = vec.iterator();
while (it.hasNext()) {
bean = (Bean) it.next();
System.out.println( bean.toString());
}
Para finalizar os adjunto un archivo comprimido donde he creado un pequeño proyecto donde podéis ver la definición de esto un poco en marcha.
Ejemplo DAO + Interfaces
Un saludo.
Miguel.

Patrón de Diseño: Data Access Object (DAO) + Data Transfer Object (DTO)

Y como no, sigo dándole vueltas a mejorar el acceso y la protección de los datos.
Antes de empezar a haceros un breve resumen de lo que es un DAO y un DTO os dejo primero unos links donde podréis verlos en marcha de forma mucho más concreta.
https://en.wikipedia.org/wiki/Data_Access_Object
https://en.wikipedia.org/wiki/Data_Transfer_Object
https://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
El chiste del DAO es que nos provee de una forma totalmente abstracta de acceso a datos. Es decir, puedo acceder a mi modelo de datos, pero íºnicamente a través del conjunto de métodos que me brinda un DAO. Si tengo un DAO para coches, por ejemplo CocheDAO, en él deberé tener definido por ejemplo un método Count() que me retornará el total de coches que tengo en mi base de datos. No sé cómo está implementado, ni qué base de datos utiliza (si es que accede a una base de datos), lo íºnico que sé es que resuelve mi problema.
Por lo tanto, desde la parte del Controlador de mi aplicación, puedo acceder a mi Modelo utilizando el patrón de diseño que ofrece DAO, de forma totalmente transparente. Esto por ejemplo nos llevarí­a a pensar que nuestro CocheDAO podrí­a contener otros métodos, como el método Delete (que borrarí­a un coche de la base de datos), Update (que actualizarí­a los datos de un coche), GetCochesByMarca (que a partir de una marcha retornarí­a los coches de la marca que hay en la base de datos), etc.
Todo esto suena en principio a lo mismo que serí­a tener una clase llamada Coche llena de métodos static a los cuales llamarí­a cuando fuera necesario. Esto, pues claro, resuelve el problema de tener todo el acceso a la tabla Coche centralizado, olé, bien, somos ordenados, pero DAO va mucho más allá. ¿Cómo resolverí­ais el problema de devolver un listado de coches a través de vuestra clase con métodos static? Pues a lo mejor vuestro método GetCoches() retorna un dataset rellenado con los coches, o un datareader/recordset, o una lista separada por comas, o una estructura xml, o un array… Pero los DAO incluyen otro concepto que es del los DTO. Los DTO son un tipo de objetos que sirven íºnicamente para transportar datos. Por ejemplo, el objeto de transferencia de datos de un coche podrí­a ser un CocheDTO (o CocheBean para los javeros). Entonces, DAO, lo que devuelve es una lista genérica de CocheBean, o tal vez un CocheBean si estamos buscando información de un solo coche. Para que os hagáis una idea, un CocheBean contiene íºnicamente propiedades de un coche como por ejemplo Marca, NumeroPuertas, Matrí­cula, etc. El DAO, tras una petición del Controlador, rellena un DTO o un conjunto de ellos, y lo devuelve al Controlador.
¿Y todo este lí­o para qué? Pues muy sencillo, si vuestro controlador ataca al modelo utilizando DAO y DTO estáis consiguiendo 100% la separación entre el Controlador y el Modelo. Ante cualquier cambio que se diera en la forma de acceder a los datos, pongamos por ejemplo que a partir de ahora en lugar de sacar los coches de una tabla coches se hace de un servicio web que retorna coches, vuestro modelo no se va a enterar, ya que lo que le va a seguir llegando van a ser siempre CocheBean. Conseguí­s un impacto cero patatero en vuestro Controlador (y en la Vista claro, pero eso ya lo habí­amos conseguido separando la Vista del Controlador).
Y aíºn más, si cada uno de vuestros DAO lo preparáis para seguir el patrón Singleton, tendréis siempre una íºnica instancia de la clase CocheDAO en memoria, por lo que aunque tengáis 200 usuarios tirando de dicho DAO tendréis una íºnica copia en memoria, con el ahorro que esto supone. Esto no ocurre por ejemplo si usáis static en todos los métodos de vuestras clases de acceso a datos (y os recuerdo que en un proyecto mediano el níºmero de métodos que llegan a acumularse para acceso a datos suele ser bastante grande).
¿Un ejemplo de código? Venga, vale, aceptamos barco, imaginaos que atacamos a una hipotética clase CocheDAO:
// GetInstance pide la instancia de la clase mediante el Singleton, CocheDAO tiene su constructor en modo privado.
CocheBean coche = CocheDAO.GetInstance().GetCocheByMatricula(‘IB-3234-ZX’);
// ahora tenemos un CocheBean, si no es nulo es que ha llegado bien, cogemos sus datos
if (coche != null)
{
    txtMatricula.Text = coche.Matricula;
    txtMarca.Text = coche.Marca;
    txtNumeroPuertas.Text = coche.NumeroPuertas;
}
¿Y qué ocurre en el Controlador si cambiamos el nombre del campo matrí­cula en la tabla coches? Pues nada, ni se entera.
Para finalizar os añado un link a un rar que he preparado con un DAO y un DTO preparados, que acceden a una hipotética tabla de Coches. Fijaros en el DAO lo que hace el Singleton, que además de forzar la utilización del método GetInstance, utiliza exclusión míºtua para evitar que se tenga más de una instancia del DAO en el caso de no haberse creado aíºn la instancia y dos usuarios accedieran al mismo tiempo al método GetInstance. El método GetCoche retorna un CocheBean, pero el método GetCoches lo que hace es retornar un lista genérica de CocheBean. Veréis además que CocheDAO hereda de BaseDAO, todos los DAOS deberí­an heredar de allí­ ya que BaseDAO les ofrece entre otras cosas la conexión a la base de datos y una serie de métodos comunes que pueden utilizar (BaseDAO lo he dejado algo básico sólo para que se entienda conceptualmente qué es lo que se supone que debe hacer). También tenéis la definición de CocheBean. Por íºltimo, veréis que existe un archivo llamado Excepciones donde se tipifican las excepciones que puede generar un DAO, una de las buenas prácticas de las que ya hemos hablado en otros artí­culos.
Os contarí­a además que DAO puede implementarse junto a DTO, pero además utilizando el modelo de Factorí­a, pero esto, lo dejaremos para más adelante.
Ejemplo DAO (esta vez os lo preparo en VB.NET, por variar un poco).
¿Interesante?
Saludos.
Miguel.