[Ruby on Rails] Les modules, un bon moyen de factoriser son code - Version imprimable +- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org) +-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38) +--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51) +--- Sujet : [Ruby on Rails] Les modules, un bon moyen de factoriser son code (/showthread.php?tid=4315) Pages :
1
2
|
[Ruby on Rails] Les modules, un bon moyen de factoriser son code - Sephi-Chan - 30-08-2009 Bonsoir, Je profite d'être dessus pour vous présenter un excellente fonctionnalité offerte par Ruby (et par extension, Ruby on Rails) : les modules. Je marque ce sujet avec [Ruby on Rails] car mon article utilise ça appliqué à une application Rails, mais c'est bien une fonctionnalité native de Ruby. Les modules sont des conteneurs qui peuvent inclure des classes et des méthodes. On ne peut pas les instancier mais on peut les inclure dans une classe : elle acquiert alors les méthodes définies dans le module. Je vais vous présenter un exemple d'utilisation d'un module pour factoriser le code et ainsi suivre le principe DRY (Don't Repeat Yourself). Dans l'application, il existe des modèles pour les annonces (Announce) et les ateliers (Workgroup). Ces ressources peuvent toutes les deux être publiées : elles ont un état de brouillon (indiqué par la colonne is_draft, qui contient 1 si la ressource est un brouillon, 0 si elle est publiée) et une date de publication (si elles sont publiées). On va donc définir un module qui contient tout le nécessaire pour que la ressource soit publiable.
La méthode de classe included (en fait, included est une méthode de la classe Module) permet d'appliquer des modification à la classe (et pas seulement à l'instance) qui inclut le module. En l'occurrence, on définit des named scope. Les named scope (portées nommées) permettent à Active Record de lancer des requêtes comme : Announce.published.all pour récupérer toutes les annonces publiées. Ainsi, quand un utilisateur lambda cherche à atteindre une annonce (à l'URL http://application.com/announce/1-une-annonce-de-fou), le contrôleur lance la requête : Announce.published.find(params[:id]). On est ainsi sûr que l'utilisateur ne peut pas accéder à une ressource non publiée. Ensuite, on personnalise l'accesseur qui permet d'affecter une valeur à l'attribut is_draft de notre ressource. L'accesseur affecte — en plus de son rôle normal — une date de publication égale à l'instant présent quand on publie la ressource. Cette date de publication est effacée (et donc NULL en base de données) si on (re)met la ressource à l'état de brouillon. Notez l'utilisation de write_attribute(:is_draft, true) pour que la méthode ne s'appelle pas elle-même indéfiniment quand on fait @announce.is_draft = true. Enfin, on définit une méthode is_published? qui retourne true si la ressource est publiée et false sinon. Voilà donc pour les comportements générique de notre module. Plus qu'à définir nos modèles et inclure notre module Publishable dedans. J'épure volontairement les classes des règles de validations, etc. afin de rester assez clair.
Comme vous pouvez le voir, l'inclusion du module est toute bête ! Voyons le contrôleur de l'une de nos ressources pour comprendre les intérêts de la chose : on utilise de manière transparente les méthodes save et update_attributes puisqu'elles feront appel à notre accesseur is_draft= !
La vue d'édition (dans la partie administration) :
Et une vue d'affichage (la vue partielle pour une annonce) :
Voilà, j'espère avoir été clair sur l'utilisation des modules. Une classe peut inclure plusieurs modules (d'ailleurs, il y aura sûrement un module Commentable). N'hésitez pas à poser vos questions si vous souhaitez en savoir plus sur un point particulier. Sephi-Chan RE: [Ruby] Les modules, un bon moyen de factoriser son code - NicoMSEvent - 31-08-2009 Ce que j'aime bien, avec tes messages, c'est que je comprends jamais directement l'intérêt ou la portée... Il me faut bien 6 mois pour m'y intéresser (et surtout pour comprendre. Je comprends vite, mais faut m'expliquer longtemps => blond inside), et 6 mois après j'arrive a la conclusion que je vais y adhérer, et que c'est la technologie du futur... :p Bon ben, rdv dans 6 mois sur ce post? ^^ (ça fait quasi 6 mois que tu as posté les premières infos sur ROR, va falloir que je m'y mette alors :p) RE: [Ruby] Les modules, un bon moyen de factoriser son code - Sephi-Chan - 31-08-2009 Tu ne saisi pas l'intérêt de ça ? Je peux comprendre, je ne crois pas qu'il existe d'équivalence en PHP (ni dans pas mal d'autre langage). Comme tu peux le voir, ça ressemble à une interface (sauf qu'on peut y implémenter du code) : quand j'inclus mon module Publishable dans un modèle, il gère la publication de manière transparente. C'est assez énorme. En entreprise, j'ai fais ça pour attacher des medias à des ressources de différente nature : en leur faisant inclure Mediable, elles géraient ça, et sans passer par l'héritage (puisqu'elles héritaient déjà d'une classe) et sans duplication de code ! Toujours pas ? Sephi-Chan RE: [Ruby] Les modules, un bon moyen de factoriser son code - pascal - 31-08-2009 ça existe dans des ORM tels que Propel en PHP, ça s'appelle les behaviors / les comportements. C'est pratique pour gérer plein de trucs répétitifs, genre : - ajouter des mots-clé à des articles, annonces, profils... - ajouter des commentaires aux mêmes - permettre de signaler / modérer n'importe quelle donnée sur un site Avec des exemples plus parlants, ça pourrait être plus explicite A+ Pascal RE: [Ruby] Les modules, un bon moyen de factoriser son code - Sephi-Chan - 31-08-2009 Ouais mais cette notion d'inclusion de module est inconnue en PHP. Vraiment pas de chance pour les développeurs PHP. Les modules servent dans le cas que j'ai indiqué, mais ça n'est qu'un de leur domaine d'utilisation, il y en a d'autres. C'est effectivement très adapté aux choses polymorphe (ici, on se fout d'avoir affaire à des modèles Announce ou Workgroup) et répétitive : un module Taggable pour ce qui peut recevoir des tags, un module Commentable pour ce qui peut être commenté, etc. Sephi-Chan RE: [Ruby] Les modules, un bon moyen de factoriser son code - Shao - 01-09-2009 Le système semble intéressant, mais il faut faire attention avec tout ce qui est générique. Justement je me posais une question : Si maintenant dans tes annonces on te demande de gérer une liste d'états de publication ( mardi cette annonce était en mode brouillon et mercredi elle ne l'était plus, puis finalement jeudi elle le redevient parce que l'annonce était finalement pas assez convaincante ), par contre on ne veut pas que ce système d'états soit disponible dans les Ateliers. Est ce qu'il faut étendre le module actuelle pour l'améliorer ? Rajouter un nouveau module qui complète celui là ? En fait je veux savoir s'il y a moyen simple de compléter les modules sans impacter les utilisateurs de ces derniers ? RE: [Ruby] Les modules, un bon moyen de factoriser son code - Ter Rowan - 02-09-2009 je me gourre peut être mais si j'étais en C++, j'appelerais ça du multi héritage (voire mono si ta classe n'a pas de classe mère) en php, est ce qu'il ne suffit pas de jouer avec un include/require pour géré la même chose ? genre : le fichier publishable : Code PHP :
et dans tes classes Code PHP :
RE: [Ruby] Les modules, un bon moyen de factoriser son code - Sephi-Chan - 02-09-2009 Un module ne surcharge donc pas les éléments qui existent déjà. Documentation Ruby de la classe Module#append_features a écrit :When this module is included in another, Ruby calls append_features in this module, passing it the receiving module in mod. Ruby’s default implementation is to add the constants, methods, and module variables of this module to mod if this module has not already been added to mod or one of its ancestors. See also Module#include. Partant de ça, tu peux donc définir des méthodes particulières dans ta classe de base puisqu'elles ne seront pas remplacées par celle du module. Ils ont pensé à tout. C'est donc assez différent de l'héritage multiple. En fait, mais ça y ressemble. Concernant l'adaptation en PHP, je ne sais pas si ça fonctionne, à voir. Sephi-Chan RE: [Ruby] Les modules, un bon moyen de factoriser son code - Ter Rowan - 02-09-2009 mmm en lisant ce que tu dis là,et après avoir découvert les méthodes php d'analyse des classes php (je trouve ca formidable, ca se trouve c'est "normal" pour vous ^^) je me dis qu'on doit être capable d'encapsuler un truc la dessus tel que décrit Pascal. c'est fou ce qu'on arrive à faire quand même comme "abstraction". Intellectuellement c'est super je trouve RE: [Ruby] Les modules, un bon moyen de factoriser son code - pascal - 02-09-2009 (02-09-2009, 02:19 PM)Ter Rowan a écrit : mmm en lisant ce que tu dis là,(...) je me dis qu'on doit être capable d'encapsuler un truc la dessus tel que décrit Pascal. On peut le faire en PHP, je confirme. A+ Pascal |