2010-02-04 19 views
6

Tengo una aplicación MVC escrita con Zend Framework que extrae datos de una base de datos Oracle 10g y muestra estos datos en tablas y listas y enriquece visualmente estos datos a través de colores y gráficos. No hay ORM ni Create, Update o Delete involucrados, solo lectura pura. Los datos se insertan desde otra aplicación. Los datos en la base de datos se modelan según los conceptos que representan y a los que acceden las vistas de base de datos que agregan estos datos de otras tablas (heredado, no puede cambiar), p.¿Cómo modelarías esta aplicación?

| Event ID | Start    | End     | Status | Created_By | 
----------------------------------------------------------------------------- 
| 12345678 | 2009-10-01 12:00:00 | 2009-10-01 12:15:00 | booked | John Doe | 
| 12345679 | 2009-11-01 13:00:00 | 2009-12-01 12:00:00 | booked | John Doe | 
| 12345680 | 2009-11-01 13:00:00 | 2009-12-01 12:00:00 | tba | Jane Doe | 

Los usuarios pueden influir en la visualización de la columna, ordenando y ordenando desde la Vista. Los clientes pueden denegar/permitir el acceso a columnas y limitar el contenido de la columna a ciertos valores. Los usuarios no pueden anular la configuración del cliente. Un usuario es un actor, mientras que un cliente es básicamente un filtro que crea un subconjunto de datos disponibles para un usuario que pertenece al cliente. La configuración del usuario y del cliente se conserva.

Mi enfoque actual funciona más o menos así:

Request --> Controller 
      | <--> sanitizes and returns Request params 
      | ---> Facade (capsules steps to fetch View Data) 
      |  | <--> Table Data Gateway builds Query for requested View 
      |  | <--> Query Decorator¹ applies User/Client settings 
      |  | <--> DB Adapter fetches RecordSet from decorated Query 
      | <----returns Recordset 
      | <--> applies RecordSet to View 
      | <--> Data-Aware ViewHelper render RecordSet (and View) 
Response <--returns rendered View 

¹El decorador de consulta puede leer en la configuración persistió usuario/cliente y añadirlo al objeto de consulta de base devuelto por el TDG sobre la marcha.

Sin embargo, últimamente he dudado de este enfoque y quiero mejorarlo. Supongo que podría eliminar los TDG por completo y hacer que View sea completamente genérico desde la interfaz de usuario; basado solo en la estructura de DB. A los usuarios ciertamente les gustaría esto. El caso es que la Vista debe saber mucho sobre los datos. Los ViewHelpers deben conocer los nombres de las columnas para enriquecer los datos y, a menudo, lo hacen con respecto a las columnas múltiples en los Recordsets. No pueden ser genéricos y algo me dice que esto es un problema de todos modos. Se siente como una mezcolanza. Simplemente no puedo precisar por qué.

Todos los patrones, ideas y opiniones son muy apreciados. Sé que la pregunta es algo vaga, pero como dije, no puedo precisar qué es lo que me hace dudar de este enfoque. Así que supongo que estoy buscando enfoques de buenas prácticas para construir aplicaciones centradas en bases de datos personalizables para usuarios y clientes de una manera sostenible. Ciertamente no necesito una solución, solo algunas ideas y tal vez algunos enlaces para ver cómo otras personas abordan este problema, por lo que puedo tenerlo en cuenta en la próxima refactorización.

Nota
Voy a dejar la pregunta abierta para la duración completa antes de aceptar una respuesta. Cualquier entrada es apreciada.

+1

Por favor, perdona mi escepticismo, pero: La vista necesita saber mucho acerca de los datos? ¿Los ViewHelpers deben saber los nombres de las columnas? * ¿Por qué? * Esto casi suena como un efecto de plataforma interna, una reinvención de Microsoft Access o Cognos. La personalización más allá de un cierto umbral es malvada; podrían ser los * requisitos * los que necesitan una refactorización. – Aaronaught

+0

@Aaronaught El escepticismo está bien. Es lo que me hizo formular esta pregunta :) Para responder la tuya: imagina que hay un ViewHelper que representa una Barra de línea de tiempo basada en * Inicio *, * Fin * y * Estado * como parte de una tabla que representa un conjunto de registros completo además de un ViewHelper que rinde un PieChart basado en * Created_By *. – Gordon

Respuesta

13

Después de volver a leer su pregunta unas cuantas veces y reflexionar sobre ella para un poco, creo que habría resumir la situación de esta manera:

La "M" se encuentra en su "MVC".

En este punto, ha creado manualmente un esquema de base de datos relacional de modo que tenga un mapeo 1: 1 con su modelo de dominio. Y eso es genial, hace que la asignación sea muy fácil, pero un conjunto de registros aún no es una clase de dominio.

El término Modelo en el contexto de MVC refiere a un modelo dominio, no un modelo relacional . Si tiene una base de datos relacional que respalda esta aplicación, entonces necesita algún tipo de mapeo. Eso no significa que necesites un marco ORM completo como Doctrine, aunque sí encuentro que estas herramientas me facilitan la vida, incluso para proyectos pequeños, pero necesitas algo. De hecho, el Zend Framework incluso entra en detalles sobre la asignación de un modelo de dominio en el Quick Start.

No creo que deba quitar el TDG. Las abstracciones son buenas Arrancarlo para hacer que su aplicación sea un poco más ágil es algo que compararía con ir a un edificio de oficinas y arrancar el sistema telefónico con el argumento de que los empleados solo pueden usar sus teléfonos celulares. Se puede , pero no quiere que, igual que no quieren que sus puntos de vista lanzando consultas SQL directamente en la base de datos. Es ineficiente y generalmente es difícil de administrar.

Mi versión de la arquitectura se vería así:

Request --> Controller 
      | <--> sanitizes and returns Request params 
      | ---> Facade (encapsulates steps to fetch View Data) 
      |  | <--> Table Data Gateway builds Query for requested View 
      |  | <--> Query Decorator applies User/Client settings 
      |  | <--> DB Adapter fetches RecordSet from decorated Query 
***   |  | <--> Mapping layer converts RecordSet to Domain Model 
***   | <----returns Model 
***   | <--> applies Model to View 
***   | <--> Data-Aware ViewHelper render Model (and View) 
Response <--returns rendered View 

He marcado las líneas de cambio con ***. En realidad, lo único que he cambiado es que, en lugar de seleccionar un conjunto de registros de la fachada, está recogiendo un modelo (probablemente una matriz de clases de dominio) y aplicando que a la Vista.

En lugar de términos como $row['Status'] en su Vista [Ayudante], tendrá $event->status, que es más seguro y simple de mantener en el largo plazo. No hay nombre de columna allí, solo una propiedad.

Ahora se mencionan explícitamente en la parte superior de su pregunta que usted no tiene ninguna ORM, así que creo que usted está probablemente consciente de la mayor parte de esto y tal vez sólo sea necesario un empujón. Esas dudas persistentes en su mente son probablemente las siguientes: ¿Qué pasa si no siempre es de solo lectura? ¿Qué pasa si el modelo de datos se vuelve más complicado? ¿Qué pasa si la gente comienza a pedir informes más complicados?

Todas estas cosas son la razón por la que tiene un modelo de dominio, por lo que es, de hecho, el bloque de construcción fundamental de MVC: el tiempo, el modelo mental de sus usuarios tienen se caída fuera de sincronía con el modelo de datos, por una serie de razones que no entraré aquí. El punto es que casi siempre sucede.

Estoy seguro de que esto es necesario? ¿Estoy seguro de que no es solo un exceso, un montón de conjuros rituales que no tienen ningún significado para un proyecto tan pequeño?

No, no lo soy. Solo tú puedes decidir eso. Lo que puede indicar es que el paradigma MVC como arquitectura específica no le está haciendo mucho bien sin un modelo de dominio adecuado. Es un poco mejor, pero no que es mucho mejor que simplemente tener consultas en línea o llamadas de fachada en cada página. Sin un modelo, MVC no es mucho más que un elegante esquema de reescritura de URL.

Tal vez necesite este nivel de abstracción, tal vez no; pero supongo que probablemente sospeches que podrías, de lo contrario no hubieras hecho la pregunta. Piénselo, analice los requisitos y el alcance actuales, pregúntese qué tipos de cambios son posibles y si la arquitectura actual parece demasiado frágil para acomodar eso, entonces el siguiente paso lógico sería un modelo de dominio, incluso si hoy es solo un espejo exacto del modelo relacional. Mañana podría no ser.

Espero que este es el tipo de respuesta que estabas buscando!

+0

Gracias Aaron. En realidad, eres bastante preciso acerca de mis dudas. Quería tener un ORM y un modelo de dominio desde el principio por las razones que mencionó, pero un superior lo convenció porque estaba preocupado por el impacto en el rendimiento que tendría. – Gordon

+0

@Gordon: Ahh, microgestión, ¡ahora todo tiene sentido! A menos que su sitio trate millones de usuarios por día, las buenas abstracciones y el buen diseño deberían ser prioridades más importantes que el rendimiento (e incluso entonces, hay otras opciones). El impacto en el rendimiento de un modelo de dominio es casi nulo de todos modos; la mayoría de las aplicaciones respaldadas por bases de datos están vinculadas a E/S y pasan la mayor parte del tiempo esperando los resultados de las consultas. ¡Buena suerte! – Aaronaught

+0

Gracias de nuevo. Disfruta de tu recompensa bien ganada :) – Gordon

0

El diseño de esquema de DB tiene diferentes requisitos (rendimiento de consulta/escritura, escalabilidad) como una buena IU (buen flujo de página, que respalda la forma en que las personas trabajan o cómo funcionan los procesos). Muy a menudo, por lo tanto, el enfoque UI y DB son difíciles de mapear directamente.

Como un mal ejemplo recuerdo una aplicación que usa 'Oracle Forms', que presentaba directamente una vista genérica de la estructura de la base de datos. Para la gente que no era un experto en tecnología, a menudo era muy poco intuitivo de usar.

Todavía creo que en su caso, si la Vista se puede asignar directamente al esquema DB, asegúrese de deshacerse de las capas de abstracción innecesarias, codificar y simplificar el sistema. Implementa los requisitos lo más simple que puedas.

Cuestiones relacionadas