Controladores y rutas en Anssible Framework

Por @jalexiscv, Hace 5 meses.

¿Que es un controlador? Un controlador es simplemente un archivo de clase cuyo nombre se puede asociar con una URI. El Controlador actúa como intermediario entre el Modelo y la Vista, gestionando el flujo de información entre ellos y las transformaciones para adaptar los datos a las necesidades de cada uno. Recibe los eventos de entrada (un clic, un cambio en un campo de texto, etc.).

Contiene reglas de gestión de eventos, del tipo "SI Evento Z, entonces Acción W". Estas acciones pueden suponer peticiones al modelo o a las vistas. Una de estas peticiones a las vistas puede ser una llamada al método "Actualizar()". Una petición al modelo puede ser "Obtener_tiempo_de_entrega ( nueva_orden_de_venta )".

En la grafica se puede observar como el controlador 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' (Middleware).

Aunque se pueden encontrar diferentes implementaciones de MVC, el flujo de control que se sigue generalmente es el siguiente:

  1. El usuario interactúa con la interfaz de usuario de alguna forma (por ejemplo, el usuario pulsa un botón, enlace, etc.)
  2. El controlador recibe (por parte de los objetos de la interfaz-vista) la notificación de la acción solicitada por el usuario. El controlador gestiona el evento que llega, frecuentemente a través de un gestor de eventos (handler) o callback.
  3. El controlador accede al modelo, actualizándolo, posiblemente modificándolo de forma adecuada a la acción solicitada por el usuario (por ejemplo, el controlador actualiza el carro de la compra del usuario). Los controladores complejos están a menudo estructurados usando un patrón de comando que encapsula las acciones y simplifica su extensión.
  4. El controlador delega a los objetos de la vista la tarea de desplegar la interfaz de usuario. La vista obtiene sus datos del modelo para generar la interfaz apropiada para el usuario donde se reflejan los cambios en el modelo (por ejemplo, produce un listado del contenido del carro de la compra). El modelo no debe tener conocimiento directo sobre la vista. Sin embargo, se podría utilizar el patrón Observador para proveer cierta indirección entre el modelo y la vista, permitiendo al modelo notificar a los interesados de cualquier cambio. Un objeto vista puede registrarse con el modelo y esperar a los cambios, pero aun así el modelo en sí mismo sigue sin saber nada de la vista. Este uso del patrón Observador no es posible en las aplicaciones Web puesto que las clases de la vista están desconectadas del modelo y del controlador. En general el controlador no pasa objetos de dominio (el modelo) a la vista aunque puede dar la orden a la vista para que se actualice. Nota: En algunas implementaciones la vista no tiene acceso directo al modelo, dejando que el controlador envíe los datos del modelo a la vista. Por ejemplo en el MVC usado por Apple en su framework Cocoa. Suele citarse como Modelo-Interface-Control, una variación del MVC más puro [li]La interfaz de usuario espera nuevas interacciones del usuario, comenzando el ciclo nuevamente...

En teoría y en relación a los conceptos anteriormente expresados tener un controlador como clase programática implicaría que cada método de dicha clase debería de corresponder a una ruta explorable del modelo y la posibilidad de la trasmisión de parámetros al método mediante segmentos definidos de la URI. Por lo general, existe una relación de uno a uno entre una cadena de URL y su método / clase de controlador correspondiente. Los segmentos de un URI normalmente siguen este patrón:

Como en la grafica se puede observar el primer elemento de la URI corresponde al controlador, en tanto generalmente, el segundo segmento está reservado para el nombre del método, y el tercero y subsecuentes a pasos de variable si estas se definen en el prototipado del software, en la arquitectura HMVC, esto continua siendo valido si el controlador esta ubicado como un elemento de la aplicación principal, mas si el controlador corresponde a un elemento al interior de un módulo este orden varia levemente de tal modo que el primer elemento de la URI corresponde al módulo, el segundo al controlador, el tercero al método y los demás a pasos por variable (Se recuerda que a esta la fecha la máxima longitud de una URL es 254 caracteres lo cual limita la cantidad de información a trasferir mediante una URL adicional a esto los parámetros trasferidos vía URL pueden ser fácilmente modificables desde el cliente).

Configuracion del enrutamiento

Seria posible automatizar que cargado un controlador sus métodos se trasformen en rutas automáticamente, pero esto reduce la precisión del desarrollo y da lugar a la existencia de métodos ruta que existan naturalmente y no por definición, también limitaría la trazabilidad de la rutas de navegación y su dinamismo, pues no se podrían crear rutas legibles, si estas obligatoriamente no coincidieran con un método asociado a un controlador, por estos y otros motivos se opto por establecer la rutas de navegación como elementos dinámicos definibles mediante la configuración de la aplicación principal o la configuración individual del modulo en ejecución.

Para tal propósito en el directorio de configuración ya sea de la aplicación (app / Config / Routes.php) o de cualquier modulo creado(app /Modules/DemoX/Config/Routes.php), el framework buscara específicamente un archivo llamado Routes.php, el cual contendrá una variable derivada del servicio de rutas, y adicionara específicamente las rutas navegables a implementar, debe recordar que cada modulo conceptualmente es un grupo especifico de rutas y este se asociara a un nombre de espacios(namespace) para la carga de los controladores correspondientes, como se visualiza en el siguiente ejemplo:

Una ruta o subruta en el caso de los módulos simplemente toma el URI de la izquierda y lo asigna al controlador y al método de la derecha, junto con cualquier parámetro que deba pasarse al controlador. El controlador y el método deben enumerarse de la misma manera que usaría un método estático, separando la clase con espacio de nombres completo y su método con dos puntos dobles, como Clase::Metodo (DemoX::componenteA). Si ese método requiere que se le pasen parámetros, entonces se enumerarán después del nombre del método, separados por barras diagonales usando $1 o $1/$2 según se haga necesario en función de los parámetros a trasferir y en función de los marcadores de posición para dichos valores, ejemplo:

A este punto esta mas que claro de que el par Ruta -> Método, por definición permite crear dinámicamente rutas sin importar el nombre del método que ejecuten siempre y cuando se respeten los parámetros asociados al método ejecutable, y que cada parámetro trasferido en la ruta puede ser leído por la plataforma como un marcador de posición donde es posible implementar algunos marcadores de posición por tipo según el siguiente listado.

  • (:any) - Coincidirá con todos los caracteres desde ese punto hasta el final del URI. Esto puede incluir varios segmentos de URI.
  • (:segment) - Coincidirá con cualquier carácter excepto por una barra inclinada (/) que restringe el resultado a un solo segmento.
  • (: num) - Coincidirá con cualquier número entero.
  • (:alpha) - Coincidirá con cualquier cadena de caracteres alfabéticos
  • (:alphanum) - Coincidirá con cualquier cadena de caracteres alfabéticos o enteros, o cualquier combinación de los dos.
  • (:hash) - Es lo mismo que (: segmento) , pero se puede usar para ver fácilmente qué rutas usan ID con hash (consulte los documentos del modelo ).

De esta forma la totalidad de las rutas y sub rutas cargadas corresponderá al mapeado de la aplicación y todo lo ejecutable en ella (módulos y componentes). También proporcionará un ligero aumento de rendimiento, ya que solo se almacenan las rutas que coinciden con el método de solicitud actual, lo que resulta en menos rutas para escanear al intentar encontrar una coincidencia y generar una respuesta. Si lo prefiere, puede utilizar expresiones regulares para definir sus reglas de enrutamiento. Se permite cualquier expresión regular válida, al igual que las referencias inversas pero deberá definirlas mediante el uso de un marcador de posición personalizado (custom place holder). Para lo cual la clase Ruta esta provista de un método denominado .addPlaceHolder(); y se puede usar discrecionalmente en rutas y sub rutas como se visualiza en el siguiente ejemplo:

Enrutamiento inverso

El enrutamiento inverso le permite definir el controlador y el método, así como cualquier parámetro, al que debe ir un enlace, y hacer que el enrutador busque la ruta actual hacia él. Esto permite que las definiciones de ruta cambien sin tener que actualizar el código de su aplicación. Por lo general, esto se usa dentro de las vistas para crear enlaces. Por ejemplo, si tiene una ruta a una galería de fotos a la que desea vincular, puede usar la route_to() función de ayuda para obtener la ruta actual que debe usarse. El primer parámetro es el controlador y el método totalmente calificado, separados por dos puntos dobles (: :), muy parecido a lo que usaría al escribir la ruta inicial en sí. Cualquier parámetro que deba pasarse a la ruta se pasa a continuación, en términos simples route_to() reconstruye la ruta pero de igual forma la ruta deberá estar definida en la configuración (Routes.php) para que este funcione ejemplo:

Como en todo diseño esto trae sus pros y contras, si está seguro del método definitivo a usar en el controlador definitivo, route_to() es el camino corto a generar las URL de los enlaces en una forma eficiente, pero si este método cambiara o el controlador cambiara se vería obligado a rescribir el código de las vistas donde halla implementado este enrutamiento inverso, tal cual como si hubiera cambiado una URL predefinida como ruta en la forma normal, por tal motivo aunque es posible hacerlo y es una de las posibilidades que el framework debe proveer a sus usuarios conceptualmente añade poco veneficio operativo (usar el enrutamiento inverso es una temática discrecional).

Rutas por referencia

Puede crear rutas por referencia asignándoles un nombre lo cual hará proceso de codificación sea más eficiente y aportar solides al modelo, si la ruta, la clase o el método cambiaran durante el tiempo de codificación, el route_to(); crearía enlaces actualizados automáticamente sin la necesidad de reescribir las vistas, para implementar el ruteado por referencia basta con asignar un alias a las rutas como se muestra en el siguiente ejemplo:

Usar la generación de enlaces por rutas referenciadas es una técnica ampliamente recomendable, y garantizara que si se cambia la ruta misma, el controlador o el método que se ejecutan, las rutas se regeneraran sin necesidad de reescribir el código fuente de las vistas.

Modularizaciòn de rutas

Modularizar rutas es una temática directa ya que modularizar las rutas es básicamente agrupar las rutas por módulos, mediante el uso del método .set_Group(); de la clase Rutas, el nombre del grupo se convierte en un segmento que aparece antes de las rutas definidas dentro del grupo. Esto le permite reducir la escritura necesaria para construir un extenso conjunto de rutas que comparten la cadena de apertura, como cuando se construye un área administrativa. Si el grupo se denomina contabilidad, cualquier ruta definida tendrá el segmento “contabilidad” como prefijo automático, a continuación se mostraran algunas rutas y como serian sus definiciones:

Con la salvedad de que el ejemplo anterior buscaría ejecutar un controlador denominado Contabilidad, el cual estaría ubicado en el directorio principal de controladores App/Controllers/Contabilidad dominio por defecto de la Aplicación principal en ejecución. Mas si contabilidad se tratase de un modulo el dominio de donde se buscaría cargar los controladores sería algo como App/Controllers/Modules/DemoX/Contabilidad y se haría del siguiente modo:

Comentarios

Esta publicación no posee opiniones, te invitamos a ser el primero en comentarla.

Notas y referencias

Copyright © 2018 - 2038 Todos los derechos reservados, se prohíbe su reproducción total o parcial, así como su traducción a cualquier idioma sin la autorización escrita de su titular.Términos y condiciones | Políticas de privacidad | Publicidad | Cookies | Más |

XXL
XL
LG
MD
SM
XS