Mapeo objeto-relacional

En el software orientado a objetos, la información se representa como clases y objetos. En las bases de datos relacionales, como tablas y sus restricciones. Por tanto, para almacenar la información tratada en un programa orientado a objetos en una base de datos relacional es necesaria una traducción entre ambas formas.

Una aproximación ampliamente usada es el mapeo objeto-relacional (ORM). Tanto en la forma de Table gateway como de Table-row gateway, se hace una correspondencia entre los siguientes elementos:

Programa OOBD relacional
ClaseTabla
PropiedadCampo
ObjetoFila
IdentificadorClave primaria
Puntero a otro objetoClave foránea

Esta correspondencia es muy "natural" ya que, en realidad el modelo orientado a objetos y el modelo relacional no son tan diferentes. Veámoslo: en los programas las instancias de un objeto son accedidas a través de un puntero a su posición de memoria. Por ejemplo:

$a = new A;
$b = $a;

En la ejecución del código anterior se realizan las siguientes acciones:

  1. Se instancia la clase A, es decir, se almacena en memoria el registro correspondiente al TDA representado en la clase A (Línea 1)
  2. Se crea una variable tipo puntero llamada $a que apunta al registro anterior (Línea 1)
  3. Se crea otra variable ($b) de tipo puntero que toma el mismo valor que $a, es decir, al registro creado en #1 (Línea 2)

Conceptualmente, podemos decir que el registro en memoria es propiamente el estado del objeto y su posición, indicada en $a, un identificador único del mismo. Y recordemos que los objetos anidados (es decir, las propiedades de $a que sean, a su vez, otros objetos) se almacenarán en el registro como punteros a otros registros.

Esta forma de almacenar información a bajo nivel —manejada comúnmente en el lenguaje C— se asemeja al modelo de las tablas y las relaciones de las bases de datos relacionales: cada registro es una fila, cada puntero una referencia foreign key. Las posiciones en memoria, es decir, los "identificadores únicos" de los objetos podríamos tratarlos como primary keys.

Pero si es tan sencilla la traducción objeto-relacional, ¿por qué la industria sigue usando DAO o sentencias agnósticas? Cuatro principales motivos:

  1. Aunque hemos explicado la estructura de los objetos en los programas, no es directamente como nuestros programas los tratan. Por ejemplo, si tenemos un objeto Libro con las propiedades título, ISBN, y autor, los lenguajes (y más concretamente PHP) no nos permiten acceder a todas las propiedades del objeto de una forma directa, sino a través de reflexión (y hasta la versión 3.5 de PHP no podíamos acceder a las propiedades privadas).
  2. Para cada clase que queramos almacenar se ha de crear un esquema de tablas y relaciones en la base de datos, algo que ya es costoso de por sí. Además, por seguridad, es bueno comprobar la validez de dichos esquemas. Por tanto, el rendimiento se reduce.
  3. PHP es un lenguaje de tipado débil, al contrario que los esquemas de bases de datos (en los cuales incluso se especifica la longitud del registro). Al declarar una propiedad en una clase no se declara el tipo, por lo que no hay modo de conocerlo a priori.
  4. PHP es un lenguaje de tipado dinámico; no así las bases de datos, que por definición tienen esquemas fijos. Por ello, si una propiedad es añadida en tiempo de ejecución no puede ser almacenada en una tabla con campos fijos. Por ejemplo:
    class A {
    	public $foo;
    }
    
    $a = new A;
    $a->bar = true;

    Además, el tipo de cualquier propiedad, declarada o dinámica, puede ser modificado en tiempo de ejecución:

    class A {
    	//Dándole un valor por defecto a la propiedad, declaramos su tipo
    	public $foo = "valor"; 
    }
    
    $a = new A;
    $a->foo = 3.14;

Estos problemas nos llevan a pensar que, además de la traducción objeto-relacional, PHP presenta un problema añadido de representación de la información, y es que las estructuras de orientación a objetos no son suficientes para definir la información de forma tan concreta como necesitan las bases de datos relacionales. Ante este problema, las soluciones existentes son las siguientes: