2010-01-22 16 views
9

NOTA: Esta pregunta se ha actualizado para proporcionar más detalles y conocimientos que los anteriores.Primeros pasos con el diseño de software utilizando MVC, OO y patrones de diseño

ACTUALIZACIÓN: Solo quiero agradecer a todos los que respondieron. Todavía estoy a oscuras sobre qué patrón de diseño funcionaría mejor para el Widget. Tal vez uno de los patrones de fábrica o constructor?


Estoy empezando un nuevo proyecto y necesito utilizar MVC, OO y patrones de diseño.

Aquí está la idea: Imagine una página que muestra un conjunto de widgets. Estos widgets son (normalmente) gráficos que se basan en datos contenidos en varias tablas separadas en la base de datos. Uso un ejemplo de página en ejecución que informa sobre el rendimiento de un alumno.

requisitos de alto nivel

  • una página que muestra un conjunto de widgets (HTML solamente).
  • Los datos del widget se basarán en una consulta de base de datos.
  • la página se puede usar para ver conjuntos de datos separados que contienen datos distribuidos de manera similar. Por ejemplo, una sola página mostrará widgets que informan sobre diversos aspectos del rendimiento de un solo alumno.
  • desea ver el rendimiento de otro alumno, abra otra página. No es necesario mostrar diferentes widgets para diferentes estudiantes (aunque puede ser bueno tenerlo después).
  • Puede haber muchos estudiantes, pero los datos contenidos en la base de datos se presentan de manera similar para todos los estudiantes.
  • la forma en que se muestra un widget se puede cambiar fácilmente (por ejemplo, cambiar un widget para que no se muestre como un gráfico circular para mostrarlo como un gráfico de barras).
  • widgets deben poder crearse rápidamente.

Requisitos nivel bajo

  • datos Actualmente no cambia de modo de widgets no tendrán que actualizar automáticamente a sí mismos.
  • Los widgets pueden representar una relación de dos cosas (por ejemplo, una proporción de pruebas fallidas a pruebas exitosas como un gráfico circular), una serie de puntos o, a veces, un único valor numérico.
  • El desarrollo de nuevos widgets debería ser pan comido, no es necesario modificar el código existente.
  • Marco a utilizar: Zend Framework, basado en MVC.

Hay (mínimamente) tres cosas para definir un widget: el conjunto de datos para informar sobre (en el ejemplo anterior, el estudiante ID), la consulta que describe la métrica que se informa, y ​​un modo de render (diagrama de barras, series de tiempo, etc.).

Aquí es un paso en la subdivisión de las responsabilidades de cada capa de la MVC:

Ver: vistas Zend son plantillas HTML con PHP inyectados. Contendrán uno de varios tipos de widgets.Los widgets son de varias formas, incluyendo: las imágenes JPEG estáticos (cargados desde un sitio remoto es decir: <img src="http://widgetssite.com?x=2&y=3"/>, los widgets javascript basados ​​JSON, o gráficos de diversos tipos (piechart, gráfico de barras, etc.)

controlador: crea los widgets, los asigna a la vista después. El conjunto de widgets que se debe mostrar en una página debe mantenerse en alguna parte. Como no puedo pensar en una buena manera de hacer esto en la vista, agregaré esto a los controladores. responsabilidades por ahora. Si hay un lugar mejor para esto, por favor gritar. El controlador también tendrá que manejar otros parámetros de entrada y pasarlos al widget. Por ejemplo, el id data_set que se puede pasar en la línea url como http:/.../report/?student_id=42

Modelo: El modelo, en Zend Framework, es responsable de extraer los datos y, como tal, muy probablemente contenga una clase para cada widget para acceder a la base de datos.

Algunos puntos:

  1. El modelo aquí, representa los datos de un widget en particular. Entonces, necesariamente, necesitará saber cuál será la consulta, para juntar las tablas necesarias para obtener esos datos.

  2. Hay un paso de procesamiento adicional que probablemente sea necesario antes de que el widget pueda presentar los datos. Esto depende de qué renderizador se utilizará. A veces puede requerir la formación de una url de los datos devueltos. Otras veces, una matriz JSON. Otras veces tal vez creando un margen de beneficio. Esto puede ir en el modelo o el controlador o la vista. A menos que alguien pueda pensar en una buena razón para moverlo al controlador o a la vista, probablemente sea mejor dejar esto en vivo en el modelo y mantener la vista y el controlador delgados.

  3. Del mismo modo, un widget se compone de 3 cosas, sus parámetros, sus datos y su procesador.

    Una gran parte de la pregunta es: Qué es una buena manera de representar el widget en un diseño orientado a objetos? Ya le pregunté esto una vez, no pude obtener una respuesta. ¿Existe algún patrón de diseño que pueda aplicarse a los widgets que tenga más sentido para este proyecto?

    Aquí está un primer paso en una clase bastante simple para el widget:

    class Widget{ 
        //method called by the view 
        render() {//output the markup based on the widget Type and interleaved the processed data} 
    
        //methods called by the controller: 
        public function __construct() {//recieve arguments for widget type (query and renderer), call create()} 
        public function create() {//tell the widget to build the query, execute it, and filter the data} 
        public function process_data() {//transform into JSON, an html entity etc} 
    
        //methods called by the model: 
        public function build_query() {...}; 
        public function execute_query() {...}; 
        public function filter_data() {...}; 
    } 
    

    En cuanto a él, que ya se puede ver algunos problemas.

  4. Por ejemplo, es fácil pasar el widget que se creó en el controlador a la Vista para representar.

    Pero cuando se trata de implementar el modelo, no parece tan sencillo. Table Gateway Pattern es más fácil de implementar que ORM. Pero dado que el patrón de puerta de enlace de tabla tiene una clase para cada modelo/tabla, no parece ajustarse a la factura. Podría crear un modelo para una tabla en particular y luego, crear una instancia de cualquier otro modelo necesario. Pero eso no parece ajustarse al Patrón Table Gateway, sino al patrón ORM. ¿Se puede implementar el patrón de puerta de enlace de tabla con varias tablas? ¿Qué alternativas hay? ¿Tiene sentido que el controlador cree el widget y el widget crea el Modelo?

  5. Otro problema que surge es que este diseño no permite una fácil creación de widgets. es decir. Digamos que quería crear un PiechartWidget, ¿cuánto código se puede reutilizar?¿No tendría más sentido usar algunas ideas OO, como una interfaz o clases/métodos abstractos y herencia?

    Digamos que extraigo la clase de Widget, por lo que solo los métodos compartidos se definen concretamente y el resto se declaran como métodos abstractos. La revisión de la clase Widget para que sea abstracta (segundo paso):

    abstract class Widget{ 
    
        private $_type; 
        private $_renderer; 
    
        //methods called by the controller: 
        //receive arguments for widget type (query and renderer), 
        protected function __construct($type, $renderer) { 
        $this->_type = $type; 
        $this->_render = $renderer; 
        $this->create(); 
        } 
    
        //tell the widget to build the query, execute it, and filter the data 
        private function create() { 
        $this->build_query(); 
        $this->execute_query(); 
        $this->filter_data(); 
        } 
    
        //methods called by the model: 
        abstract protected function build_query(); 
    
        protected function execute_query() { 
        //common method 
        } 
    
        abstract protected function filter_data(); 
    
        //method called by controller to tranform data for view 
        //transform into JSON, an html entity etc 
        abstract protected function process_data(); 
    
        //method called by the view 
        //output the markup based on the widget Type and interleave the processed data 
        abstract protected function render(); 
    } 
    

    Es este un buen diseño? ¿Cómo puede ser mejorado?

  6. Supongo que escribir un nuevo widget requerirá al menos un nuevo código para generar la consulta, y tal vez filtrar los datos, pero debería poder usar el código preexistente para casi todo el resto de su funcionalidad, incluyendo los renderizadores que ya existen

Estoy esperando que alguien pudiera proporcionar al menos alguna información sobre este diseño. Validarlo? Arráncalo. Llámame un idiota. Eso está bien también. Podría usar cualquier tracción delantera.

Algunas preguntas específicas:

Q1. ¿Cuál es la mejor manera de implementar los procesadores, como parte de la clase de Widget o como una clase separada? 1a. Si está separado, ¿cómo interactuaría con la (s) clase (s) de widget?

Q2. ¿Cómo podría mejorar este diseño para simplificar la creación de nuevos tipos de widgets?

Q3. Y, por último, siento que me falta algo aquí con respecto a la encapsulación de datos. ¿Cómo se relaciona la encapsulación de datos con los requisitos y se desarrolla en este escenario?

+0

http://en.wikipedia.org/wiki/Presentation-abstraction-control – alex

+0

Esto está usando Zend Framework, por lo que MVC es inherente. – hinghoo

+0

¿Todos los datos estarían en forma de proporciones como el ejemplo que usted da, o algunos widgets mostrarían una proporción mientras que otros mostrarían, por ejemplo, un conjunto de puntos? – mattjames

Respuesta

1

El propósito detrás de todas estas ideas - MVC, patrones, etc. - es esencialmente el mismo: cada clase debe hacer una cosa, y cada responsabilidad distinta en su aplicación deberían separarse en distintas capas. Sus puntos de vista (página y widgets) deben ser delgados y tomar pocas o ninguna otra decisión que presentar datos recopilados de los modelos. Los modelos deberían operar en una capa de datos de forma independiente, es decir, no deberían saber si la fuente de sus datos es un tipo específico de fuente de datos. Los controladores también deberían ser delgados, actuando básicamente como una capa de enrutamiento entre las vistas y los modelos. Los controladores toman la información de los usuarios y realizan las acciones relevantes en los modelos. La aplicación de este concepto varía dependiendo de su entorno de destino - web, cliente rico, etc.

La arquitectura del modelo por sí solo no es un problema trivial. Usted tiene muchos patrones para elegir y muchos marcos, y elegir el correcto - patrón o marco - dependerá completamente de los detalles de su dominio, del que tenemos muy pocos aquí para darle consejos más específicos. Baste decir que se recomienda que dedique un tiempo a conocer algunos marcos Object-Relational Mapping para su pila de tecnología particular (ya sea Java, .NET, etc.) y el respective patterns en el que se crearon.

También familiarícese con la diferencia entre MVP y MVC - Martin Fowler 's trabajo es esencial aquí.

En cuanto a los patrones de diseño, la aplicación de la mayoría de los patrones estándar GOF fácilmente podría entrar en juego de una forma u otra, y se recomienda que gasta tiempo en Design Patterns o uno de los muchos introductory texts sobre el tema. Nadie aquí puede dar respuestas específicas sobre cómo se aplica MVC a su dominio, que solo pueden responder ingenieros experimentados en cooperación con un propietario de producto que tenga la autoridad para tomar decisiones de flujo de trabajo y UI que afectarán en gran medida dichas decisiones en sus detalles .

En resumen, la propia naturaleza de su pregunta sugiere que está en necesidad de un arquitecto o desarrollador programación orientada a objetos con experiencia mayor que ha hecho esto antes. Alternativamente, concédete una buena cantidad de tiempo en un estudio intensivo antes de seguir adelante. El alcance de su proyecto abarca una gran cantidad de aprendizaje que muchos codificadores toman años para comprender completamente. Esto no quiere decir que su proyecto esté condenado; de hecho, puede lograr mucho si elige la pila de tecnología adecuada, el marco, etc., y suponiendo que es razonablemente brillante y centrado en la tarea que tiene entre manos.Pero obtener conceptos tan amplios como "MVC" u "OO" no es algo que creo que se pueda hacer en un primer intento y con limitaciones de tiempo.

EDIT: Acabo de ver tu edición re: Zend. Tener un marco en su lugar es bueno, que se encarga de muchas decisiones arquitectónicas. No estoy familiarizado con Zend, pero me quedaré con sus valores predeterminados. Mucho más depende aquí de su entrega definitiva de IU: ¿se encuentra en un entorno de RIA como Flash o Silverlight, o se encuentra en un entorno HTML/JavaScript estricto? En cualquier caso, los controladores aún deberían ser delgados y operar como enrutadores que reciban las solicitudes de los usuarios de HTTP get y posts, y de inmediato entreguen los modelos. Las vistas también deberían ser delgadas y tomar la menor cantidad de decisiones posible. El concepto de MVC aplicado en un entorno web ha sido bastante bien establecido por Rails y los marcos que siguieron, y asumo que Zend es similar a algo así como CakePHP en este aspecto: el servidor de aplicaciones tiene un sistema de enrutamiento que mapea las llamadas HTTP a acciones del controlador que responden con vistas específicas. El ciclo de petición/respuesta es básicamente el siguiente:

  1. petición del usuario publicado a través de una URL
  2. Router manos el control a una clase controlador
  3. controlador realiza una llamada a un modelo con los parametros dados
  4. el modelo opera en los datos, publicaciones en el controlador
  5. El marco mapea los datos terminados en una vista, con algún tipo de código subyacente que pone los resultados de la solicitud en el alcance de la vista.
  6. El marco crea html (o xml o lo que sea) y se devuelve a la persona que llama.
+0

La última entrega de interfaz de usuario == un estricto entorno HTML/JavaScript. – hinghoo

1

Es posible considerar el uso de Subject Observer Pattern

Que su clase, DataReader nombrado como único sujeto. Sus múltiples widgets actuarán como observadores. Una vez que su DataReader reciba datos del servidor, este (Asunto) informará a múltiples widgets (Observer).

Sus widgets individuales pueden tener una presentación diferente para presentar al mismo conjunto de datos de DataReader.

actualización

En el mensaje, donde sujetos notificar observador, que puede incluir la información de tipo de mensaje también. Los widgets solo procesarán el tipo de mensaje, que es de su propio interés, e ignorarán el resto del mensaje.

+0

Gracias por su respuesta. Tengo curiosidad si se aplica en el caso de que los widgets se basen en consultas separadas. Además, con respecto a la segunda parte de mi pregunta, ¿cuál es la mejor manera de integrarlo en un diseño de MVC? – hinghoo

+0

Ver mi actualización;) –

4

Para # 2, si está utilizando WPF en Windows, o Silverlight en general, considerar el uso de patrón MVVM (Model-View-ViewModel), aquí está la explicación con una aplicación de WPF: MVVM at msdn

Para # 1 (comentarios no contestados): para implementaciones exactas (y variaciones menores) de MVC, realmente depende del idioma que esté usando.

Otra alternativa para MVC es MVP Model View Presenter

Recuerde que el objetivo de OO no es de meter los patrones de diseño en el código, pero para crear el código mantenible con menos errores/aumento de la legibilidad.

1

Parece que quiere usar MVC y otros patrones porque son las nuevas palabras de moda. La división de su diseño entre la vista de modelo y el controlador debería indicarle cómo distribuir la funcionalidad de su aplicación. Aunque estoy totalmente de acuerdo en que usar MVC es el enfoque correcto, sugiero que investigue el patrón y mire algún código fuente que lo implemente. Sin embargo, como inicio de su pregunta, los widgets que se mostrarán serán sus puntos de vista, eso debería ser obvio. La entrada del usuario, como cambiar un parámetro de algún widget o solicitar otra información, entrará en su aplicación y debe ser manejada por un controlador. Un ejemplo concreto de esto es un HttpServlet basado en Java. El servlet del controlador recibe la solicitud del usuario y le pide a las capas inferiores de su aplicación (Servicio, Persistencia, etc.) una representación actualizada de su modelo. El modelo incluye todos los objetos específicos de su dominio (es decir, los datos de sus bases de datos, etc.). Estos datos (el modelo actualizado) vuelven al controlador, que a su vez empuja una nueva vista para el usuario. Con suerte, eso es suficiente para comenzar a diseñar su aplicación.

Como ayuda adicional, usted podría considerar el uso de un marco para ayudar en el desarrollo de su aplicación. Me gusta mucho Spring, y tiene una implementación MVC de primera clase que realmente te ayuda a diseñar una aplicación web MVC correcta.

+0

Siéntase libre de comentar para el voto abajo personas –

2

Requisitos elevados - una página que muestra un conjunto de widgets. los widgets se basan en los datos contenidos en varias tablas separadas en la base de datos. - los datos del widget se basarán en una consulta de base de datos. widget muestra sus datos de una manera particular. - los widgets deberían poder crearse rápidamente.

Requisitos nivel bajo - cambios en los datos, varios gráficos necesitan cambiar, modelo de inserción (de datos a la interfaz de usuario) - Desarrollo de nuevos widgets debe ser una brisa, código existente no tiene por qué ser modificado

asesoramiento de diseño Conceptos básicos de patrones - MVC admite uno a muchos patrones de notificación, así que sí, una vez que su widget se inicializa, se crea y se conecta a la página web, debe esperar las notificaciones de la base de datos. - Patrón de estrategia, todo su código debería desarrollarse en una interfaz. Se deben agregar nuevos widgets a una LinkedList parametrizada (u otra estructura de datos). De esta forma, los nuevos desarrolladores de widgets solo implementan la interfaz y su marco recoge estas notificaciones sin cambiar el código existente.

Siddharth

+0

Me gusta su desglose de los requisitos. Me disculpo por no ser más claro. Un requisito fue crítico, no es un modelo de tipo push. Los widgets no necesitan actualizar _hat_ con frecuencia. Avíseme si tiene alguna sugerencia sobre qué patrón usar para el widget basado en eso. – hinghoo

0

NOTA: Este es mi nueva respuesta basada en la pregunta nueva actualización.

Aquí hay un diagrama de clases propuesto. Voy a trabajar en un diagrama de secuencia. alt text

Mi vieja respuesta está aquí:

Sobre la base de los requisitos que usted describe, su modelo es su base de datos o almacén de datos y sus vistas son sus gráficos circulares, gráficos de barras, etc.No veo la necesidad de un controlador, porque parece que tienes un tablero de una página con widgets.
Necesita pasar su tiempo en el modelo de base de datos. Como está haciendo todas las selecciones y no hay actualizaciones, busque un modelo de datos desnormalizado que haga que estas consultas sean eficientes. Debe colocar los resultados de estas consultas en un objeto tipo tabla (por ejemplo, matriz bidimensional) o en una matriz tridimensional según la cantidad de dimensiones. Estás limitado a 3 dimensiones a menos que uses animación.

+0

¡Buen consejo sobre el esquema desnormalizado para sistemas de solo selección! Por favor aclare lo que quiere decir con la última parte "Deberías empujar ...". ¿Eso es para el almacenamiento en caché? ¿O para la representación final? – hinghoo

+0

LWoodyiii: Gracias, ¿qué usas para crear ese diagrama? – hinghoo