Les slides de ma présentation à Paris.rb le 7 janvier 2013 sur le problème de l'implémentation de DCI en Ruby.

Commentaires

Merci pour cette présentation, Simon, on y réfléchira à deux fois avant de faire du DCI. :)

Comme je te l'avais dit lors des questions, ce qui me surprend est cette volonté, dans l'implémentation du DCI, de séparer effectivement les méthodes dans la mémoire en utilisant obj#extend plutôt que de simplement les séparer dans la structure des fichiers, par exemple en utilisant un dossier app/contexts/, et d'include ces contextes dans les models.

J'imagine que je n'ai pas réalisé que l'usage mémoire est soudainement devenu une problématique de premier ordre dans le monde de rails.

Il y a presque 12 ans

C'est n'est pas qu'une question de mémoire en fait. Le but est aussi de réduire le risque de collisions entre les noms de méthodes de chaque module. Comme le disait Ori c'est un peu le sujet des Refinements aussi.

Normalement tu as la maitrise de ton code et les collisions ne sont pas censées arriver mais dés que l'équipe grossit un peu ou qu'on intervient sur un projet externe ça peut vite déraper. Séparer les "rôles" peut éviter ça.

En tout honnêteté, j'utilise des Concerns et je me prends pas la tête parce que je suis flemmard mais sur le principe ça peut être une bonne chose de passer par la division des responsabilités.

Au passage, une lecture intéressante est l'article de Ryan Bates, My issues with Modules https://gist.github.com/4172391

Il y a presque 12 ans

Article intéressant, merci, je ne l'avais pas vu passer.

Personnellement, j'ai pris l'habitude de ne pas mettre plus d'une ou deux méthodes dans mes modules (il n'y en a qu'une seule, la grande majorité du temps), et cette méthode instancie une classe contenue dans le module, qui dispose de toutes les méthodes nécessaires.

Ça permet largement d'éviter ces problèmes de collision, même quand les models approchent la limite du trop complexe (et je me suis rendu compte que dans toutes les méthodes des modules, il n'y en avait effectivement qu'une ou deux que je comptais utiliser, les autres servant principalement à rendre le code plus lisible).

Ça a ses propres problèmes de lisibilité, cela dit, notamment parce que la classe dans le module doit pouvoir accéder aux méthodes de la classe dans laquelle le module est inclu, ce qui veut dire implémenter un methode missing à chaque fois.

Je fais ça par facilité, mais ce design pourrait également régler le problème de dépendence soulevé par Ryan : si an lieu de passer `self` en paramètre à l'instantiation de la classe contenue dans le module et de lui déléguer les method missing, on lui passe un ensemble fixe de paramètres, on peut plus facilement découpler les attributs utilisés par la classe contenu dans le module et ceux de la classe d'origine : https://gist.github.com/4501186

Il y a presque 12 ans

De ce que tu me dis, ce que tu fais avec le method_missing pourrait être simplifié avec SimpleDelegator justement, non ? J'ai peut être mal saisi.

Après effectivement la solution de ton gist permet de découpler ce qui est attendu de ce qui est envoyé. C'est utile si c'est un module utilisé avec plusieurs modèles, sinon je mettrais purchase_attributes dans Purchasable.

Il y a presque 12 ans

> De ce que tu me dis, ce que tu fais avec le method_missing pourrait être simplifié avec SimpleDelegator justement, non ? J'ai peut être mal saisi.

Oui tout à fait, c'est juste une habitude. Mais le problème reste le même : il y a une dépendence à la classe d'origine.

> Après effectivement la solution de ton gist permet de découpler ce qui est attendu de ce qui est envoyé. C'est utile si c'est un module utilisé avec plusieurs modèles, sinon je mettrais purchase_attributes dans Purchasable.

Oui, ce besoin de déclarer une méthode me posait problème aussi, j'ai modifié le gist à peu près en même temps pour pouvoir passer ces valeurs en param :)

Note que ça résoud le point soulevé par Ryan qui était : "If we change the behavior it is very easy to call another method on Order and suddenly we've broken the other class that includes this module". Donc oui, c'est spécifique à un module destiné à plusieurs classes.

Il y a presque 12 ans

En effet, la nouvelle version du gist me parle déjà plus :)

Il y a presque 12 ans
Vous devez vous inscrire ou vous connecter pour poster un commentaire