Grimpi IT Blog

abril 9, 2008

El patrón DAO

Filed under: .NET, Arquitectura, Patrones, SQL Server — grimpi @ 1:12 am

Yo no soy un fanático de implementar montón de patrones y capas a los sistemas. Hoy en día hay sistemas que para desarrollar una función, requieren escribir en hasta 7 archivos diferentes.
Muchas veces complica más las cosas de lo necesario.
Sin embargo, uno de los patrones en mi opinión “fundamentales” del desarrollo de software, es el DAO (Data Access Object).
El DAO maneja la conexión con la fuente de datos para obtener y almacenar datos.

El uso de este patrón ofrece varios beneficios para la persistencia de datos:
* Sirve para separar el acceso a datos de la lógica de negocio. Algo altamente recomendable en sistemas medianos o grandes, o que manejen lógica de negocio compleja.
* Encapsula la fuente de datos. Esto es especialmente beneficioso en sistemas con acceso a múltiples entradas.
* Oculta la API con la que se accede a los datos. Por ejemplo en .NET si usamos siempre OleDb y queremos cambiar al NHibernate.
* Centraliza Todos los Accesos a Datos en un Capa Independiente

Cuando trabajamos con DAO, trabajamos en un mundo donde desconectado, donde nuestros datos se deben persistir en objetos.
Por lo tanto, cuando nos piden realizar una operación, se abre la conexión a la base, se ejecuta el comando, si es una operación de lectura, se vuelca el contenido hacia una estructura de datos y se cierra la conexión.

Transacciones:
Un problema muy común cuando se trabaja con este patrón, es como usar las transacciones.
Se deben ejecutar todas las operaciones dentro de un método?
Puede un DAO invocar métodos en otro DAO? Quien y como se deben manejar las transacciones?
Bueno, todo esta problemática que define el límite de la transacción se llama “Transaction demarcation”.
Existen 2 modelos diferentes que aplican según la necesidad de la operación transaccional que se va a efectuar.
Uno hace al objeto DAO responsable de la transacción, el otro desplaza la transacción al objeto que esta llamando el método DAO.
El primer caso (y el más usual) se puede codificar de la siguiente manera en C#:

public class ProductoDAO
{
public void Eliminar()
{
SqlConnection connection = new SqlConnection(“CONEXION”));
conn.open();
using (SqlTransaction trans = new SqlTransaction(conn))
{
SqlCommand com = new SqlCommand(“DELETE FROM P1”, conn, trans);
com.Execute();
SqlCommand com2 = new SqlCommand(“DELETE FROM P2”, conn, trans);
com2.Execute();
SqlCommand com3 = new SqlCommand(“DELETE FROM P3”, conn, trans);
com3.Execute();
trans.Commit();
}

conn.close();
}

}

En este ejemplo, para eliminar todos los productos y tablas relacionadas, se llama al objeto que maneja las transacciones de ADO.NET.
Con lo cual es perfectamente lógico encapsular el borrado de todas las tablas en un mismo método DAO, ya que se está afectando solamente la entidad Producto.

Pero supongamos que queremos eliminar transaccionalmente además de todos los productos, todas las ventas y todas las agencias.
Seria correcto meter la lógica del borrado de Ventas y Agencias dentro del método EliminarProducto? Como funcionar, funcionaria obviamente, pero estaríamos mezclando operaciones de distintas entidades y peor aún, estaríamos agregando métodos poco reutilizables y confusos.
Entonces lo correcto en este caso sería meter la lógica de la transacción fuera del DAO.
Para poder implementar esto, es necesario usar Transacciones distribuidas que .NET se implementan con EnterpriseService (En Java existe JTA). En caso de que usemos SQL Server 2005, podemos simplificar su considerablemente.

public class Negocio

{
public static void EliminarTodo
{
using (TransactionScope scope = new TransactionScope())
{
VentasDAO.Eliminar();
AgenciasDAO.Eliminar();
ProductoDAO.Eliminar();
scope.Complete();
}
}
}

Pasaje entre capas:
Ahora bien, ya sabemos porque debemos usar DAO y que beneficios nos trae.
Pero como deben ser el pasaje de datos con esta capa? Qué tipo de estructura usar?
En .NET existen varias variantes:

1) Dataset (tipado o no tipado)
2) XML
3) Data Transfer Objects (o objetos de Entidad)

Dependiendo de las particularidades de la aplicación, una opción puede ser mejor que la otra.
Definitivamente en la mayoría de los casos, usar Dataset no es la mejor práctica. Estamos de acuerdo que tal vez sea la opción más “cómoda”, pero los dataset son objetos pesados y lentos (en comparación con un Datareader), tienen montón de información, propiedades y métodos que no necesitamos.
Pero lo peor no es eso, la principal desventaja es que fuerza a toda la aplicación a usar un objeto de una tecnología especifica.

La más común de todas, es usar los Data Transfer Objects (DTO), también conocido como Value Object (VO). Es el típico patrón asociado a DAO.
Que son los DTO? Bueno, no son más que simples objetos que solo tienen getters y setters, que sirven para transportar la información de una capa a otra. El usar este patrón, ganamos performance, ya que al ser objetos livianos ocupan menos memoria, además de que nos permite abstraernos de cualquier tecnología especifica.

Recomendaciones a la hora de implementar DAO:

1) Combinar con el patrón singleton:
Tiene sentido tener múltiples instancias de DAO en memoria?
En la mayoría de los casos no, por eso yo por lo menos, suelo declarar todas mis clases DAO como static.

2) Crear una interfaz y un factory:
Todos los DAO generalmente tienen métodos comunes a todos, como DeleteById, GetById, GetAll, etc.
Declarar una interfaz IDAO, nos permitiría hacer un factory de DAOs.

3) Evitar el uso de dataset:
Si, como dije antes, es cómodo usarlos, nos ahorran tiempo de desarrollo. Pero a un costo alto.

Links:
http://www.ibm.com/developerworks/java/library/j-dao/
http://www.miguelmatas.es/blog/2007/11/13/mejorando-nuestro-dao-y-dto/
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.htm

4 comentarios »

  1. Otro método para abstraerse del sistema de transacciones propio de la tecnología, (en lugar de utilizar transactionscope para .NET por ejemplo) es que los propios DAO gestionan las transacciones de forma interna y que dispongan de métodos públicos para ello.

    http://www.miguelmatas.es/blog/2007/12/03/haciendo-nuestros-data-access-object-dao-transparentemente-transaccionales/

    Internamente los DAO gestionarán lo que es para ellos una transacción, dependiendo si realmente están accediendo a una tabla, un fichero, un servicio web, o una combinación de ellos.

    Saludos y gracias por el link.

    Miguel.

    Comentario por Miguel — abril 16, 2008 @ 6:56 pm

  2. Muy buen post, me acabas de despejar algunas dudas gracias :D

    Comentario por aldo — noviembre 4, 2008 @ 8:21 pm

  3. Excelente post.

    Comentario por Anónimo — diciembre 26, 2011 @ 1:07 pm


RSS feed for comments on this post. TrackBack URI

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Blog de WordPress.com.

A %d blogueros les gusta esto: