2009-12-28 23 views
20

Casi he terminado mi Data Mapper, pero ahora estoy en el punto de las relaciones.Data Mapper and Relationships: Estrategias de implementación?

Trataré de ilustrar mis ideas aquí. No pude encontrar buenos artículos/información sobre este tema, así que tal vez estoy reinventando la rueda (estoy seguro, podría usar un gran marco, pero quiero aprender haciéndolo).

1: 1 Relaciones

En primer lugar, veamos 1: 1 relaciones. En general, cuando tenemos una clase de dominio llamada "Compañía" y otra llamada "Dirección", nuestra clase Compañía tendrá algo como id_dirección. Digamos que en la mayoría de los casos solo mostramos una lista de compañías, y la dirección solo es necesaria cuando alguien mira los detalles. En ese caso, mi Data Mapper (CompanyDataMapper) simplemente se carga de forma perezosa, lo que significa que solo obtendrá ese id_dirección de la base de datos, pero no se unirá para obtener también los datos de la dirección.

En general, tengo un método getter para cada relación. Entonces, en este caso, hay un método getAddress (Company companyObject). Toma un objeto de compañía, busca su propiedad de dirección y, si es NULL, obtiene el objeto Address correspondiente de la base de datos, utilizando la clase Mapper para ese objeto Address (AddressDataMapper) y asigna ese objeto de dirección a la propiedad de dirección de la especificada objeto de la empresa

Importante: ¿Se permite a un Data Mapper utilizar otro Data Mapper?

Digamos que en la mayoría de los casos necesita el objeto de la empresa Y el objeto de la dirección, porque siempre lo muestra en una lista todos juntos. En este caso, CompanyDataMapper no solo obtiene objetos de la compañía, sino que realiza una consulta SQL con JOIN para obtener también todos los campos del objeto de dirección. Finalmente, itera sobre el conjunto de registros y alimenta nuevos objetos con sus valores correspondientes, asignando el objeto de dirección al objeto de la compañía.

Sonidos simples, hasta ahora.

1: n Relaciones

¿Qué hay de estos? La única diferencia para 1: 1 es que una empresa puede tener múltiples objetos de dirección. Echemos un vistazo: cuando la mayoría de las veces solo nos interesa la compañía, Data Mapper simplemente establece las direcciones propiedad del objeto de la compañía en NULL. La propiedad de direcciones es una matriz que puede hacer referencia a ninguna, una o varias direcciones. Pero aún no lo sabemos, ya que cargamos perezosamente, por lo que solo es NULL. ¿Pero qué, si necesitaríamos todas las direcciones en la mayoría de los casos también? ¿Si mostramos una gran lista con todas las empresas junto con todas sus direcciones? En este caso, las cosas empiezan a ponerse realmente feas. En primer lugar, no podemos unirnos a la tabla de direcciones cincuenta veces para cada objeto de dirección (creo firmemente que es imposible, y si lo es, el rendimiento sería inferior a cero). Entonces, cuando pensamos esto más adelante en el camino, es imposible NO cargarlo perezosamente en este caso.

Importante: ¿Es esto cierto? ¿Debo enviar 100 consultas para obtener 100 objetos de dirección, si tengo 10 empresas con cada 10 direcciones?

m: n Relaciones

permite decir un objeto de dirección sólo contiene el número del país, estado, ciudad, carretera y casa. Pero una casa podría ser una gran torre de negocios con muchas compañías en ellas.Como uno de esos modernos edificios de oficinas donde cualquiera puede alquilar una pequeña rom para exhibir esa torre en su sitio web. Entonces: muchas compañías pueden compartir la misma dirección.

No tengo planes para lidiar con ese tipo de problema.

Importante: ¿Probablemente no es un problema mayor que las relaciones 1: n?

Si alguien conoce un buen recurso que entra en detalles sobre cómo resolverlo/implementarlo, ¡me alegrará un enlace!

Respuesta

3

estoy deseando que cualquier respuesta que obtendrá sobre este tema, pero mientras tanto ¿por qué no saltar encima a Amazon (o sus libros locales distribuidor) y finalmente compro

Estos libros contienen los patrones originales que se han señalado en varias de sus preguntas y se consideran obras de referencia en Patrones de diseño y Arquitectura de software.

0

Yo también estoy trabajando en este tema. Para empezar, he adaptado el patrón Data Mapper de Matt Zandstra Objetos PHP, Patrones y Práctica (2d Ed). Veo ahora que ha salido un new edition

Quizás la parte más ingeniosa de la configuración son los objetos de "Colecciones". No estoy seguro de qué idioma está usando, así que le ahorraré los detalles. Baste decir que PHP tiene una interfaz Iterator que hace posible cargar una matriz (mapa, en otros idiomas) al principio y transformar los datos sin procesar en objetos (¿hidratar?) Sobre la marcha, mientras se repite.

Al igual que usted, estoy luchando con la forma de cargar las relaciones. Lo que he encontrado hasta ahora es que puedo escribir mi masiva consulta JOIN en la clase Mapper y crear una colección deshidratada para el objeto objetivo y colar los datos en los objetos relacionados al mismo tiempo.

Realmente no me gusta "Lazy Load" porque me lleva a tantas consultas en la base de datos. Ofender mis sensibilidades perfeccionistas es saber que estoy usando decenas o cientos de consultas para lograr lo que se podría hacer en una.

Yo también estoy esperando más respuestas.

16

Antes de comenzar, asumo que has leído el libro PoEAA de Fowler de principio a fin. =) Además, consideraré que ya pensó en los primeros problemas iniciales que enfrenta al tratar con ORM. Puedo resaltar uno fácil, como llamar a un DataMapper varias veces usando el mismo identificador y devolver siempre el mismo objeto (leer como IdentityMap).

Importante: ¿Se permite a un Data Mapper utilizar otro Data Mapper?

Solo es posible tener un DataMapper accediendo a otro si el segundo es una referencia débil en el segundo.

permite decir en la mayoría de casos, es necesario tanto el objeto social y el objeto de dirección, porque siempre lo mostrará en una lista todos juntos. En este caso, CompanyDataMapper no solo obtiene objetos de la compañía, sino que realiza una consulta SQL con JOIN para obtener también todos los campos del objeto de dirección. Finalmente, itera sobre el conjunto de registros y alimenta nuevos objetos con sus valores correspondientes, asignando el objeto de dirección al objeto de la compañía.

El problema que está tratando de analizar aquí suena simple en la práctica, pero es un poco complejo detrás de la escena.

En primer lugar, no debe tener una getAddress (Compañía), sino beneficiarse de tener objetos Proxy. Un proxy es una representación no inicializada de una instancia determinada. En este caso, un Proxy contiene una referencia a la entrada que está buscando. Debe extenderse desde su objeto original y necesita proporcionar un método de inicialización, junto con un DataMapper relacionado para cargarlo.

La segunda parte sobre UNIRSE y cargar múltiples objetos a la vez se denomina Hidrador. Hydrators recibe una estructura plana de líneas y columnas y se convierte en un gráfico de objetos. Pero realmente entra en un tema aparte: si solo estás lidiando con objetos, ¿por qué estás buscando tablas? Intentar llevar a cabo un enfoque de búsqueda de objetos lo llevaría a implementar una especie de OQL (lenguaje de consulta de objetos).

Importante: ¿Es esto cierto? ¿Debo enviar 100 consultas para obtener 100 objetos de dirección, si tengo 10 empresas con cada 10 direcciones?

Lidiar con una colección de objetos es una pesadilla en PHP. Sí, el lenguaje apesta mucho por la falta de una implementación poderosa de la colección. Básicamente, está obligado a tratar diferentes situaciones aquí: - nueva instancia y todos los elementos en esta lista de elementos son nuevos - nueva instancia y todos los elementos en esta lista de elementos son preexistentes - nueva instancia y elementos en este lista de elementos se mezclan entre lo nuevo y pre-existente - instancia preexistente y no tocar nada en la lista de elementos - instancia preexistente y la manipulación de elementos de la lista

estoy siendo muy simplista aquí, pero el punto principal que quiero destacar es la necesidad de un objeto Collection. Hay dos de ellos: uno que trata con listas nuevas y otro que trata con listas existentes. El que se ocupa de las listas existentes debe poder cargar la colección una vez que intente acceder a cualquier elemento dentro de ella. Esa es la única forma de no tener n + 1 problemas.

Aquí también se destaca el próximo gran problema que tendría que tratar. Las asociaciones pueden ser unidireccionales o bidireccionales. Esto significa que la Empresa conoce la Dirección pero la Dirección no tiene idea de que la Compañía es unidireccional, mientras que un Usuario es parte de muchos Grupos y Grupos contiene muchos Usuarios es una asociación bidireccional. Las cosas fácilmente se convierten en una pesadilla aquí y es por eso que necesita patrones de mapeo para comprender adecuadamente lo que está pasando.

Trabajar con muchos-a-muchos es lo mismo que tratar con colecciones en general.

Hay una parte importante que no ha considerado todavía. Si construyo todo el gráfico de objetos (Compañía y Dirección) y decido persistirlos ... ¿necesita persistir ambos o debo decir qué deseo persistir? Ambas formas tienen diferentes conjuntos de problemas. Supongamos que quiere el primer enfoque.Acaba de ingresar en lo que considero uno de los patrones de diseño más complejos para implementar: UnitOfWork. Luego, tendría que ocuparse de ordenar el orden de las entidades que se aplicarán para que no generen problemas de restricción (lea Clasificación topológica sobre cómo resolver esto). Si toma el segundo enfoque, puede ingresar fácilmente en una situación en la que siente que su herramienta está rota, principalmente porque es muy fácil tener su gráfico de objetos en un estado incoherente.

Finalmente ... ¿planea hacer ALGÚN apoyo para la herencia? Si es positivo, toda su planificación acaba de entrar en un nivel completamente nuevo. = (Intentar explicarme me llevaría un libro. Pero puedo señalar algunos patrones de diseño que puede ver: Herencia de tabla concreta (1 clase, 1 tabla), herencia de tabla única (N clases, 1 tabla) y herencia de tabla de clase (N .. clases, mesas M)

puedo ir a fondo en muchos puntos distintos, aunque la ORMs normalmente conduce a la cabeza explota voy a parar por ahora

PS:. soy uno de los desarrolladores del núcleo de Doctrine ORM. A menos que esté haciendo esto con fines de estudio, no se moleste en tratar de crear otro. Es extremadamente complejo, requiere mucho tiempo y exige mucha y mucha planificación sobre cómo funcionarían las cosas incluso antes de codificar el primero línea De hecho, planificamos Doctrine ORM durante 2 años y tardamos 1 año en implementar re Liably la funcionalidad central. No te estoy desanimando, pero como dijo Fowler en su artículo ORM de odio, es una solución compleja para un problema incluso complejo.

Cuestiones relacionadas