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.

31 thoughts on “Patrón de Diseño: Data Access Object (DAO) + Data Transfer Object (DTO)”

  1. Hola Miguel,
    Me parace muy interesante el artí­culo pero hay una cosa que no entiendo y puede que tenga más que ver con el patrón singleton que con el acceso a datos. No entiendo porqué utilizas el singleton en lugar de métodos estáticos. Se supone que un método estático es compartido por la apliación y no se crea una instancia de dicho método cada vez que sea utilizado ¿no es así­?.
    Saludos.

  2. Hola Goyo,
    En primer lugar, si utilizas métodos estáticos ten en cuenta que un hijo de un DAO no podrá sobreescribir el método y eso hace perder potencia a tu definición. Imagí­nate el caso de que creas una clase de pruebas que herede de tu DAO y sobreescriba la definición de alguno de los métodos para hacer como te digo ciertas pruebas… si son static no vas a poder hacerlo. Estás perdiendo la orientación a objetos.
    En segundo lugar, no tengo muy claro que si declaras todos tus métodos estáticos puedas llevar a cabo una factorí­a de DAOs. Y eso volverí­a a ser otra vez perder potencia.
    Saludos.
    Miguel.

  3. Hola Miguel,
    Bien, utilizando métodos estáticos no podemos sobreescribirlos en herencia y por tanto el código es menos flexible y tampoco podemos utilizar una factoria.
    Salvando este inconveniente y si no cecesitamos herencia, el rendimiento serí­a similar utilizando métodos estáticos y el singletón
    ¿O realmente hay diferencias de rendimiento cuando hay muchos usuarios (ocupación de memoria, etc.) en un caso y otro?
    Gracias por tu respuesta.
    Saludos,
    Goyo.

  4. Hola de nuevo,
    La verdad es que en cuanto rendimiento desconozco totalmente si el uso de una u otra solución te podrá aportar una mejora de peso.
    El único problema que conozco al respecto lo podrí­as tener si utilizas el singleton sin crear la zona de exclusión míºtua al comprobar si se ha hecho instancia de la clase DAO (en el método getInstance).
    Siento no poder aclararte más dudas respecto a la diferencia de rendimiento.
    Saludos!
    Miguel.

  5. Es genial este patrón, facilita mucho el desarrollo de un sistema por capas, lo estoy usando en un proyecto actual y vale la pena el esfuerzo extra a cambio de una mayor portabilidad y organización.

  6. La verdad es que ayuda a dejar la capa de acceso a datos niquelada. Fácilmente mantenible, totalmente estructurada, y lo más importante, eres capaz de sacar esa pieza y substituirla sin que el resto de capas ni tan siquiera se enteren del cambio.

  7. Gracias Shirley,
    Cualquier tipo de aportación, corrección o mejora al artí­culo que pueda aumentar su valor, es más que bienvenida.
    Un saludo.
    Miguel.

  8. Hola Miguel,
    Gracias por explicar de una manera clara este tema, por si alguien no sabe que es el patrón Singleton, ahi les va una breve explicación.
    El patrón singleton se implementa creando en nuestra clase un método que crea una instancia del objeto sólo si todaví­a no existe alguna. Para asegurar que la clase no puede ser instanciada nuevamente se regula el alcance del constructor (con atributos como protegido o privado).

  9. Hola, muy buena la explicacion, clara y precisa, me quedo con una buena base para empezar el nuevo proyecto en el que estoy, gracias.

  10. ínimo con vuestro trabajo, cualquier aportación será bienvenida 🙂
    Voy a intentar preparar una segunda parte a futuro de este artí­culo, que veo que a muchos os ha resultado interesante.
    Saludos.

  11. En hora buena Miguel, la verdad que que tu articulo es de muchisima ayuda .
    Muchas Gracias, y espero que sigas desaznando nuestras intrigas de progrmación.
    Un abrazo.
    Saludos.

  12. hola Miguel. me parece muy interensate este articulo, ya que soy apenas una estudiante de desarrollo de software(me lo dejaste muy muy claro), y q bn poderlo implementar.
    El ejemplo DAO esta disponible en c#?

  13. Me soluciona alguna dudas, creo que es hora de comenzar a implementar y encontrarme de frente con esto.
    Voy a ver que mas articulos interesantes tienes por el blog

  14. Gracias por la explicación. Yo recién he recibido un curso de esto, pero me hubiera ahorrado muchas horas de estudio de haber leí­do antes tu explicación.
    Saludos desde El Salvador

  15. No entendi un carajo con tu explicacion, no hay forma de verle un lado mas practico, pero bueno supongo que es porque soy ignorante del tema MVC, pero aun asi seria de mas utilidad ejemplificar la teoria de una forma mas practica, gracias de todas formas

  16. Excelente aporte y muy buena redaccion para la explicacion.
    Me gustaria agregar que tambien existen mapeadores ( como hibernate) que evitan tener estos Objetos DAOs que pueden ser tediosos de programar
    Saludos

  17. Excelente aporte Miguel, lei varios blogs pero el tuyo definitivamente es el q mas entendi.
    Nos debes el RAR en C#. Saludos!

  18. He usado varias veces el DAO pattern, pero realmente no entiendo la utilidad de usar el Data Transfer Object pattern. ¿Por que no utilizas los objetos del negocio directamente, de forma que los daos retornen objetos del negocio en vez de objetos DTO? Todo el quilombo de los DTO es para desacoplar completamente el controlador del modelo??
    Agradecerí­a una ayuda acá.
    Saludos.

  19. Hola Miguel,
    Pienso que has hecho un gran trabajo con esta pequeña explicación sobre DAOs y DTOs.
    Gracias
    Marcos

  20. Que tal Miguel,
    Me ha servidor mucho este blog y aclaró algunas dudas que tenía al respecto. Finalizando me gustaría tener el código del proyecto en C Sharp, ¿es posible? Te lo agradezco.
    Saludos.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.