Ingénierie des composants internes d'un framework RAD... en tant que développeur PHP chez Nooku
Publié: 2022-03-11Chacun a son propre ensemble d'outils. En tant que développeur PHP, l'un de mes favoris est un framework de développement rapide d'applications appelé "Nooku". Selon les mots du groupe de développement : « Nooku est plus une boîte à outils de développement Web qu'un framework ».
Au cas où vous ne le connaîtriez pas, jetez un œil. Il s'agit d'un projet open source qui fait un usage intensif des modèles de conception acceptés par l'industrie pour produire des applications hautement composables qui sont facilement extensibles et réutilisables (initialement créées par l'un des principaux développeurs Joomla!). Prêt à l'emploi, Nooku vous offre de nombreux outils de développement d'applications rapides pour vous aider à faire démarrer vos projets plus rapidement. Un échantillon petit mais solide :
- Une implémentation par défaut de MVC où tout ce que vous avez à faire est d'écrire la mise en page (c'est ce qui m'a accroché)
- Disponibilité immédiate de HMVC
- Prise en charge de différents formats de sortie tels que JSON et XML pour toutes vos données (c'est-à-dire, exposez votre API en quelques minutes)
- Implémentations administratives et frontales par défaut
Au cœur de Nooku se trouve le principe de conception "Composition over Inheritance" (en fait, c'est le premier concept de la page d'introduction de Nooku. En une seule ligne : vous devez viser à composer (ou additionner) la fonctionnalité de plusieurs objets pour créer des une sorte d'objet composite, plutôt que de s'appuyer sur des sous-classes.
Ce principe vous permet d'écrire moins de code et conduit souvent à des solutions assez élégantes. Alors, comment est-il exactement promu? Eh bien, au niveau du code, les meilleurs exemples proviennent de l'utilisation de Mixins et d'identificateurs de ressources/services. Nous allons jeter un coup d'oeil.
Le Mixin
Avant PHP 5.4, le langage n'avait pas de concept de Traits . Ce sont des structures de type classe qui, lorsqu'elles sont "utilisées" par un objet, fournissent un certain type de fonctionnalité (similaire à l'héritage multiple). Nooku résout ce problème depuis des années (depuis PHP 5.2) avec le Mixin .
Le Mixin vous permet non seulement de composer des objets ensemble, mais il ajoute également les méthodes de chaque objet mixte à l'interface de l'objet composite. L'objet utilisant le mixin semble "hériter" des méthodes de l'objet mixte.
/** * 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; }
Presque tous les objets de Nooku ont cette capacité car ils étendent la classe de base KObject qui a défini la méthode mixin .
Les principales classes de l'architecture de contrôleur de Nooku sont également issues de KObject. Le contrôleur abstrait est la classe KControllerAbstract et par inspection, vous pouvez voir qu'il tire immédiatement parti de la capacité de mixage. Chaque fois qu'une instance de cette classe est construite, les fonctionnalités KMixinCommand et KMixinBehavior sont immédiatement ajoutées à son interface. Par conséquent, chaque contrôleur de Nooku est composé de fonctionnalités de gestion de la chaîne de commande et du comportement via les objets respectifs.
Pourquoi le K devant tous les noms de classes ? La bibliothèque principale de Nooku porte le nom de code "Koowa".
Pour en revenir au contrôleur Nooku : la classe KMixinBehavior contient toutes les pièces pour donner à KControllerAbstract la possibilité de charger des comportements spécifiques au moment de l'exécution. Les stratégies comportementales sont des classes qui décrivent un processus ou une logique qui peut être séparé et utilisé par d'autres classes (par exemple, modifiable, ordonnable). KMixinBehavior est assez simple et n'a que quatre méthodes : getBehavior, hasBehavior, addBehavior et getBehaviors. Et c'est tout ce dont nous avons besoin pour donner à un objet la capacité de gérer et d'encapsuler différentes stratégies comportementales.
De même, KMixinCommand n'a que trois méthodes : getCommandContext, getCommandChain, setCommandChain. Si vous ne l'aviez pas deviné, ces trois méthodes permettent à KControllerAbstract d'implémenter une chaîne de commandes, mais lui permettent de le faire à l'exécution.
Vous pouvez considérer ce mélange comme une simple addition arithmétique :
Nous donne une interface qui ressemble à ceci :
Par définition, les classes abstraites sont censées être étendues et ainsi, par la magie de l'héritage, tous les objets qui sont des enfants ou des instances de KControllerAbstract ont également la possibilité d'ajouter des comportements et une chaîne de commandes au moment de l'exécution.
Cela paraît bien. Mais qu'est-ce que cela veut vraiment dire? En bref, Nooku fournit des fonctionnalités en composants ; c'est-à-dire que Nooku vous permet de modulariser vos fonctionnalités et de composer des fonctionnalités entre les modules lors de l'exécution.

Ces deux exemples servent à démontrer la composition. Ils servent également à démontrer la prise en charge du framework Nooku RAD pour une composition plus poussée en son cœur. C'est un avantage important. Les méthodes ajoutées à KControllerAbstract ci-dessus prennent en charge le "Strategy Design Pattern" en donnant aux développeurs les outils pour encapsuler ce qui varie avant qu'une ligne de code ait été écrite. Le fait que la méthode mixin() fasse partie de chaque extension de KObject signifie que vous pouvez facilement définir et ajouter d'autres interfaces de gestion comportementale à la plupart des objets lors de l'exécution.
Identificateurs et localisateurs de service et de ressource : dissocier mon nom de classe de mon objet
Les identificateurs et localisateurs de services et de ressources dans Nooku fournissent également un support puissant pour la séparation des préoccupations.
Encore une fois, regardons à nouveau KObject, mais aussi KService. Nous pouvons traiter la plupart des choses dans Nooku comme un service ou une ressource, et en tant que telles les instancier et les interroger exactement de la même manière.
Considérez un service comme quelque chose dont vous obtenez une ressource. Tous les services sont des ressources mais toutes les ressources ne sont pas des services
Lorsque vous allez à l'épicerie et achetez un produit, considérez le magasin comme le Service, c'est-à-dire une collection d'articles que vous pouvez parcourir ; et le produit comme Ressource, c'est-à-dire une logique d'élément/solution unique qui peut être :
- regardé spécifiquement (lire) (par exemple, regarder une boîte de soupe aux tomates)
- déplacé dans le magasin ( édité ) (par exemple, déplacer la soupe vers l'allée des fruits et légumes)
- ajouté ou retiré de l'inventaire du magasin ( Ajouter et supprimer ) (par exemple, ajouter un nouveau type de soupe et se débarrasser de la tomate)
En poussant cet exemple encore plus loin, imaginez que l'épicerie a un rayon franchisé et que vous voulez être en affaires. Dans cette situation, le service est le département franchisé et la ressource est l'épicerie que vous achetez. Il s'agit essentiellement d'une classification contextuelle. Dans son ensemble, ceci est connu sous le nom de modèle d'action BREAD (vous verrez chacun d'entre eux représenté entre KControllerService et KControllerResource précédé de '_action', c'est-à-dire _actionRead()).
Un modèle peut être un service, un objet de table peut être considéré comme un service, une triade MVC spécifique est instanciée comme une ressource ou un service, tandis qu'un enregistrement spécifique résultant de l'interrogation du service peut être considéré comme une ressource.
Chaque objet dans Nooku est une composition d'objets dans la mesure où chacun d'eux contient une référence aux services instanciés de l'application entière dans un 'conteneur de services' et une méthode pour accéder aux services appelée getService(). Tout ce qui est requis par la méthode KObject::getService() est que nous transmettions un identifiant de ressource valide et elle renverra un service instancié prêt à l'emploi.
Dans le développement rapide d'applications PHP, les identificateurs de ressources nous offrent un moyen puissant de dissocier l'instanciation d'un objet de son nom de classe, et ainsi de fournir des alias pour cette identification. Cela a des implications importantes sur la maintenabilité d'une application. Grâce à l'aliasing, un développeur peut changer la classe utilisée par chaque objet qui est instancié avec un identifiant donné en ajoutant une ligne de code avec KService::addAlias().
Un exemple d'identifiant de ressource que nous connaissons est l'URI ou Uniform Resource Identifier :
Il s'agit de toutes les informations nécessaires à KService pour localiser et charger la classe appropriée. Ces pièces correspondent aux conventions de nommage et de placement des classes de Nooku qui offrent une prévisibilité du placement et de l'instanciation. L'exemple d'identifiant ci-dessus (com://site/user.database.table.user) tente de charger le fichier /components/com_user/databases/tables/user.php, dont le nom de classe est ComUserDatabaseTableUser. Incidemment, si le fichier n'existe pas, le framework vous donnera un objet de table par défaut et le construira en fonction des conventions de nommage et de schéma d'identification de la base de données (cela m'a encore plus accroché). Comme mentionné précédemment, KService vous permet également de définir des alias pour vos identifiants. Utilisation KService::setAlias('maindbaseadapter','com://admin/default.database.adapter.mysqli')
; chargeons un objet db avec KService::getService('maindbaseadapter')
.
Cela nous donne le découplage dont nous parlions et offre un avantage marqué dans la maintenance et l'extension de nos applications. Nous sommes libres de créer des applications autres que « site » et « admin » si nécessaire et, grâce aux identifiants décrits ici, nous pouvons facilement utiliser des services situés dans d'autres applications pour aider nos solutions à répondre à leurs besoins. Encore une fois, c'est un autre exemple de la façon dont Nooku fournit aux développeurs et équipes PHP et RAD un support pour la composition non seulement d'objets de classe unique, mais de services et d'applications entiers… gratuitement.
Résumé
Avec la composition sur l'héritage en son cœur ; les compositions et structures intelligentes préexistantes qui existent pour soutenir d'autres amalgames ; et l'architecture orientée service gratuite avec les identifiants décrits ici, Nooku fournit un framework RAD puissant avec une longueur d'avance significative sur n'importe lequel de ses outils de développement PHP homologues.