8

He estado leyendo en múltiples frameworks PHP, especialmente Zend Framework, pero me confundo la forma correcta de seguir adelante.¿El patrón DataMapper rompe MVC?

Zend Framework no usa ActiveRecords, sino que utiliza el patrón Table Data Gateway y Row Data Gateway, y utiliza un DataMapper para asignar los contenidos de Row Data Gateway al modelo, porque ActiveRecord se rompe cuando sus modelos no lo hacen tener una asignación de 1: 1 a sus tablas de base de datos. Hay un example of this en la guía Zend Quickstart.

Para mí, su ejemplo se ve muy hinchado con una tonelada de getters y setters en todo el lugar. Me encontré con varias publicaciones de blog sobre Domain Driven Design argumentando que el uso de tantos getters y setters es una mala práctica porque expone todos los datos del modelo interno al exterior, por lo que no tiene ninguna ventaja sobre los atributos públicos. Here is one example.

Mi pregunta: Si elimina esos getters y setters, ¿cómo representará sus puntos de vista? En algún punto, los datos tienen que golpear la vista para que pueda mostrarle algo al usuario. Seguir los consejos de DDD parece romper la separación entre M y V en MVC. Seguir el ejemplo de MVC y Zend parece romper DDD y me deja escribiendo un montón de getters, setters y DataMappers para todos mis modelos. Además de ser mucho trabajo, también parece violar DRY.

Realmente apreciaría algunos (enlaces a) buenos ejemplos o más información sobre cómo encaja todo. Estoy tratando de mejorar mis habilidades de arquitectura y diseño aquí.

Respuesta

2

Utilizando Value Objects, puede eliminar algunos de esos métodos de establecimiento público. Aquí hay una descripción de the difference between Entity and Value Objects. Los objetos de valor son inmutables y, a menudo, están vinculados a una entidad. Si pasa todos los valores con el constructor, no necesita establecer estas propiedades desde el código externo.

algo extra, que no están directamente relacionados con una respuesta, pero más centrado en DDD:

(exención de responsabilidad: La única cosa que sé sobre el Zend Framework es lo que leo en el artículo enlazado.) Zend Framework está utilizando DataMappers en lugar de Repositorios. ¿Es esto realmente DDD-ish? Bueno, Fowler's interpretation of a Repository podría decir que no. Sin embargo, Eric Evans afirma que un repositorio DDD puede ser muy simple. En su forma más simple, un Repositorio es un DataMapper (Ver libro DDD). Para algo más complejo y aún DDD, vea el artículo de Fowler. DDD tiene un Repositorio conceptual que puede diferir de la definición del patrón.

Le insto a que continúe leyendo sobre el diseño controlado por el dominio. Creo que hay un error en la suposición de que los getters y setters violan DDD. DDD se trata de enfocarse en el modelo de dominio y las mejores prácticas para lograr eso. Los accesorios son solo un detalle menor.

+0

Gracias. Ese artículo de Devlicious hace una buena lectura. Voy a leer el resto de la serie también. –

+0

Esta es una buena respuesta y agregaría que no está mal con getters, setters. De hecho, tenerlos es una forma excelente de agregar lógica de validación. Hacer públicas las propiedades es rápido y sucio, y está bien al crear prototipos, pero no es una gran solución a largo plazo. Supongamos que quiere cambiar el nombre de una propiedad. Si hace esto, cada pieza de código que accede a esa propiedad debe cambiar. Si usa un nombre genérico para el método de acceso, no tiene que cambiar el código de cliente. Además, Doctrine es una solución mucho más rica que Zend DB. No recomendaría Doctrine1, pero prueba Doctrine2. –

2

No necesita implementar todos los getters/setters, puede usar__get() y __set(). ¿Cuál es el problema entonces?

1

Desde mi lectura de la publicación, la pregunta es más filosófica que práctica.

No tengo tiempo para escribir en profundidad, pero aquí está mi granito de arena. Aunque estoy de acuerdo con que desea limitar el número de solicitudes de obtención y configuración porque una clase debe ocultar sus elementos internos, también debe tener en cuenta que Java y PHP son herramientas diferentes y tienen diferentes propósitos. En el entorno web, las clases se crean y eliminan con cada solicitud y, por lo tanto, el código que se escribe no debe depender de grandes clases. En el artículo que señaló el autor sugiere colocar la lógica de vista en la clase. Probablemente esto no tenga sentido en la web, ya que probablemente quiera presentar la vista en múltiples formatos (rss, html, etc.). El uso de métodos de acceso (obtener & conjunto) por lo tanto es un mal necesario. Aún desea usarlos con cuidado para no dispararse en el pie. La clave es intentar que tus clases hagan el trabajo por ti en lugar de tratar de obligarlos a trabajar externamente. Al acceder a sus propiedades con un método en lugar de directamente usted oculta las partes internas que es lo que quiere.

De nuevo, esta publicación podría usar algunos ejemplos, pero no tengo el tiempo ahora.

¿Alguien más puede dar algunos ejemplos de por qué los métodos de acceso no son malos?

+0

Gracias. Mi pregunta es de hecho más filosófica que práctica. Poner lógica de vista en el modelo de dominio me pareció problemático (ya que viola MVC) y eso fue lo que provocó la pregunta. Lo que realmente espero ver son algunos ejemplos prácticos que muestran claramente la teoría en acción. Si de hecho es un equilibrio entre Domain Driven Design y MVC, me encantaría ver cómo otras personas resuelven el aparente conflicto entre ellos. –

0

La implementación de captadores y definidores tiene dos ventajas, en los ojos:

  1. Puede elegir qué propiedades para hacer pública, por lo que no necesariamente tiene que exponer todas las partes internas del modelo
  2. Si use un IDE con autocompletar, todas las propiedades disponibles serán una TAB lejos cuando comience a escribir "get" o "set"; esto solo es motivo suficiente para mí.
1

Aquí hay dos enfoques: lo que llamo el "enfoque de no preguntar" y el otro es el enfoque de ViewModel/DTO. Esencialmente, las preguntas giran en torno a lo que es el "modelo" en su opinión. Decir no preguntar requiere que la única forma en que se puede externalizar un objeto sea desde el objeto mismo. En otras palabras, para representar un objeto, tendrías un método de renderizado, pero ese método de renderización necesitaría hablar con una interfaz. Algo como esto:

class DomainObject { 
    .... 
    public function render(DomainObjectRenderer $renderer) { 
     return $renderer->renderDomainObject(array $thegorydetails); 
    } 
} 

En el contexto de Zend Framework, puede subclase Zend_View y tener su subclase implementar esta interfaz.

He hecho esto antes, pero es un poco difícil de manejar.

La segunda opción es convertir su modelo de dominio en un objeto ViewModel, que es como una vista simplificada, achatada, "encuadernada" de sus datos, personalizada para cada vista específica (con un ViewModel por vista), y en el camino de regreso, convierta los datos POST a un modelo de edición.

Este es un patrón muy popular en el mundo ASP.NET MVC, pero también es similar al patrón de clase "DTO" utilizado para transferir datos entre "capas" en una aplicación. Tendría que crear mapeadores para hacer el trabajo sucio para usted (no muy diferente a un DataMapper, en realidad). En PHP 5.3, puedes usar el reflejo para cambiar las propiedades privadas, ¡así que tu DomainObject ni siquiera necesita exponerse!

Cuestiones relacionadas