2 votes

Meilleure pratique : Créer un module avec l'attente du type dans lequel il est inclus ?

Lors de la définition d'un module en Ruby, j'ai vu des exemples où le module s'attend à ce que la ou les classes dans lesquelles il doit être inclus doivent avoir des définitions et des fonctionnalités particulières.

Par exemple, le module pourrait appeler une méthode qui elle-même ne contient pas de en attendant que la classe dans laquelle il est inclus contient cette définition de méthode.

Pour moi, il s'agit d'un paradigme différent de celui des langages fortement typés qui n'ont pas la capacité d'inclure un ensemble arbitraire de logique (Ruby dans son ensemble est un paradigme totalement différent d'ailleurs).

Est-ce que c'est un style acceptable selon les standards ruby ou du moins vu assez souvent dans des bases de code matures pour être considéré comme "ok" ?

Je me rends compte que c'est une question quelque peu subjective, mais je cherche à savoir si c'est quelque chose qui se produit assez souvent pour que l'on soit considéré comme étant dans la "norme" si l'on construit un module de ce type.

2voto

tadman Points 70178

Étant donné que Ruby est très peu typé, et qu'il repose davantage sur la capacité à répondre aux méthodes, ce qu'on appelle les dactylographie du canard que la classe, il est difficile de prendre la responsabilité de ces choses.

Si votre module est inclus dans un contexte qui est incompatible, ce n'est pas à vous, en tant que module, de faire quoi que ce soit à ce sujet. Il n'y a aucun moyen de savoir, à l'avance, si un appel de méthode donné va réussir ou échouer parce qu'après l'inclusion de votre module, d'autres choses peuvent se produire qui rendraient prématurée une sorte de validation.

Compte tenu de ces limites, il est important d'essayer d'architecturer les choses de manière à éviter ce genre d'ambiguïté.

Prenez Énumérable à titre d'exemple. Pour qu'il fonctionne correctement lorsqu'il est inclus, un certain nombre de méthodes doivent être définies dans le contexte dans lequel il est inclus. Si celles-ci ne sont pas définies, le module ne fonctionnera pas, mais la responsabilité de cet échec n'incombe pas à Enumerable, mais au module qui l'a inclus.

En gros, avant que vous include SomeModule vous devez être certain que les dépendances, s'il y en a, pour inclure ce module sont respectées. En tant qu'incluseur, vous assumez également la responsabilité de tout conflit que cela pourrait causer.

D'autres langages ont des méthodes plus rigides pour valider l'intégrité, comme la fonction protocoles de l'Objective C ou la présence d'une classe de base en C++. Comme Ruby n'en dispose pas, des suites de tests automatisés sont utilisées pour s'assurer que tout fonctionne correctement. Vous remarquerez que la communauté Ruby est très orientée vers les tests, et ce genre d'ambiguïté est l'une des nombreuses raisons pour lesquelles il en est ainsi.

1voto

numbers1311407 Points 15653

Oui, c'est acceptable. Vous voyez ce genre de choses très souvent, même dans la bibliothèque de base, avec des modules tels que Comparable y Enumerable qui attendent toutes deux que certaines méthodes soient mises en œuvre dans la classe d'inclusion.

Ce type d'attente pourrait être comparé aux interfaces en Java, mais avec un typage canard vs structurel.

Au-delà de ces modules d'application générale, on observe souvent ce phénomène avec des classes complexes qui sont décomposées en petites préoccupations modulaires. Les modules s'attendent toujours à fonctionner dans le contexte de la classe incluse, mais le code est décomposé en morceaux, ce qui permet de garder les préoccupations enfichables et la classe incluse d'une taille plus gérable.

Ce genre de schéma :

lib/
  someclass.rb
  someclass/
    concern_a.rb
    concern_b.rb

... où concern_a y concern_b sont des modules inclus dans someclass est assez courant, et je pense qu'il est suffisamment intuitif pour que vous ne vous demandiez pas ce que les méthodes de la section concern_a font.

Bien sûr, cette flexibilité n'est pas sans prix. Dans Rails en particulier, étant donné l'abondance de méthodes définies dynamiquement (échappant aux greps), et l'autoloading magique, trouver le code que vous recherchez peut parfois être difficile, en particulier lorsqu'il s'agit d'un code hérité moins qu'excellent, par exemple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X