Introducción al Modelo de Datos (I)

Llevo tiempo pensando en lo útil que resultaría contar con un modelo de datos cómodo que permita facilitar la labor de programación y posterior mantenimiento de nuestras aplicaciones. Coincido con mucha gente que la construcción de un modelo de datos es una tarea pesada que requiere mucha abstracción mental y escribir mucho código, pero también he de admitir que un modelo de datos bien construido ahorra muchas horas de trabajo.

He dividido el artículo en dos para hacerlo menos pesado, aunque al terminar este creo que todos los lectores sabrán por donde van los tiros y que va a pasar en la segunda parte.

Todo el código que pongo aquí está escrito con el único objetivo de ejemplificar un modelo de datos y, desde luego, puede ser mejorado; he suprimido a propósito controles de errores y otras cosas a fin de que se vea claramente como funcionan las clases que lo componen.

El ejemplo que vamos a usar para construir nuestro modelo de datos es una sencilla facturación:

  • Tabla de familias de artículos (id, nombre)
  • Tabla de artículos ( Id, Id_familia, nombre, pvp )
  • Tabla de clientes( Id, nombre, domicilio, telefono )
  • Tabla de cabecera de facturas ( Id, fecha, Id_cliente, iva )
  • Tabla de lineas de facturas ( Id_factura, linea, Id_articulo, cantidad, precio )

Comencemos por identificas las clases que van a constituir nuestro modelo de datos:

  • Clase TFamilia
  • Clase TArticulo
  • Clase TCliente
  • Clase TFactura
  • Clase TLineasFactura

Para el código de los ejemplos usaré xHarbour y Xailer. Todas las clases heredarán de una clase principal y abstracta llamanda TQuery, que es una clase que simula un datasource. La clase TQuery está programada por mí basándome el los wrappers que construyó Manu Expósito en Eagle 1 para acceder de forma nativa a MySQL. Creo que no existen problemas para poder heredar del sistema de datasource de cualquier otro producto. Quien lo desee puede contactarme para que le envíe el código fuente de TQuery.

Las primeras clases que vamos a definir son las relacionadas con las tablas maestras, empezando por las que no contienen referencias a claves foráneas de otras tablas, en nuestro caso, las clases TFamilia y TCliente.

CLASS TFamilia FROM Tquery

DATA cConsulta

METHOD Init( cQuery )

METHOD Delete( nId_Familia )

END CLASS

METHOD Init( cQuery ) CLASS TFamilia

DEFAULT cQuery TO “SELECT * FROM famila”

::New()

::cConsulta := cQuery

::Query( ::cConsulta )

RETURN Self

METHOD Delete( nId_Familia ) CLASS TFamilia

IF !Empty( nId_Familia )

::Command( “DELETE FROM familia “ + ;

“WHERE id = “ + Str( nId_Familia ) + “ “ + ;

“LIMIT 1” )

END IF

RETURN Nil

//——————————————————————//

CLASS TCliente FROM Tquery

DATA cConsulta

METHOD Init( cQuery )

METHOD Delete( nId_Cliente )

END CLASS

METHOD Init( cQuery ) CLASS TCliente

DEFAULT cQuery TO “SELECT * FROM cliente”

::New()

::cConsulta := cQuery

::Query( ::cConsulta )

RETURN Self

METHOD Delete( nId_Cliente ) CLASS TCliente

IF !Empty( nId_Cliente)

::Command( “DELETE FROM cliente “ + ;

“WHERE id = “ + Str( nId_Cliente ) + “ “ + ;

“LIMIT 1” )

END IF

RETURN Nil

//——————————————————————//

Constituiremos ahora la clase para controlar la tabla de artículos, que como podemos observar, contiene una clave foránea a la tabla de familias (Id_familia); por lo tanto, desde nuestro modelo de datos, un objeto oArtículo de la clase TArtículo tendrá que poder acceder a los datos de la familia de cada artículo, facilitando posteriormente las labores de programación de nuestra aplicación.

CLASS TArticulo FROM TQuery

DATA cConsulta

DATA oFam

METHOD Init( cQuery )

METHOD Delete( nId_Articulo )

METHOD Change( oSender )

ACCESS oFamilia

END CLASS

METHOD Init( cQuery ) CLASS TArticulo

DEFAULT cQuery TO “SELECT * FROM articulo”

::New()

::OnChange := { | oSender | Change( oSender ) }

::cConsulta := cQuery

::Query( ::cConsulta )

RETURN Self

METHOD Delete( nId_Articulo ) CLASS TArticulo

IF !Empty( nId_Articulo)

::Command( “DELETE FROM articulo “ + ;

“WHERE id = “ + Str( nId_Articulo ) + “ “ + ;

“LIMIT 1” )

::Change()

END IF

RETURN Nil

METHOD Change( oSender ) CLASS TArticulo

::oFam := NIL

RETURN Nil

METHOD oFamilia CLASS TArticulo

IF Empty( ::oFam )

::oFam := Tfamilia():Init( “SELECT * FROM familia “ + ;

“WHERE id = “ + Str( ::Id_Familia ) )

END IF

RETURN ::oFam

Vamos a detenernos un instante a estudiar que tienen estas clases dentro. De forma general, todas las clases llevan una DATA que contiene la consulta efectuada (cConsulta) y los MÉTODOS Init() y Delete().

El método Init() es el encargado de construir y retornar el objeto correspondiente. En su interior nos encontramos instrucciones que, a parte de establecer un valor por defecto para la consulta, también realizan:

  1. Llamar al método New() de la superclase para la construcción del objeto.

  2. Llamar al método Query() de la superclase para ejecutar la consulta y cargar los datos correspondientes.

El método Delete() es el encargado de eliminar una fila de la tabla correspondiente. En caso de usar bases de datos SQL recomiendo tener bien definida la integridad referencial. En otro tipo de almacenes de datos, en este método habrá que incluir el código necesario para eliminar información de las tablas que contengan información de la fila que estamos eliminando.

Estudiando la clase TArticulo podemos observar algunas diferencias muy significativas: aparece una DATA aFam, el método Change() y el método especial ACCESS oFamilia.

Mediante la palabra reservasa ACCESS de xHarbour se define un método especial que se comportará como una DATA y que además ejecuta su código cada vez que se instancia.

La DATA oFam contendrá un objeto de la clase TFamilia descrita anteriormente.

El método Change() se ejecutará cada vez que dispare el evento OnChange() de la clase TQuery. Este evento responde cada vez que se produce un cambio al añadir, actualizar, borrar, navegar o recargar datos de la consulta. Este método pone a NIL la data oFam para controlar un tipo de recursividad que veremos más adelante.

El método ACCESS oFamilia se ejecutará cada vez que accedamos a él, ejecutando la consulta que carga los datos de la familia relacionada con el artículo actual. Para evitar la recursividad y que se ejecuten consultas constantes (perdida de velocidad :-(), miramos si está vacío.

Con lo visto hasta este momento creo que ya habréis podido adivinar que el modelo de datos perimite acceder de forma automática a los datos de tablas relacionadas sin necesidad de escribir código adicional. Comparemos:

  1. Forma tradicional sin modelo de datos:

oArticulo := TQuery():New( “SELECT * FROM articulo” )

WHILE !oArticulo:Eof()

oFamilia := Tquery():New( “SELECT * FROM familia “ + ;

“WHERE id = “ + Str( oArticulo:Id_Familia ) )

MsgInfo( oFamilia:Nombre )

oArticulo:Skip()

END DO

  1. Usando el modelo de datos:

oArticulo := TArticulo():New( “SELECT * FROM articulo” )

WHILE !oArticulo:Eof()

MsgInfo( oArticulo:oFamilia:Nombre )

oArticulo:Skip()

END DO

Es obvio que usando un modelo de datos conseguimos claridad y automatización en la mayoría de los procesos que tenemos que realizar dentro de nuestros programas.

En la segunda parte de este artículo veremos como se automatiza la clase Tfactura.

Tags: , , , , ,

6 Responses to “Introducción al Modelo de Datos (I)”

  1. Rafa Carmona Says:

    Gracias por el aporte Jose A.!

  2. admin Says:

    Hola Rafa,

    Espero te haya gustado, que se que a tí te gustan estas cosas.

    Si me da tiempo prepararlo, espero publicar la segunda parte este fin de semana.

    Saludos,

    Alf+.

  3. Manolo Says:

    Hola Jose Alfonso,

    Saludos desde Cádiz. Espero que te vaya bien por tu cuenta y que tpvsoft siga funcionando como mereces.

  4. Manu Says:

    Jose…
    Muy bueno, espero las siguientes entregas con auténtica ansiedad…

    Saludos

  5. Claudio Says:

    Interesante artículo. Hace poco que estoy en Xailer y me interesaría leer la clase TQuery que comentás. Si pudieses hacermela conocer estaría muy agradecido.

  6. Jose Antonio Albarracin Says:

    Me encontre con tu archiculo de MVC y me parecio muy interesante yo actualmente trabajo con oohg + harbour y al igual que todos estoy interasado en que me facilites el codigo de la clase TQuery para poner en practica el modelo MVC. Te antemano de agradezco tu colaboracion y ayuda.

Leave a Reply