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.
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.
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.
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.
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.
Gracias por tu ayuda y enhorabuena por tus artículos.
Saludos,
Goyo.
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.
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.
Muy buen material
Saludos
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.
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).
Gracias por la aportación Cris.
Saludos.
Miguel.
Hola Miguel,
Muchas gracias por tu paciencia al explicar este tipo de temas que son de gran ayuda.
Saludos.
Hola, muy buena la explicacion, clara y precisa, me quedo con una buena base para empezar el nuevo proyecto en el que estoy, gracias.
í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.
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.
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#?
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
Muy buen resumen !!! muy didactica tu explicacion.
gracias Miguel
Hola miguel tendras el ejemplito en Java ???
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
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
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
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.
Excelente aporte Miguel, lei varios blogs pero el tuyo definitivamente es el q mas entendi.
Nos debes el RAR en C#. Saludos!
Gracias amigo por hacer de algo tan dificil, algo tan facil!!!!
saludos desde Chile…
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.
Hola Miguel,
Pienso que has hecho un gran trabajo con esta pequeña explicación sobre DAOs y DTOs.
Gracias
Marcos
Hola,
me ha ayudado mucho tu explicación.
Gracias!
Muy interesante.
Gracias
Muy buen artículo Miguel. saludos
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.