Miguel Matas Blog

Ingeniería y Arquitectura de Software, Proyectos IT, Programación, Personas, Problemas, Mejora Continua, la vida.

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.

5 comments

5 Comments so far

  1. Jeff September 2nd, 2008 7:24 am

    Primera ves que veo esta instruccion SyncLock pero ya entiendo algo como para que sirve

    El uso más comíºn de SyncLock es impedir que más de un subproceso actualice los datos simultáneamente. Si las instrucciones que manipulan los datos deben completarse sin interrupciones, colóquelas dentro de un bloque SyncLock.

  2. Ignacio April 3rd, 2009 3:19 pm

    Miguel, buen dí­a! Mi nombre es Ignacio. Estoy siguiendo tus consejos para el desarrollo de un software pero me surgió el siguiente problema. Creé una IEntidad (que vendrí­a a ser tu IBean) y la implementé a todos los DTO de mi aplicación. Cuando los uso, los declaro segíºn el tipo de Entidad. Por ejemplo, tengo una entidad clsArticulo, entonces cuando declaro un objeto a partir de esta clase lo hago de la siguiente manera: dim oArticulo as clsarticulo. Hasta acá todo bien. En cambio, cuando declaro una lista de estos objetos tengo que hacerlo de la siguiente manera: dim oListaArticulos as list(of IEntidad). En tu ejemplo veo que hacés lo mismo. El problema surge cuando quiero utilizar el método find de la clase List. Te paso mi fragmento de código para que puedas ver lo que te voy a comentar:

    Private Sub MostrarArticulo()
    _Articulo = Nothing
    Dim IdArticulo As New Predicate(Of IEntidad)(AddressOf BuscarArticulo)
    _Articulo = CType(_ListaArticulos.Item(_ListaArticulos.FindIndex(IdArticulo)), clsArticulo)
    If Not _Articulo Is Nothing Then
    Dim frmArticulo As New frmArticulo
    frmArticulo.Articulo = _Articulo
    frmArticulo.ShowDialog()
    End If
    End Sub

    Private Function BuscarArticulo(ByVal Articulo As clsArticulo) As Boolean
    If Articulo.IdArticulo = Me.lvwLista.SelectedItems.Item(0).Text Then
    Return True
    Else
    Return False
    End If
    End Function

    Me dice que BuscarArtí­culo tiene distinta firma que el delegado predicate. Si en todos los lugares donde dice clsArticulo pongo IEntidad, la propiedad IdArticulo me va a tirar error. Evidentemento pq pertenece a la clase clsArchivo. No se cómo salir de este inconveniente. En VS2008 me anda pero le tengo que poner option strict off.

    Si pudieras darme una mano con esto te lo agradecerí­a mucho.

    Desde ya muchas gracias.
    Saludos,
    Ignacio.

    PD: Excelente tu blog!

  3. Miguel April 11th, 2009 8:37 am

    Hola Ignacio,

    Mucho me temo que para utilizar la solución Predicate+Delegate+Find es obligatorio mantener la misma firma.

    Por lo que me he podido documentar, el Find internamente lo que hace es una especie de “For Each”, así­ que tal vez si encapsulas dicho funcionamiento en un método tuyo, puedas obtener el mismo resultado que pretendes obtener con el Find, pero utilizando la “potencia” del IEntidad.

    Te dejo el link a un artí­culo que marca el ejemplo donde me he apoyado para responderte.

    http://www.eggheadcafe.com/conversation.aspx?messageid=32369677&threadid=32369628

    Un saludo.

  4. […] en uno de los comentarios añadidos al post Mejorando Nuestros DAO y DTO, se ha tratado el uso del método Find en listas […]

  5. Ignacio April 15th, 2009 3:38 pm

    Miguel, muchas gracias por tu respuesta me aclaró las cosas y pude resolver mi problema. Yo necesitaba que la lista sea del tipo IEntidad y no clsArticulo. Por lo tanto, se me ocurrió hacer lo siguiente:

    Private Function BuscarArticulo(ByVal Articulo As IEntidad) As Boolean
    If CType(Articulo, clsArticulo).IdArticulo = Me.lvwLista.SelectedItems.Item(0).Text Then
    Return True
    Else
    Return False
    End If
    End Function

    De esta manera también me funcionó. Lo que hice fue poner la misma firma que el delegado y luego hice un CType de Articulo para que sea del tipo clsArticulo (que implementa la interfaz IEntidad) para tener la propiedad IdArticulo.

    Muchas Gracias!!
    Saludos,
    Ignacio.

Leave a reply

Please copy the string lKi2pH to the field below: