php - programacion - ¿Cómo manejar la comunicación entre el dominio y las capas de la base de datos?
manual de programacion android pdf (4)
Soy bastante nuevo en el uso de capas separadas para la lógica de negocios (Dominio) y la lógica de acceso a la base de datos, pero en el transcurso de las cosas, me he encontrado con un problema que todavía siento que no he encontrado una gran solución.
Aclaración. Mi solución existente usa Data Mappers para tratar las interacciones de la base de datos directamente. Sin embargo, a medida que investigué este problema, muchas personas sugirieron que la capa de Dominio no debería comunicarse directamente ni contener los Data Mappers que realmente realizan la interacción de la base de datos. Es por eso que coloqué los objetos del Repositorio entre el Dominio y los Data Mappers necesarios, pero esto no parece muy natural ni correcto. Entonces, la verdadera pregunta es ¿qué capa existe naturalmente para manejar la comunicación entre el Dominio y los Data Mappers? Cualquier ejemplo de cómo estructurarlo sería apreciado.
Por ejemplo:
- ¿Cómo manejo adecuadamente la recuperación de una colección de objetos de dominio dentro del contexto de otro objeto de dominio?
- ¿Cómo fuerzo la inserción de un único objeto de dominio o colección de objetos en función de una acción realizada contra otro objeto? El caso al que me estoy enfrentando actualmente es que cuando una persona está vinculada a una campaña, entonces necesito insertar todos los eventos que deben ejecutarse para esa persona para esa campaña.
Gabriel, esto se llama el " problema de adaptación de la impedancia ". Existen muchas soluciones, desde pesadas como beans de entidad J2EE hasta Ruby ActiveRecord, simplemente codificando una conexión manual.
Actualizar
De acuerdo, bueno, es difícil ver exactamente cómo atacar esto sin mucha más información, pero aquí está el enfoque básico.
Cualquiera de estos tipos de problemas arquitectónicos están impulsados por requisitos no funcionales como el rendimiento; Además, hay un problema de corrección aquí, en el que desea asegurarse de que las actualizaciones se realicen en el orden correcto. Por lo tanto, tendrá que pensar en la carga de trabajo , es decir, el patrón de uso en la aplicación del mundo real. Con eso en mente, básicamente tiene un par de problemas: primero, los tipos de datos básicos en su aplicación pueden no corresponderse correctamente con la base de datos (por ejemplo, ¿qué representa una propiedad VARCHAR como en su código?), Y en segundo lugar su modelo de dominio no puede mapear limpiamente a su modelo de base de datos.
Lo que desea es que la base de datos y el modelo dmain funcionen para que una instancia de un objeto de dominio sea exactamente una fila de una tabla en su modelo de base de datos; en aplicaciones a gran escala, rara vez se puede hacer esto debido a limitaciones de rendimiento o restricciones impuestas por un modelo de base de datos preexistente.
Ahora, si controla completamente su modelo de base de datos, simplifica un poco las cosas, porque entonces puede hacer que su modelo de base de datos se parezca más al dominio. Esto podría significar que el modelo de la base de datos está algo desnormalizado, pero si es así, puede (dependiendo de su base de datos) manejarlo con vistas, o simplemente no tener una base de datos completamente normalizada. La normalización es una construcción teórica útil, pero eso no significa que no puedas relajarla en un sistema real.
Si no controla completamente su modelo de base de datos, entonces necesita una capa de objetos que haga la asignación. Tiene muchas opciones para elegir al implementar eso: puede construir vistas o tablas desnormalizadas en la base de datos, puede construir objetos intermedios, o puede hacer algunas de ambas, o incluso puede tener varios pasos de ambas (es decir, un objeto intermedio que accede a una tabla desnormalizada).
En ese punto, sin embargo, te encuentras con problemas con "no te repites" y "haz lo más simple que posiblemente funcione". Piensa en lo que es más probable que cambie? ¿Tu modelo de dominio? Si tiene un modelo de dominio sólido, es menos probable, el negocio cambia con relativa poca frecuencia. La representación exacta de los datos en la base de datos? Un poco mas comun O, más comúnmente, los patrones de uso exactos (como descubrir la necesidad de manejar actualizaciones concurrentes). Por lo tanto, cuando piense en eso, ¿qué debe hacer para que sea lo más fácil posible lidiar con los cambios más comunes?
Me doy cuenta de que esto no te da instrucciones muy precisas, pero no creo que podamos ofrecer instrucciones precisas sin saber mucho sobre tu aplicación. Pero también tengo la impresión de que te estás preguntando cuál sería la forma "correcta" de manejar esto, mientras que ya estás trabajando con algo que hace más o menos el trabajo. Entonces, terminaría preguntando "¿con qué estás descontento ahora?" y "¿Cómo te gustaría resolver eso?"
Me gustaría ver las capas de abstracción de datos utilizadas por PHPCake y Symfony.
Muchos sistemas emplean una capa de datos independiente para manejar la persistencia hacia y desde una base de datos. Hay varios modelos para la organización de dicha capa. Algunos usan una especie de implementación tipo fábrica, otros emplean un mapeo de uno a uno con una clase de capa de datos por clase de dominio.
El modelo para la capa de datos a menudo depende del estilo y la preferencia. Lo importante es separar la capa de persistencia de la capa de dominio. Creo que hay herramientas que te ayudarán a generar esta capa, pero mi conocimiento de PHP es escaso, así que no puedo nombrar ninguno específicamente para PHP.
Hay una distinción entre un modelo de dominio y su implementación. El hecho de que su modelo muestre una relación Person ---> Campaign ---> Event
no significa que tenga que implementarlo de esta manera. IOW, su modelo muestra su análisis y diseño de una manera orientada a objetos, sin embargo, implementa ese modelo en OOP que está limitado en qué tan bien puede replicar ese modelo en el código.
Considera lo siguiente.
Una Person
no se define por su propiedad de una Campaign
, por lo que la campaña puede quedar fuera de sus responsabilidades de conocimiento. Por otro lado, una Campaign
se define por los Event
que ocurren como parte de su ejecución, por lo que es justo tener una colección de eventos dentro de una campaña. El punto que estoy haciendo es que cada clase debe tener el comportamiento y el conocimiento suficiente para hacerlo completo.
En cuanto a la comunicación entre el dominio y las capas de persistencia, considérelas como dos sistemas muy distintos que no se ocupan del otro. Todo lo que cada uno sabe es cuáles son sus responsabilidades y qué anuncios hace. Por ejemplo, la capa de persistencia sabe cómo persistir los datos que se le pasan y anunciar que se han guardado los datos. Sin embargo, la capa de persistencia no necesariamente necesita comprender los objetos del dominio. Del mismo modo, la capa de dominio comprende Person
, Campaign
y Event
pero no sabe nada acerca de la persistencia.
La implicación de lo anterior es que la capa de dominio debe ser un todo en sí misma y no debe depender de la capa de persistencia para sus datos. Sin embargo, aún necesita recibir datos para cumplir con sus responsabilidades. Esa información puede provenir de la interfaz de usuario o de la base de datos y se le pasa a través de un tercero que conoce tanto el dominio como las capas de persistencia.
Entonces, en el código (pseudo-C #) ...
namespace DomainLayer
{
interface IDomainListener
{
void PersonCreated(Person person);
}
class Person
{
private string name;
public Person(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
}
}
class Domain
{
private IDomainListener listener;
public Domain(IDomainListener listener) {
this.listener = listener;
}
public void CreatePerson(string name) {
Person person = new Person(name);
listener.PersonCreated(person);
}
}
}
namespace PersistenceLayer
{
interface IPersistenceListener
{
void PersonDataSaved(int id, object data);
}
class Persistence
{
private IPersistenceListener listener;
public Persistence(IPersistenceListener listener)
{
this.listener = listener;
}
public void SaveData(object data)
{
int id = ...; // save data and return identifier
listener.DataSaved(id, data);
}
}
}
namespace MyApplication
{
class MyController : IDomainListener, IPersistenceListener
{
public void CreatePersonButton_Clicked()
{
Domain domain = new Domain(this);
domain.CreatePerson(NameTextbox.Text);
}
public void PersonCreated(Person person)
{
Persistence persistence = new Persistence(this);
persistence.SavePersonData(person.Name);
}
public void DataSaved(int id, object data)
{
// display data on UI
}
}
}
Como puede ver, los espacios de nombres representan los diferentes niveles. Las interfaces XYZListener
definen los anuncios que realiza el nivel XYZ
. Cualquier otro nivel que esté interesado en estos anuncios y que responda a ellos debe implementar estas interfaces, al igual que nuestro nivel MyApplication
.
Cuando se hace clic en el "botón Crear", el controlador crea el objeto de fachada Domain
para la capa de dominio y se registra a sí mismo como un oyente. Luego llama al método CreatePerson
que CreatePerson
una instancia de una Person
luego anuncia que esto se ha hecho, pasando la nueva instancia. El controlador responde a este anuncio en la implementación de PersonCreated
donde genera una fachada de la capa de persistencia y se registra como el oyente nuevamente. Luego llama al método SaveData que anuncia DataSaved
cuando se completa. La implementación de ese método luego muestra los datos en la interfaz de usuario.
Como puede ver, la capa de dominio y la capa de persistencia solo son conscientes de sí mismas y no se preocupan por las responsabilidades de la otra. Es la lógica de la aplicación, que se manifiesta aquí como el controlador, que los conecta entre sí.
Volviendo a su problema específico, podría tener un método FindPerson
en la persistencia, que anunciaría PersonFound(int id)
. La respuesta del controlador sería llamar a la capa de persistencia para recuperar datos sobre campañas y eventos, luego llamar a la capa de dominio con esos datos para compilar la Person
.
Perdón por la respuesta larga ...