Ingeniería interna de un marco RAD... como desarrollador de PHP con Nooku
Publicado: 2022-03-11Cada uno tiene su propio conjunto de herramientas. Como desarrollador de PHP, uno de mis favoritos es un marco de desarrollo rápido de aplicaciones llamado "Nooku". En palabras del grupo de desarrollo: “Nooku es más un conjunto de herramientas de desarrollo web que un marco”.
En caso de que no estés familiarizado con él, échale un vistazo. Es un proyecto de código abierto que hace un uso intensivo de los patrones de diseño aceptados por la industria para producir aplicaciones altamente compuestas que son fácilmente extensibles y reutilizables (inicialmente creadas por uno de los principales desarrolladores de Joomla!). Listo para usar, Nooku le brinda una gran cantidad de herramientas de desarrollo de aplicaciones rápidas para ayudar a que los proyectos despeguen más rápido. Una pequeña, pero fuerte muestra:
- Una implementación predeterminada de MVC donde todo lo que necesita hacer es escribir el diseño (esto es lo que me enganchó)
- Disponibilidad de HMVC de inmediato
- Soporte para diferentes formatos de salida como JSON y XML para todos sus datos (es decir, exponga su API en minutos)
- Implementaciones administrativas y front-end predeterminadas
En el corazón de Nooku se encuentra el principio de diseño de "Composición sobre herencia" (de hecho, es el primer concepto en la página de introducción de Nooku. En una línea: debe intentar componer (o sumar) la funcionalidad de múltiples objetos para crear algunos una especie de objeto compuesto, en lugar de depender de subclases.
Este principio le permite escribir menos código y, a menudo, conduce a algunas soluciones bastante elegantes. Entonces, ¿cómo se promociona exactamente? Bueno, a nivel de código, los mejores ejemplos vienen a través del uso de Mixins e Identificadores de Recursos/Servicios. Vamos a ver.
la mezcla
Antes de PHP 5.4, el lenguaje no tenía el concepto de Rasgos . Estas son estructuras similares a clases que, cuando son 'utilizadas' por un objeto, proporcionan algún tipo de funcionalidad (similar a la herencia múltiple). Nooku ha estado resolviendo este problema durante años (desde PHP 5.2) con Mixin .
Mixin no solo le permite componer objetos juntos, sino que también agrega los métodos de cada objeto mixto a la interfaz del objeto compuesto. El objeto que usa el mixin parece 'heredar' los métodos del objeto mezclado.
/** * Mixin an object * * When using mixin(), the calling object inherits the methods of the mixed * in objects, in a LIFO order. * * @param KMixinInterface $object An object that implements KMinxInterface * @return KObject */ public function mixin(KMixinInterface $object) { $methods = $object->getMixableMethods($this); foreach($methods as $method) { $this->_mixed_methods[$method] = $object; } // Set the mixer $object->setMixer($this); return $this; }
Casi todos los objetos en Nooku tienen esta habilidad porque extienden la clase base KObject que definió el método mixin .
Las principales clases en la arquitectura del controlador de Nooku también descienden de KObject. El controlador abstracto es la clase KControllerAbstract y, al inspeccionarlo, puede ver que aprovecha la capacidad de mezcla de inmediato. Cada vez que se construye una instancia de esta clase, la funcionalidad KMixinCommand y KMixinBehavior se agrega inmediatamente a su interfaz. En consecuencia, cada controlador en Nooku se compone de la funcionalidad de gestión de comportamiento y cadena de comandos a través de los objetos respectivos.
¿Por qué la K delante de todos los nombres de las clases? La biblioteca principal de Nooku tiene el nombre en código "Koowa".
Volviendo al controlador Nooku: la clase KMixinBehavior contiene todas las piezas para dar a KControllerAbstract la capacidad de cargar comportamientos específicos en tiempo de ejecución. Las estrategias de comportamiento son clases que describen un proceso o lógica que puede ser separado y utilizado por otras clases (por ejemplo, editable, ordenable). KMixinBehavior es bastante simple y solo tiene cuatro métodos: getBehavior, hasBehavior, addBehavior y getBehaviors. Y eso es todo lo que necesitamos para darle a un objeto la capacidad de manejar y encapsular diferentes estrategias de comportamiento.
De manera similar, KMixinCommand tiene solo tres métodos: getCommandContext, getCommandChain, setCommandChain. Si no lo había adivinado, estos tres métodos proporcionan a KControllerAbstract la capacidad de implementar una cadena de comandos, pero le permiten hacerlo en tiempo de ejecución.
Puedes pensar en esta mezcla como una simple suma aritmética:
Nos da una interfaz que se ve así:
Por definición, las clases abstractas están destinadas a extenderse y, por la magia de la herencia, todos los objetos que son hijos o instancias de KControllerAbstract también obtienen la capacidad de agregar comportamientos y una cadena de comandos en tiempo de ejecución.
Suena bien. Pero, ¿qué significa eso realmente? En resumen, Nooku proporciona funcionalidad dividida en componentes; es decir, Nooku le permite modularizar su funcionalidad y componer funcionalidades a través de módulos en tiempo de ejecución.
Estos dos ejemplos sirven para demostrar la composición. También sirven para demostrar el soporte del marco Nooku RAD para una mayor composición en su núcleo. Esta es una ventaja importante. Los métodos agregados a KControllerAbstract anteriormente admiten el "Patrón de diseño de estrategia" al brindar a los desarrolladores las herramientas para encapsular lo que varía antes de que se haya escrito una línea de código. El hecho de que el método mixin() sea parte de cada extensión de KObject significa que puede definir y agregar fácilmente otras interfaces de administración de comportamiento a la mayoría de los objetos en tiempo de ejecución.

Identificadores y localizadores de servicios y recursos: desacople el nombre de mi clase de mi objeto
Los identificadores y localizadores de servicios y recursos en Nooku también brindan un poderoso soporte para la separación de preocupaciones.
Una vez más, echemos un vistazo a KObject, pero también a KService. Podemos tratar la mayoría de las cosas en Nooku como un servicio o un recurso y, como tal, instanciarlas e interrogarlas exactamente de la misma manera.
Piense en un servicio como algo de lo que obtiene un recurso. Todos los servicios son recursos pero no todos los recursos son servicios
Cuando vaya al supermercado y compre un producto, piense en la tienda como el Servicio, es decir, una colección de artículos que puede examinar ; y el producto como el Recurso, es decir, una única lógica de artículo/solución que puede ser:
- mirado específicamente (leer) (p. ej., mirar una lata de sopa de tomate)
- movido alrededor de la tienda ( Editado ) (p. ej., mover la sopa al pasillo de productos)
- agregado o eliminado del inventario de la tienda ( Agregar y Eliminar ) (p. ej., agregar un nuevo tipo de sopa y deshacerse del tomate)
Llevando este ejemplo aún más lejos, imagina que la tienda de comestibles tiene un departamento de franquicias y quieres estar en el negocio. En esa situación, el Servicio es el departamento de franquicias y el recurso es la tienda de comestibles que compra. Es en gran medida una clasificación contextual. En conjunto, esto se conoce como el patrón de acción BREAD (Verá cada uno de estos representados entre KControllerService y KControllerResource con '_action', es decir, _actionRead()).
Un modelo puede ser un servicio, un objeto de tabla se puede considerar como un servicio, una tríada MVC específica se instancia como un recurso o servicio, mientras que un registro específico resultante de interrogar al servicio se puede considerar como un recurso.
Cada objeto en Nooku es una composición de objetos en el sentido de que cada uno de ellos contiene una referencia a los servicios instanciados de toda la aplicación en un 'contenedor de servicios' y un método para acceder a los servicios llamado getService(). Todo lo que requiere el método KObject::getService() es que pasemos un identificador de recurso válido y devolverá un servicio instanciado listo para usar.
En el desarrollo rápido de aplicaciones PHP, los identificadores de recursos nos brindan una forma poderosa de desacoplar la creación de instancias de un objeto de su nombre de clase y, por lo tanto, proporcionar alias para esa identificación. Esto tiene implicaciones importantes en la mantenibilidad de una aplicación. A través de la creación de alias, un desarrollador puede cambiar la clase utilizada por cada objeto que se instancia con un identificador dado agregando una línea de código con KService::addAlias().
Un ejemplo de un identificador de recursos con el que estamos familiarizados es el URI o el Identificador uniforme de recursos:
Esta es toda la información necesaria para que KService localice y cargue la clase adecuada. Estas piezas coinciden con las convenciones de ubicación y nomenclatura de clase de Nooku, que brindan previsibilidad de ubicación e instanciación. El ejemplo de identificador de arriba (com://site/user.database.table.user) intenta cargar el archivo /components/com_user/databases/tables/user.php, que tiene un nombre de clase de ComUserDatabaseTableUser. Por cierto, si el archivo no existe, el marco le dará un objeto de tabla predeterminado y lo construirá en función de las convenciones de nombres de bases de datos y esquemas de identificación (esto me enganchó un poco más). Como se mencionó anteriormente, KService también le permite establecer alias para sus identificadores. Utilizando KService::setAlias('maindbaseadapter','com://admin/default.database.adapter.mysqli')
; nos permite cargar un objeto db con KService::getService('maindbaseadapter')
.
Esto nos da el desacoplamiento del que hablamos y proporciona una marcada ventaja en el mantenimiento y extensión de nuestras aplicaciones. Somos libres de crear aplicaciones que no sean 'sitio' y 'administrador' si es necesario y, a través de los identificadores descritos aquí, podemos usar fácilmente los servicios ubicados en otras aplicaciones para ayudar a que nuestras soluciones cumplan con sus requisitos. Nuevamente, este es otro ejemplo de cómo Nooku brinda a los desarrolladores y equipos de PHP y RAD soporte para la composición no solo de objetos de una sola clase, sino de servicios y aplicaciones completos... de forma gratuita.
Resumiendo
Con composición sobre herencia en su corazón; las composiciones y estructuras inteligentes y preexistentes que existen para soportar futuras amalgamas; y la arquitectura gratuita orientada a servicios con los identificadores descritos aquí, Nooku proporciona un poderoso marco RAD con una ventaja significativa sobre cualquiera de sus herramientas de desarrollo PHP similares.