Entendiendo M de MVC y sus problemas

Introducción

MVC por sus siglas en ingles (Model- View — Controller) fue introducido por Trygve Reenskaug en los años 70. Y tenía un concepto muy diferente al que hoy se menciona por toda la red. Y es que dicho patrón ha sido adaptado a las necesidades de aplicaciones web, evolucionando de tal forma que en la actualidad muchos frameworks y aplicaciones lo implementan en su arquitectura de una forma totalmente diferente a la idea original.

Si bien es cierto ha ayudado a resolver muchos problemas; separando responsabilidades y haciendo que el sistema sea mucho más modular, de tal forma que permita agregar nuevas características a cada capa; cada vez las aplicaciones demandan muchas más tareas, responsabilidades, y el concepto original del patrón MVC, adaptado a la web, ya no se ajusta a las necesidades de las aplicaciones actuales.

Modelo Vista Controlador

El concepto original de MVC nos define tres capas y cada una de ellas tiene asignado una tarea. Esto permite que cada capa sea “fácil de entender”, mantener y se puedan añadir nuevas características, y los desarrolladores y diseñadores puedan trabajar de forma simultánea sobre su capa correspondiente, evitando así el código espagueti. Veamos las siguientes figuras:

Figura 1. Tomado de la página web: //miblogtecnico.files.wordpress.com/2012/07/mvc.jpg
Figura 2. Tomado de la página web: //i.stack.imgur.com/Beh3a.png

Dado que el concepto original de MVC fue establecido para el diseño de software con interfaz gráfica de usuario (sus siglas en ingles GUI), MVC ha tenido que ir evolucionando para adaptarse a las necesidades de las aplicaciones web. Claramente se puede ver una marcada diferencia entre las figuras mostradas anteriormente. Mientras que en la primera figura se ve de forma general a MVC, en la segunda se puede ver que MVC trabaja conjuntamente con otras capas (otros patrones de diseño cómo dispatcher pattern, por ejemplo).

Definiciones

Modelo

Según Wikipedia: Es la representación de la información con la cual el sistema opera, por lo tanto gestiona todos los accesos a dicha información, tanto consultas como actualizaciones, implementando también los privilegios de acceso que se hayan descrito en las especificaciones de la aplicación (lógica de negocio).

Según CackePhp: El modelo representa la parte de la aplicación que implementa la lógica de negocio. Esto significa que es responsable de la recuperación de datos convirtiéndolos en conceptos significativos para la aplicación, así como su procesamiento, validación, asociación y cualquier otra tarea relativa a la manipulación de dichos datos.


Controlador

Según Wikipedia: Responde a eventos (usualmente acciones del usuario) e invoca peticiones al ‘modelo’ cuando se hace alguna solicitud sobre la información (por ejemplo, editar un documento o un registro en una base de datos). También puede enviar comandos a su ‘vista’ asociada si se solicita un cambio en la forma en que se presenta el ‘modelo’ (por ejemplo, desplazamiento o scroll por un documento o por los diferentes registros de una base de datos), por tanto se podría decir que el ‘controlador’ hace de intermediario entre la ‘vista’ y el ‘modelo’

Según CackePhp: La capa del controlador gestiona las peticiones de los usuarios. Es responsable de responder la información solicitada con la ayuda tanto del modelo como de la vista.


Vista

Según Wikipedia: Presenta el ‘modelo’ (información y lógica de negocio) en un formato adecuado para interactuar (usualmente la interfaz de usuario) por tanto requiere de dicho ‘modelo’ la información que debe representar como salida.

Según CackePhp: La vista hace una presentación de los datos del modelo estando separada de los objetos del modelo. Es responsable del uso de la información de la cual dispone para producir cualquier interfaz de presentación de cualquier petición que se presente.


Mi criterio sobre el modelo y sus problemas

En cierta medida, estoy un poco de acuerdo con los conceptos de Vista y Controlador. Sin embargo, con el Modelo; sobre el cual hoy discutiré, y el concepto de Modelo; definido en muchas fuentes de información, en la actualidad no tengo una total convicción de que esté bastante clara ni sean las más acertadas. 
Antes de cambiar mi perspectiva con respecto al Modelo y que hoy por hoy lo tengo bien claro; el concepto me parecía “bastante sencillo”:

“El modelo se encarga de representar la parte de la aplicación que implementa la lógica de negocio” y es donde también se maneja la persistencia a la base de datos.

Sin embargo, la experiencia ha hecho que las dudas siempre me asalten cuando he desarrollado una aplicación, por ejemplo: 
 
 Una clase que se encargue de enviar un correo electrónico, 
¿Dónde pertenece? ¿En el modelo? o ¿En el controlador?

Nota: Taylor Otwell también nos menciona que estas preguntas, muchos de los desarrolladores “novatos”, se formulan.

Y es esto, un ejemplo de otros tantos, que me han llevado a cambiar de parecer y re-considerar que el concepto de Modelo definido en muchas páginas web, o inclusive en libros, es demasiado ambiguo. Porque a la final nunca terminaba de entender que significaba “lógica de negocio” y tampoco tenía bien claro que clase debería ponerla en el modelo.

Y no soy el único que considera que es un concepto poco claro y que no aporta mucho para desarrollar aplicaciones escalables. De hecho, Taylor Otwell autor del framework Laravel para php, también lo menciona en su libro laravel 4 from apprentice to artisan. Haré mención sobre esto más adelante.

Entendiendo la lógica de negocio

Otra definición de lógica de negocio

Una definición adaptada:

La lógica de negocio representa la información de _las reglas de negocio_ de una entidad real, en términos de algoritmos e información codificada. “El modelo” es la capa que se encarga de llevar a cabo dicha representación a través de algoritmos computacionales, de tal forma que la información se pueda manipular en cualquier instante y pueda ser almacenada o extraída de una base de datos u otro medio de almacenamiento.

Y ahora, ¿qué son las reglas de negocio?

Definición de las reglas de negocio

Según wikipedia, y que considero es un concepto bastante claro y acertado:
Describe las políticas, normas, operaciones, definiciones y restricciones presentes en una organización y que son de vital importancia para alcanzar los objetivos misionales.

En resumen: Son las directrices de una empresa. Pero hay que tener bien claro que este concepto se atañe al mundo de negocios y no a un software en particular.

Entendiendo las reglas de negocio a través de ejemplo

  • Facturar algún producto,
  • Llevar la contabilidad,
  • Manejar reclamos,
  • Despachar productos,
  • etc.

Estas reglas de negocio deben ser representadas en la lógica de negocio para su inclusión en aplicaciones de software; es aquí donde entra en acción el Modelo y su concepto.

1er Caso. Tienda que no dispone de un sistema web para facturación.

Hay una tienda que venden zapatos deportivos y tienen ciertas reglas de negocio que deben ser aplicadas antes de facturar un producto adquirido por el cliente. Estas reglas, propias del negocio podrían ser:

1. Aplicar descuentos; ya sea por ofertas de temporada, o porque es cliente premium o frecuente, o porque el precio supera un límite base, etc.
2. Recibir un producto adicional como regalo; ya sea porque compra más de dos productos u otros.

Y otras más que no se mencionan porque no ayudarán para completar el ejemplo.

Cuando estas reglas de negocio son analizadas para aplicarse al cliente, se procede a realizar la factura, de forma manual, donde se ingresará:
1. Todos los datos del usuario
2. El precio real del producto adquirido
3. El Precio real del producto de regalo
4. Aplicar el descuento de temporada
5. Aplicar el descuento del 100% del producto de regalo
6. Calcular el precio total
7. Aplicar el iva correspondiente.
10. Calcular el precio final
11. Cobrar

Finalmente se emite una copia al cliente y la otra permanecerá en una carpeta para más tarde ser procesada por la tienda.

El documento emitido, guarda en sí, las reglas de negocio de la tienda además de información adicional como valores de costos, impuestos, entre otros. Sin embargo, para haber llegado a este punto de guardar toda esta información en la factura, se debieron llevar a cabo varias tareas que implícitamente estaban embebidas en el proceso de facturación, pero que no forman parte de las reglas de negocio. Por ejemplo, ingresar los datos de usuario, verificar el precio de los productos, realizar el cálculo de los valores, etc.

2do Caso. Tienda que dispone de un sistema web para facturación.

Ahora imaginemos todo el proceso anterior, pero que la tarea de facturar ahora se la quiere realizar a través de una aplicación web.
Como se mencionó en el caso anterior, la factura guarda en si la información del usuario, valores, etc. Inclusive, de forma implícita, las reglas de negocio. Las mismas tareas que estaban asociadas en el proceso de facturación, y que se hacían de forma manual, ahora las debe realizar la aplicación. El usuario únicamente ingresa los datos a través de la aplicación y ésta será la encargada de procesar toda la información y devolver un resultado.

Entonces teniendo en cuenta lo anterior, procedemos a diseñar la parte que se encargaría de la lógica de negocio. En primera instancia necesitaríamos una tabla de la base de datos para almacenar la información de la factura, y también la clase responsable de manipular la información de la factura y que formará parte de nuestro modelo.

1. El nombre de la tabla será Factura donde almacenará toda la información que corresponde a la factura.
2. En nuestra capa modelo, tendremos una clase que se encargue de procesar las reglas de negocio y transformarla en conceptos significativos para la aplicación (lógica de negocio). Entonces creamos una clase con nombre FacturaModelo.

FacturaModelo es nuestra clase que se encargará de: _convertir la información (reglas de negocio) en conceptos significativos para la aplicación, así como su procesamiento, validación, asociación, almacenamiento y cualquier otra tarea relativa a la manipulación de dichos datos (concepto definido en la documentación de cakephp para implementar la lógica de negocio)_.

Hasta ahora hemos cumplido con el concepto de modelo, sin embargo, si aún seguimos analizando y seguimos los conceptos de principios de diseño, esta clase; FacturaModelo , por un lado tiene muchas tareas que realizar; rompiendo así el principio de responsabilidad única; Y por otro, llevar a cabo tareas que no tienen que ver con la lógica de negocio. Así como se mencionó en el primer ejemplo, hay tareas embebidas en el proceso de facturación que no forman parte de las reglas de negocio, inclusive apareció otra más; la validación del tipo de datos ingresado por el usuario. Esto último forma parte de la lógica de la aplicación más no de la lógica de negocio. Y entonces, ¿Dónde deben ir dichas tareas? ¿Cómo no romper el principio de responsabilidad única?

Más adelante verémos como se trata de solucionar estos inconvenientes, que ha simple vista no parecen serlo.

Otro ejemplo real(Opcional)

Veamos un ejemplo real de una clase que debe realizar varias tareas.

Voy a tomar un ejemplo de un modelo hecho en javascript sobre nodejs: user.js. Obviamente estos ejemplos también se dan en otros lenguajes de programación.


/models
user.js

Y dentro del archivo user.js encontramos:

Se puede visualizar que el archivo user.js, tiene como responsabilidades: validar datos y generar una contraseña encriptada y autenticar y esto y aquello y un sin fin de responsabilidades. La conjunción “y”, que se repite muchas veces al detallar las responsabilidades, indica que este modelo user tiene muchas responsabilidades y está violando el principio de responsabilidad única, ojo no confundir con una tarea única. Bueno esto último es para otro tema.

Esta clase tiene muchas responsabilidades que forman parte de una lógica tanto de negocio cómo de aplicación y tampoco es responsabilidad de la capa controlador realizar tareas de validaciones, generar hash, etc.
El problema de esto es que hace que una clase sea difícil de mantener y fácilmente puede crecer en líneas de código de tal manera que sea difícil de depurar.

La solución al problema del Modelo y la lógica de negocio

Aplicando el concepto de modelo sin mayores consideraciones de las que se mencionan en muchas fuentes de información; obviamente información básica, esto hace que se construyan aplicaciones web que no son escalables; que rompen muchos principios de diseño; que son difíciles de mantener y de testear. Ahora, suponiendo que quedó claro que el concepto de modelo es demasiado ambiguo, porque no podemos responder a preguntas tales como ¿Qué clase debe hacer tal o cual tarea? ¿Dónde debe ir esta clase? o ¿Cómo no romper el principio de responsabilidad única? y que en definitiva:

El modelo se convierte en un cajón de sastre para todo el código encargado de la lógica de negocio

La solución es simple y sencilla:

Modularizar en capas tanto la lógica de negocio como la lógica de la aplicación de tal manera que se puedan asignar responsabilidades acorde a su funcionalidad. Entonces la solución al problema con el modelo es ya no tener una capa modelo y empezar a modularizar en más capas, según los requerimientos del sistema.

Y Taylor Otwell, autor del popular framework para php Laravel lo menciona de esta manera.

Bye, Bye Models
Is your models directory deleted yet?If not, get it out there! Let’s create a folder within our app directory that is simply named after our application.
Cita tomada del libro laravel 4 from apprentice to artisan

One key to organizing your project will be simply creating more folders, which correspond to namespaces within your Laravel application …Next, we create sub-folders within our “Snappy” directory that correspond to various “areas of responsibility”. Organizing Snappy

Perfecto, ahí está la solución al problema con el Modelo de MVC. Ya entendemos la teoría, al parecer quedo claro cuál es el problema; teóricamente se ha dado la solución. Sin embargo, es mejor llevar a la práctica estos conceptos y definiciones para entender de mejor manera y dar un paso más en nuestros diseños de aplicaciones web. Por lo tanto, en la próxima entrega; probablemente sean varias, hablaré de cómo estructurar aplicaciones web teniendo en cuenta las consideraciones dadas para solucionar problemas que se presentan con MVC, y así también cómo adaptar su estructura básica a nuestros requerimientos con los siguientes frameworks:
Expressjs | Hapijs | Laravel

Los dos primeros frameworks están enfocados para desarrolladores que se están moviendo en el mundo de nodejs y último para desarrolladores de aplicaciones utilizando php.

Conclusión

MVC está bien para aplicaciones pequeñas; obviamente considerando algunos cambios, pero para aplicaciones escalables ya no puede ser aplicado en su totalidad sino parcialmente, debiendo ser modificado de tal forma que cada una de las capas deban ser modularizadas.

Espero que sea de utilidad este artículo.

Saludos.

Nota final: Algunos ejemplos de sistemas modularizados.