MVC: ¿El controlador rompe el principio de responsabilidad única?

15

El Principio de Responsabilidad Única establece que "una clase debe tener un motivo para el cambio".

En el patrón MVC, el trabajo del Controlador es mediar entre la Vista y el Modelo. Ofrece una interfaz para que la Vista informe las acciones realizadas por el usuario en la GUI (por ejemplo, permite que la Vista llame a controller.specificButtonPressed() ) y puede llamar a los métodos apropiados en el Modelo para manipular sus datos o invocar sus operaciones (por ejemplo, model.doSomething() ).

Esto significa que:

  • El Controlador necesita saber acerca de la GUI, para ofrecerle a la Vista una interfaz adecuada para informar las acciones de los usuarios.
  • También debe conocer la lógica en el Modelo para poder invocar los métodos apropiados en el Modelo.

Eso significa que tiene dos razones para cambiar : un cambio en la GUI y un cambio en la lógica de negocios.

Si la GUI cambia, por ejemplo, se agrega un nuevo botón, es posible que el Controlador deba agregar un nuevo método para permitir que la Vista informe a un usuario presionando este botón.

Y si la lógica de negocios en el Modelo cambia, el Controlador podría tener que cambiar para invocar los métodos correctos en el Modelo.

Por lo tanto, el Controlador tiene dos posibles razones para cambiar . ¿Se rompe el SRP?

    
pregunta Aviv Cohn 04.05.2014 - 00:01
fuente

5 respuestas

12

Si continúa razonando sobre el SRP, notará que "responsabilidad única" es en realidad un término esponjoso. Nuestro cerebro humano es capaz de distinguir de alguna manera entre diferentes responsabilidades y múltiples responsabilidades pueden resumirse en una responsabilidad "general". Por ejemplo, imagine que en una familia común de 4 personas hay un miembro de la familia responsable de preparar el desayuno. Ahora, para hacer esto, uno tiene que hervir huevos y tostar pan y, por supuesto, preparar una taza saludable de té verde (sí, el té verde es lo mejor). De esta manera usted puede dividir "preparar el desayuno" en pedazos más pequeños que se resumen en "preparar el desayuno". Tenga en cuenta que cada pieza también es una responsabilidad que podría, por ejemplo, ser delegado a otra persona.

De vuelta al MVC: si mediar entre el modelo y la vista no es una responsabilidad sino dos, ¿cuál sería la siguiente capa de abstracción arriba, combinando esas dos? Si no puede encontrar uno, tampoco lo abstrajo correctamente o no hay ninguno, lo que significa que lo entendió bien. Y siento que ese es el caso con un controlador, manejando una vista y un modelo.

    
respondido por el valenterry 04.05.2014 - 01:11
fuente
8

Si una clase tiene "dos posibles razones para cambiar", entonces sí, viola el SRP.

Por lo general, un controlador debe ser liviano y tener la responsabilidad única de manipular el dominio / modelo en respuesta a algún evento controlado por GUI. Podemos considerar que cada una de estas manipulaciones son básicamente casos de uso o características.

Si se agrega un nuevo botón en la GUI, el controlador solo debería cambiar si ese nuevo botón representa alguna característica nueva (es decir, opuesto al mismo botón que existía en la pantalla 1 pero que aún no existía en la pantalla 2, y luego se agrega a la pantalla 2). También debería haber un nuevo cambio correspondiente en el modelo, para admitir esta nueva funcionalidad / característica. El controlador todavía tiene la responsabilidad de manipular el dominio / modelo en respuesta a algún evento controlado por GUI.

Si la lógica de negocios en el modelo cambia debido a un error que se corrige, y requiere que el controlador cambie, entonces este es un caso especial (o tal vez el modelo está violando el principal abierto). Si la lógica de negocios en el modelo cambia para admitir alguna funcionalidad / característica nueva, entonces eso no necesariamente afecta al controlador, solo si el controlador necesita exponer esa característica (lo que casi siempre sería el caso, de lo contrario, ¿por qué se agregaría a el modelo de dominio si no se va a utilizar). Por lo tanto, en este caso, el controlador también debe modificarse para admitir la manipulación del modelo de dominio de esta nueva forma en respuesta a algún evento controlado por GUI.

Si el controlador tiene que cambiar porque, digamos, la capa de persistencia se cambia de un archivo plano a una base de datos, entonces el controlador ciertamente está violando el SRP. Si el controlador siempre funciona en la misma capa de abstracción, eso puede ayudar a lograr el SRP.

    
respondido por el jordan 04.05.2014 - 00:49
fuente
4

El controlador no viola SRP. Como indicas, su responsabilidad es mediar entre los modelos y la vista.

Dicho esto, el problema con su ejemplo es que está vinculando los métodos del controlador a la lógica en la vista, es decir, controller.specificButtonPressed . Nombrar los métodos de esta manera vincula el controlador a su GUI, no ha podido abstraer correctamente las cosas. El controlador debe tratar de realizar acciones específicas, es decir, controller.saveData o controller.retrieveEntry . Agregar un nuevo botón en la GUI no significa necesariamente agregar un nuevo método al controlador.

Presionar un botón en la vista, significa hacer algo, pero lo que sea podría haberse activado fácilmente de cualquier otra forma o incluso no a través de la vista.

Del artículo de Wikipedia sobre SRP

  

Martin define una responsabilidad como una razón para cambiar, y concluye   que una clase o módulo debe tener una, y solo una, razón para   cambio. Como ejemplo, considere un módulo que compila e imprime un   informe. Tal módulo puede ser cambiado por dos razones. Primero el   El contenido del informe puede cambiar. En segundo lugar, el formato del informe puede   cambio. Estas dos cosas cambian por causas muy diferentes; uno   sustantivo, y uno cosmético. El principio de responsabilidad única.   dice que estos dos aspectos del problema son en realidad dos   responsabilidades, y por lo tanto deben estar en clases separadas o   módulos Sería un mal diseño juntar dos cosas que cambian para   diferentes razones en diferentes momentos.

El controlador no se preocupa por lo que está en la vista solo que cuando se llama a uno de sus métodos, proporciona datos específicos a la vista. Solo necesita conocer la funcionalidad del modelo en la medida en que sabe que debe llamar a los métodos que tendrán. No sabe nada más que eso.

Saber que un objeto tiene un método disponible para llamar no es lo mismo que conocer su funcionalidad.

    
respondido por el Schleis 04.05.2014 - 02:49
fuente
1

Una responsabilidad única de los controladores es ser el contrato que media entre la vista y el modelo. La vista solo debe ser responsable de la visualización, el modelo solo debe ser responsable de la lógica empresarial. Es responsabilidad de los controladores reducir esas dos responsabilidades.

Eso está muy bien, pero aventurarse un poco fuera de la academia; Un controlador en MVC generalmente se compone de muchos métodos de acción más pequeños. Estas acciones generalmente corresponden a cosas que una cosa puede hacer. Si estoy vendiendo productos, probablemente tendré un ProductController. Ese controlador tendrá acciones como GetReviews, ShowSpecs, AddToCart ect ...

La vista tiene el SRP de mostrar la interfaz de usuario, y parte de esa interfaz de usuario incluye un botón que dice AddToCart.

El controlador tiene el SRP de conocer todas las vistas y modelos involucrados en el proceso.

Los controladores AddToCart Action tienen el SRP específico de conocer a todos los que deben participar cuando se agrega un artículo a un carrito.

El Modelo de producto tiene el SRP de la lógica del producto de modelado, y el Modelo de ShoppingCart tiene el SRP de modelar cómo se guardan los artículos para su posterior pago. El Modelo de usuario tiene un SRP de modelar al usuario que está agregando cosas a su carrito.

Puede y debe estar reutilizando modelos para hacer su negocio y esos modelos deben estar acoplados en algún punto de su código. El controlador controla cada forma única en que ocurre el acoplamiento.

    
respondido por el Yojin 02.07.2017 - 06:05
fuente
0

Los controladores en realidad solo tienen una responsabilidad: alterar el estado de las aplicaciones según la entrada del usuario.

  

Un controlador puede enviar comandos al modelo para actualizar el estado del modelo (por ejemplo, editar un documento). También puede enviar comandos a su vista asociada para cambiar la presentación del modelo de la vista (por ejemplo, al desplazarse por un documento).

fuente: wikipedia

Si, por el contrario, tiene "controladores" al estilo de Rails (que combinan instancias de registros activos y plantillas simples) , entonces, por supuesto, están rompiendo el SRP.

Por otra parte, para empezar, las aplicaciones de estilo Rails no son realmente MVC.

    
respondido por el mefisto 05.05.2014 - 22:25
fuente

Lea otras preguntas en las etiquetas