2011-08-08 11 views
25

Siempre he trabajado con varios ORM y colocé toda mi lógica dentro de mis modelos independientemente de su naturaleza: SQL, consultas de MongoDB & incluso la obtención de objetos JSON remotos. Pero cuando es necesario garantizar acoplamientos sueltos para permitir un alto nivel de capacidad de prueba, los problemas de esta metodología aparecen rápidamente.¿Entender el objeto Dominio + el patrón del mapeador de datos?

Hoy he leído sobre la separación de modelos en dos partes, Domain objects & Data mappers.
Si lo entendí completamente, Domain objects son completamente inconscientes del almacenamiento utilizado, y en cambio existe para manejar la lógica de negocios. Data mappers por otro lado se encarga de almacenar el conjunto de datos en el Domain objects a un conjunto de almacenamiento de datos.

Sin embargo, me resulta un poco difícil encontrar un buen ejemplo fácil de entender en línea sobre cómo trabajar con los DomainObjects & DataMappers en un ejemplo del mundo real.

¿Sería esto (el código que se muestra a continuación) la forma adecuada de trabajar con DomainObjects & DataMappers en mi código para almacenar Usuarios o lo he entendido mal en mi cabeza?

$user = new User_DO; 
$userSave = new User_DM; 
$userSave->store($user->add(array('name' => 'John Doe'))); 

class User_DO { 

    function add($array) { 
     if(!isset($array['name'])) { 
      throw new Exception("Name must be set"); 
     } 

     return $array; 

    } 

} 

class User_DM { 

    function store($array) { 
     MyDatabase::execute("INSERT INTO..."); 
    } 

} 
+0

un ejemplo quizás estúpido en el mundo real, pero que puede explicar mejor el patrón, sería un objeto de dominio con un campo "edad", mientras que el mapeador de datos persistirá el valor de "año de nacimiento". –

Respuesta

24

La idea detrás de esto es tener un objeto estándar, que representa el estado actual en la vida real o en otras palabras, en el dominio. Este modelo de dominio suele ser una colección de datos sin lógica.

class person_DO { 
    public $id; 
    public $firstname; 
    public $lastname; 
    public $addresses; 
} 

La carga de instancias de este modelo de dominio (objetos dominio) y la persistencia se maneja a través mapeadores de datos - por ejemplo, la dirección de la persona anterior podría estar ubicado en otra mesa a través de una relación 1: n, como por ejemplo:

TABLE person { 
    id  INTEGER PRIMARY KEY, 
    firstname VARCHAR(32), 
    lastname VARCHAR(32) 
} 

TABLE addresses { 
    id INTEGER PRIMARY KEY, 
    person_id INTEGER FOREIGN KEY ON person.id, --Reference on person-row 
    street  VARCHAR(64), 
    ... 
} 

El person_DO no necesita saber acerca de eso, pero el DataMapper hace, ya que tiene que agregar el datos durante la carga y separado durante la persistencia de:

class person_DM { 
    /** 
    * @param [integer] $id 
    * @return [person_DO] an instance of a person or null, if no person 
    *      with that id was found. 
    */ 
    public function findById ($id) {...} 

    /** 
    * @return [array of person_DO] 
    */ 
    public function fetchAll() {...} 

    /** 
    * persists a person object 
    * @param [person_DO] an instance of a person 
    */ 
    public function saveOrUpdate(person_DO $person) {...} 
} 

con el fin de desacoplar las diferentes partes aún más, los DataMappers suelen utilizar la DbTable puerta de enlace o un patrón similar para permitir el uso de diferentes bases de datos o acciones similares. De esta forma, puedo tener varias bases de datos con los mismos esquemas, pero p. en diferentes organizaciones para construir un almacén de datos con el mismo código, solo diferentes objetos de base de datos.

Como ejemplo práctico, sugeriría mirar el Quickstart Tutorial del Zend Framework, que hace exactamente lo que acabo de explicar brevemente.

+0

¿Cómo manejaría un asignador un dominio que tiene relaciones bilaterales de muchos a muchos? Diga si esa persona_DO tiene muchas direcciones_DOs o algo. Si quisiera cambiar las direcciones que tiene la persona, ¿la cambiaría en el dominio y luego la dejaría en manos del mapeador para persistir en las nuevas relaciones que tiene la persona_DO? o ¿usaría el asignador para cambiar los registros de la base de datos que a su vez actualizarían el dominio ...? – user965369

+1

"Este modelo de dominio suele ser una recopilación de datos sin lógica". No creo que esa declaración sea necesariamente precisa. Sus objetos de dominio deben representar estado + comportamiento (lógica comercial). Lo que no quieres que hagan es incluir lógica de persistencia. – AgmLauncher

+2

"Este modelo de dominio generalmente es una colección de datos sin lógica.". Eso no es exacto en absoluto. Ese es un modelo anémico y una pobreza menor, tu lógica de dominio DEBERÍA estar dentro de tus objetos de dominio, eso es una simple encapsulación. – Andrew

8

La forma aproximada, sí. Aunque recomiendo encarecidamente no reinventar la rueda y usar un ORM sofisticado como Doctrine 2.x que implemente dicho patrón. Puede echar un vistazo a su documentación (Chapter 8: Working with objects) para muestrear la interfaz.

Cuestiones relacionadas