domingo, 3 de julio de 2016

¿Cuando usar MVC?

En resumen

Arquitectura de tres capas que separa la Vista o interfaz de usuario, el Modelo de datos y el Controlador que se encarga de la recepción de eventos de la vista y los transforma en comandos. Pero cuando algo cambia en el modelo, cambia en TODAS las vistas dentro de un mismo contexto, que generalmente es una sesión.

Algo de música para saber más sobre MVC: MVC.mp3

Como funciona MVC

MVC está formado por 3 elementos relacionados unos con otros. Redundando: el modelo se relaciona con la vista, la vista con el controlador y el controlador con el modelo, como formando un triángulo.

Figura 1: MVC

La idea de esta arquitectura es, que cuando el usuario usando la vista ejecuta un comando pase lo siguiente (llamémoslo Flujo 1): 
  1. El evento vaya al controlador (relación 3).
  2. El controlador utilice el modelo durante la ejecución del comando (relación 2).
  3. Cuando un error ocurre en el modelo, lo regrese al controlador (relación 2).
  4. El controlador regrese a la vista un mensaje de éxito o de error (relación 3).
  5. FIN. Pero falta la relación 1!

La relación 1 comunmente no la implementan los programadores, si esta relación no es implementada por definición la arquitectura deja de ser MVC. La relación 1 muestra una comunicación de Modelo a Vista, nunca hay una comunicación de Vista a Modelo porque esto lo realiza el Controlador (aparentemente la comunicación en ambas vías).

Imaginemos el siguiente escenario:
Un usuario abre dos ventanas (dos vistas), ambas tienen su propio controlador pero manipulan un tipo de dato en común, por lo tanto tenemos que usar el mismo modelo, pensemos que esta instancia se ejecuta en la misma sesión, entre diferentes sesiones no es necesario que los cambios del modelo sean notificados.
Algo así:

Figura 2: dos vistas manipulando el mismo modelo

Si ambas ventanas tienen la misma lista de objetos perteneciente al modelo en común y la vista 1 manipula un objeto se ejecuta el flujo 1, pero si luego el usuario manipula el mismo objeto en la vista 2 ocurrirá un problema de concurrencia debido a que ahora las vistas tienen diferentes versiones del mismo objeto, por esto es necesaria la relación 1 de la figura 1. La relación 1 de la figura 1 es equivalente a las relaciones 5 y 6 de la figura 2:

El modelo tiene que notificar a todas las vistas cuando ocurre un cambio.

Para implementar la relación entre modelo y vista se puede aplicar el patrón Observer. Las vistas jugarían el rol de observadores y el modelo jugaría el rol de observable.

Sin la implementación de la relación modelo-vista, la arquitectura es de 3 capas pero no es una arquitectura MVC. Recordemos que MVC es de 3 capas pero 3 capas no necesariamente es MVC.

MVC facilita mucho la integración de nuevas vistas, pero el cambio de lógica de negocios es relativamente complejo. Si vemos la relación vista-controlador, podemos tener una idea del acoplamiento fuerte entre ambos elementos, esto rompe una regla de diseño: El acoplamiento entre elementos debe ser débil.


Golden Hammer: MVC

 A continuación otras herramientas. No solo con un martillo se repara todo!!!

 

Modelo Vista Adaptador (MVA)

Es similar a MVC pero aquí no se implementa la relación vista-modelo. El "triangulo" se vuelve una "línea":

Figura 3: MVA

Funciona como lo indica el Flujo 1, el modelo no debe notificar a nadie sobre cambios. Este pequeño cambio evita el uso de recursos del lado del servidor, podría utilizarse en un sistema sin sesión o con una sesión parcial.

Modelo Vista Presentador (MVP)

Esta arquitectura también es un triángulo, la vista tiene una relación con el modelo en ambas vías, el modelo no es observable y no debe notificar los cambios, la relación es para traer los datos directamente y el presentador está mas relacionado a la vista que a la lógica de negocios, como sí pasa con el controlador de MVC. Esta arquitectura se utilizó en páginas estáticas en los inicios del mundo web, actualmente podría funcionar para reportería o páginas donde no se requiera una mayor interactividad con el usuario.

Figura 4: MVP

Modelo Vista VistaModelo (MVVM)

Un nuevo elemento, vistamodelo. Generalmente se implementa utilizando un patrón Mediator o un Proxy y la idea del vistamodelo es que represente una capa visual remota en un contexto local. Esta arquitectura está implementada en frameworks como GWT y ZK, la implementación de un sistema utilizando esta arquitectura es mucho mas barata comparada con MVC. 
Además, sobre esta arquitectura se puede implementar MVC, pero utiliza mas recursos. Para implementar MVC utilizando una MVVM, la capa visual serían la capas vistamodelo y vista. La capa de control puede aplicarse sin problema (y la relación 1 de la Figura 1).

Figura 5: MVVM

Figura 6: MVC sobre MVVM

Presentación Abstración Control (PAC)

Esta arquitectura está formada por agentes, los agentes (cada grupo P-A-C) se comunican entre sí para mostrar en diferentes niveles la información a los usuarios, por ejemplo los usuarios finales utilizarían el nivel BOTTOM, los usuarios técnicos podrían utilizar la capa TOP que está más cerca de los datos crudos.
El elemento control además de conectar los datos entre los elementos de abstracción y presentación se encarga de la comunicación con el resto de agentes. Esta relación se puede implementar utilizando el patrón Mediator.
El elemento de presentación es similar a la vista de MVC.
El elemento de abstracción contiene los datos como el modelo en MVC, pero contiene solo información parcial dependiendo del contexto del agente.
PAC facilita el cambio de lógica de negocios porque se reutilizan los elementos de control, por otro lado es complejo de implementar.
Figura 7: PAC

MVC jerárquico (HMVC)

Es similar a PAC, pero cada "agente" implementa una estructura MVC. 

Microservicios

Los servicios son componentes autónomos que proveen datos bajo un esquema específico. Esta arquitectura provee escalabilidad, no es monolítica, permite modernizar constantemente los componentes, balancea la carga entre los componentes, facilita el trabajo en grupo, etc.
Figura 8: Microservicios
La figura 8 muestra 3 instancias del servicio A y 3 del servicio B. Las 3 instancias del servicio A están físicamente en el mismo servidor. 2 instancias del servicio B están en un servidor físico y la tercera instancia está en otro servidor.
Todos los servicios se comunican con el orquestador, el orquestador balancea la carga entre los servicios activos, el orquestador sabe cuando un servicio nuevo se inicia o cuando uno se detiene.
Si se detuviera el servicio A-1, el orquestador balancearía el tráfico a los servicios A-2 y A-3.
En caso contrario si se iniciara otro servicio por ejemplo A-4 el orquestador balancearía la carga entre los servicios A 1,2,3 y 4.
Si fuera necesario crear otro servicio B se puede iniciar en uno de los dos servidores donde se ejecutan las otras instancias del servicio B o en un nuevo servidor.
Además imaginemos que los servicios A están en node.js y que lo servicios B están en java, pero los servicios B-1 y B-2 se ejecutan en JDK7 en un linux fedora  y el servicio B-3 se ejecuta en JDK8 en un linux centos.
Bastante flexible, ¿no?!!! De cualquier forma también se debe tener cuidado o podríamos terminar con muchos procesos desordenados, esto se conoce como procesos ravioli.



Conclusión

Todas las arquitecturas tienen ventajas y desventajas, ninguna se adapta a todos los problemas. Tal y como dice el antipatrón golden hammer.
Personalmente implementaría las arquitecturas en estos casos:

MVC en un sistema pequeño a la medida, tal vez con 100 a 200 transacciones concurrentes o para un producto empaquetado. También lo aplicaría en un sistema grande, pero solo en el "front-end".

MVC sobre MVVM también en sistemas medianos o empaquetados, tiene una ventaja sobre MVC es mucho más barato de implementar, entre sus desventajas está que consume mas recursos de tecnología.

MVA lo usaría en sistemas medianos, combinadola con servicios podría ser bastante flexible y escalable y podría servir para sistemas grandes.

MVP lo usaría en sistemas donde la interfaz visual no necesita ser muy interactiva como un sistema de reportería.

MVVM en sistemas medianos con bastante interactividad y si cuento con un equipo de desarrollo pequeño.

PAC HMVC si tengo un equipo grande de trabajo y estoy implementando un sistema con gran cantidad de funcionalidades de usuario.

Microservicios en sistemas grandes, con un equipo de trabajo mediano para un sistema con un nivel medio de interactividad o un equipo grande con un sistema bastante interactivo.