Arquitectura MVC: ¿cuántos controladores necesito?

54

He estado codificando durante un tiempo, pero principalmente scripts y aplicaciones simples. Me mudé a un nuevo rol donde se trata de desarrollar aplicaciones web y usar una arquitectura MVC adecuada, por lo que estoy tratando desesperadamente de aprender todo eso muy rápidamente.

Espero que esta pregunta no sea muy similar a las " Mejores prácticas para la arquitectura MVC ", pero a medida que reviso algunos tutoriales diferentes, noté que algunos tienen múltiples controladores para diferentes cosas.

¿Cuántos controladores necesita una sola aplicación web?

Me doy cuenta de que esto sería difícil de responder sin un ejemplo, así que proporcionaré uno:

Solicitud:

  1. El usuario inicia sesión.
  2. El usuario puede hacer una de estas tres cosas:
    a) Cargar un archivo (almacenado en una base de datos mongodb con metadatos).
    b) Buscar un archivo.
    c) Cerrar sesión.

Mi pregunta es general, pero di el ejemplo para ayudar a cualquiera que intente responder.

Jeff
fuente
8
Una pregunta muy bien hecha.
Daniel Hollinrake

Respuestas:

34

Para su ejemplo, crearía dos controladores:

  • Controlador de sesiones para inicio y cierre de sesión (crear y destruir sesión para REST como diseño)
  • Controlador de archivos para todo en archivos (índice = buscar y crear = cargar)

En general, un enfoque RESTful en el que piensas en todo como un recurso que se puede mostrar, crear, editar y destruir te da una buena idea de cómo estructurar las cosas. Como puede ver en mis ejemplos, no me pego demasiado a cada verbo en REST.

Lo más probable es que necesite más controladores para una mayor funcionalidad. Por ejemplo, un controlador de usuarios donde los usuarios pueden crear nuevas cuentas. Y además de esto, necesitaría una interfaz de administración donde puede editar los recursos con mayores privilegios. En tal caso, es bastante común tener casi todos los controladores duplicados.

Una estimación muy aproximada para obtener una idea inicial podría ser un controlador para cada tabla en su base de datos a la que los usuarios puedan acceder. Pero esto es realmente solo una medida muy cruda.

Thorsten Müller
fuente
3
Tomando su ejemplo de administrador: ¿Extendería el controlador de administrador al usuario general o redefiniría completamente todos los métodos? Por ejemplo, tal vez todos los usuarios pueden cargar y buscar, pero solo los administradores pueden eliminar. ¿La clase de controlador de administrador heredaría todos los métodos de usuario generales?
Jeff
44
Esto realmente depende mucho de la funcionalidad real, pero en general simplemente escribo un segundo controlador sin ninguna herencia. Siguiendo el principio del 'controlador delgado' no debería haber mucho código en un controlador de todos modos. Y el controlador de administración puede ser especialmente simple. Toda la funcionalidad importante entra en el modelo. (por ejemplo, si eliminar un usuario significa que todos sus archivos también deberían eliminarse, entonces el modelo maneja esto, no hay una sola línea para esto en el controlador)
thorsten müller
6

Realmente depende de la aplicación web. En su ejemplo, uno es probablemente suficiente. Si tuviera que implementar una aplicación de comercio electrónico completa con envío, impuestos, gestión de inventario, precios escalonados, etc., es posible que desee tener un par más.

Si su controlador sufre de uno o más olores de código (especialmente Clase Grande u Objeto de Dios ), entonces sabe que probablemente haya pasado el punto en el que solo uno lo hará.

Dan Pichelman
fuente
5

Realmente depende de las necesidades de su aplicación y la arquitectura de los módulos empresariales.

Como regla general , la cantidad de controladores necesarios depende de una cantidad de módulos y submódulos en la aplicación web.

Como complemento, sería útil organizar los controladores en Áreas . El concepto de Áreas está integrado en el marco ASP.NET MVC y simplifica la organización de los controladores que sirven a un módulo.

Hay varias discusiones relacionadas:

EL Yusubov
fuente
1
Grandes referencias! ¡Me aseguraré de verlos!
Jeff
Claro, no hay problema.
EL Yusubov
4

Me gusta la forma en que Apple lo hace.

Cada vista está controlada por un solo controlador de vista. ~ Ver la guía de programación del controlador para iOS

La idea es que puedas cambiar fácilmente las Vistas. En mi opinión, tener solo 1 Controllerpor cada Viewhace que sea más fácil lograr esto. Pero estoy seguro de que podría tener un controlador con múltiples vistas y aún así diseñarlo para que pueda cambiar las vistas sin cambiar la lógica del programa.

Korey Hinton
fuente
Ese es un buen punto, pero ¿necesitaría tener un controlador para cada vista más otros adicionales para ocuparse de cosas como los usuarios? También supongo que si mi proyecto fuera más grande, tendría más sentido tener más controladores.
Jeff
Los modelos deben hacer un seguimiento de los usuarios. Por lo tanto, varios controladores pueden usar el mismo objeto modelo si es necesario.
Korey Hinton
2
Entonces, un controlador tiene un objeto Modelo y un objeto Vista. El Controlador solicita información al objeto Modelo (como Información del usuario) y luego configura la Vista en consecuencia. El Modelo debe tener la mayor parte de la lógica del programa, mientras que el Controlador solo tiene la lógica para poder comunicarse entre la Vista y el Modelo.
Korey Hinton
2
Un controlador por vista tiene un diseño muy limitado, ya que su controlador no podría mostrar diferentes modelos de vista para diferentes estados del Modelo.
EL Yusubov
1
@ElYusubov Puedo ver dónde podría ser confuso. En iOS, cada vista tiene solo un controlador de vista y cada controlador de vista tiene solo 1 vista activa (y esa vista puede tener sub-vistas) pero ese controlador de vista también puede contener referencias a cualquier número de vistas.
Korey Hinton
2

Un ejemplo que me gusta es pensar en un termostato. Un termostato es un excelente visual para ver el patrón MVC.


En un termostato analógico antiguo, puede imaginar cosas como esta:

Ver : el lector de temperatura, que muestra la temperatura actual.

Controlador : el dial, donde cambia la temperatura

Modelo : las partes internas que invoca el controlador que hacen que cambie la temperatura.


Siempre debe cumplir con los diseños que permiten el acoplamiento suelto y limitar los modelos y sus controladores asociados a una sola tarea , y debe usar tantos módulos / controladores como necesite . Dependiendo del tamaño de su aplicación, puede tener muchas menos vistas que los modelos y controladores. Esto es de esperar con cualquier aplicación de gran tamaño. La buena programación orientada a objetos se caracteriza por acoplamiento flojo, encapsulación, herencia y polimorfismo. No todos los idiomas admiten el polimorfismo en el mismo grado (función, método, sobrecarga / anulación del operador).

Si desea comprender mejor el uso adecuado de la arquitectura MVC, consulte los "Patrones de diseño: elementos de software reutilizable ... de GoF" de GoF que utilizan código C ++ y SmallTalk, por ejemplo. Este libro no es el alfa y el omega, ¡pero sin duda es un comienzo!

¡Buena suerte!

Charles Addis
fuente
1

Supongo que su ejemplo evolucionará en un sistema complejo.

Solicitud:

El usuario inicia sesión:

  • LoginController

Su única responsabilidad es manejar los inicios de sesión, redirigir o notificar al usuario del resultado.

Cargar un archivo

  • UploadController

Asumo aquí que quieres subir cualquier tipo de archivo. Si en una fecha posterior decide cargar MP3 y PDF, entonces tendría una base UploadController, MP3UploadController y PDFUploadController.

Busca un archivo.

  • SearchFileController

Esto sería suficiente para un requisito básico. Puede tener múltiples controladores de búsqueda en una fecha posterior dependiendo de cuán compleja se vuelva la lógica de búsqueda. Lo último que desea tener es un SearchController único con 20 métodos de acción que realicen búsquedas diferentes.

Cerrar sesión.

-LogoutController .

Uno podría considerar que esto es una exageración, pero no creo que lo sea. Creo que está limpio y bien separado.

Si mirara esta estructura del proyecto, sabría instantáneamente qué hace y cómo está estructurada. Para ir un paso más allá, me gustaría poner LoginControllery LogoutControlleren la zona separada.

He desarrollado algo como esto antes y funcionó muy bien.

CodeART
fuente
¡Gracias por el aporte! ¿Tienes algún código de trabajo? atascarse en algunas cosas.
Jeff
¿Qué problemas tienes?
CodeART el
Puedo cargar un asunto y una fecha (en formato de cadena) pero no puedo cargar el archivo en sí (consulte stackoverflow.com/questions/18344614/… ).
Jeff
Soy un desarrollador de .NET. Lo siento, no puedo ayudarte.
CodeART
1

La mayor parte de su código estaría sucediendo en una capa empresarial, ¿verdad? Si ese es el caso, todo lo que realmente está haciendo en su controlador es devolver datos a la vista.

No estoy seguro de si soy fanático de separar los controladores en subtipos. Si bien debe mantener la separación de las preocupaciones, creo que los subtipos van demasiado lejos. También debe tener cuidado en los casos en que los objetos pesados ​​se inicializan en el constructor o en un controlador. Por ejemplo: en su ejemplo, desearía que se lanzara un objeto pesado, utilizado solo para buscar / cargar archivos cuando el usuario está en la página de inicio de sesión.

Es mejor tener un controlador por unidad lógica, por ejemplo AccountController (inicio de sesión, registro, cierre de sesión), FileController (buscar, cargar), etc.

harsha
fuente
0

En general, puede decir que cada MODELO tiene sus propios CONTROLADORES y VISTAS dedicadas. Al decir general quiero decir que esta es la mejor práctica.

Los aspectos de la aplicación (como la gestión de usuarios) deben traducirse al servicio de la aplicación y el controlador debe llamarlos por sí mismo, o para ajustar su controlador (utilizando atributos que hacen que la funcionalidad del controlador sea "visible" de acuerdo con el rol del usuario solicitado, por ejemplo).

Recuerde que todos los controladores deberían manejar básicamente las operaciones CRUD sobre el modelo y usar diferentes vistas para diferentes filtros.

En mi opinión, una de las principales ventajas de MVC como patrón es que ofrece la mejor manera de vincular modelos y vistas.

Acerca del ejemplo que agregó: crearía 2 controladores: uno para la operación de inicio de sesión de todos los usuarios (registro, inicio de sesión, cierre de sesión, etc.) y el segundo para operaciones de archivo (Carga y búsqueda). tenga en cuenta que el primero también debe estar respaldado con algunos aspectos relacionados con la funcionalidad de inicio de sesión y el segundo es un controlador ordinario

Tecnologías de Saturno
fuente
sin una explicación, esta respuesta puede volverse inútil en caso de que alguien más publique una opinión opuesta. Por ejemplo, si alguien publica un reclamo como "La administración de roles de usuario y la autorización no deberían estar en la parte superior del controlador" , ¿cómo ayudaría esta respuesta al lector a elegir dos opiniones opuestas? Considere editarlo en una mejor forma
mosquito
1
@gnat Acepto tu comentario, mira la respuesta editada
Saturn Technologies