Existe-t-il des inconvénients réels au chaînage de méthodes autoréférentielles?

14

J'ai récemment suggéré qu'une méthode de chaînage soit implémentée pour une certaine classe dans un certain projet afin que la lisibilité du code puisse être améliorée. J'ai obtenu une réponse «les interfaces fluides ne devraient pas être implémentées uniquement pour des raisons de commodité, mais pour la sémantique» et ma proposition a été rejetée. J'ai répondu que je ne proposais pas une interface fluide mais une méthode de chaînage (les deux peuvent être confondues , lues en bas) pour améliorer la lisibilité et le confort de codage, la suggestion a été rejetée à nouveau.

Quoi qu'il en soit, cela m'a fait penser que je pourrais peut-être encourir une mauvaise pratique en renvoyant toujours "ceci" dans des méthodes qui ne sont censées rien renvoyer (par exemple, les setters).

Ma question est la suivante: l'application de la convention précédente peut-elle être considérée comme une mauvaise pratique ou un abus?, Pourquoi?. Je ne pense pas qu'il y ait des inconvénients de performances, ou y en a-t-il?.

dukeofgaming
la source
2
Regardez cette question pour une belle discussion programmers.stackexchange.com/questions/48419/…
KeesDijk
@KeesDijk Merci, j'ai édité un peu ma question afin qu'elle ne soit pas similaire à celle-ci, car je suis plus intéressé par le cas des méthodes de chaînage de la même classe
dukeofgaming
1
chez SO, ils m'ont dit que le chaînage n'est pas pour C ++ - stackoverflow.com/questions/5760551/… - qu'en pensez-vous?
kagali-san
1
@mhambra Il semble que vous ne deviez être prudent que lors de l'implémentation du chaînage de méthodes et définir des normes claires pour cela.
dukeofgaming

Réponses:

10

Non

Comme le souligne Kent Beck , le code est lu beaucoup plus souvent qu'il n'est écrit.

Si le chaînage de méthodes rend votre code plus lisible, utilisez le chaînage de méthodes.

Steven A. Lowe
la source
1
Great book .. +1
Rein Henrichs
5
MAIS , que se passe-t-il si vous êtes la seule méthode de recherche d'enchaînement plus lisible? S'il s'agit d'une question sytiliste, vous devrez vous en tenir à un ensemble de conventions de codage: cela signifie, écrire de la même manière que le code existant, pour plus de cohérence.
coredump
@coredump On dirait que l'OP a déjà été dit de le faire, mais je pense que Steven disait juste cela si le chaînage de la méthode le rend plus lisible.
Panzercrisis
1
@Panzercrisis OP a été invité à s'abstenir d'utiliser le chaînage de méthodes en raison de la commodité par rapport à la sémantique. La réponse de Steven dit essentiellement "faites-le quand même" et ne considérez que la lisibilité du code OP seul, sans prendre en compte l'opinion ou la cohérence de l'équipe. Que se passe-t-il si OP veut réécrire chaque classe existante dans le projet afin qu'elle corresponde à son goût en matière de lisibilité du code? C'est ainsi que je comprends l'argument commodité / sémantique: il devrait y avoir une raison "technique" d'avoir un chaînage de méthode (en fait, cet argument sonne également comme si l'autre personne
invente
9

Oui, il y a des inconvénients

Un code facile à lire est bon, mais méfiez-vous également de ce qu'il communique . Lorsque les méthodes d'un objet retournent toujours l'objet, il communique deux ou trois choses:

  1. J'ai besoin d'une configuration avancée qui n'est pas nécessairement évidente dans quel ordre les choses doivent être définies ou configurées
  2. Chaque appel de méthode suivant s'appuie sur le dernier

Cas d'utilisation valide: requêtes de base de données ad hoc

Les bibliothèques de classes existent dans la plupart des langages qui vous permettent d'interroger une base de données sans recourir à du code SQL codé en dur. Prenez l'exemple d'Entity Framework pour .NET:

DBContext db = new DBContext();
List<Post> posts = db.Posts
    .Where(post => post.Title.Contains("Test"))
    .OrderBy(post => post.DateCreated)
    .ToList();

Il s'agit d'une interface fluide où chaque appel de méthode suivant s'appuie sur le précédent. La lecture de ces appels est logique dans le contexte de l'interrogation d'une base de données.

Cas d'utilisation non valide: sucre syntaxique pour la définition des propriétés

Maintenant, utilisons le même modèle avec la Postclasse:

public class Post
{
    public string Title { get; set; }
    public DateTime DateCreated { get; set; }
    public string Body { get; set; }

    public Post SetTitle(string title)
    {
        Title = title;

        return this;
    }

    public Post SetDateCreated(DateTime created)
    {
        DateCreated = created;

        return this;
    }

    public Post SetBody(string body)
    {
        Body = body;

        return this;
    }
}

Voyons maintenant comment vous utiliseriez cette classe:

Post post = new Post()
    .SetTitle("Test")
    .SetDateCreated(DateTime.Now)
    .SetBody("Just a test");

Lorsque je vois ce code, je pose immédiatement cette question: "Après avoir appelé SetBody, interroge-t-il la base de données? Dois-je appeler une autre méthode pour dire" J'ai terminé? ""

Que communiquent les appels de méthode chaînés au code à l'aide de la Postclasse?

  1. J'ai une configuration compliquée
  2. Chaque appel de méthode s'appuie sur le précédent

Est-ce vraiment vrai? Non. La Postclasse n'a pas de configuration compliquée. La définition du titre, de la date de création et du corps ne s'appuie pas l'un sur l'autre vers un objectif final plus compliqué. Vous avez écrasé une cheville carrée dans un trou rond.

L'inconvénient du chaînage de méthode auto-référentiel est que vous communiquez que plusieurs appels de méthode sont nécessaires pour faire quelque chose, et que chaque appel s'appuie sur le dernier. Si ce n'est pas le cas, le chaînage de méthode peut être communiquer la mauvaise chose à d'autres programmeurs.

Lorsque vos collègues ont dit:

Les interfaces fluides ne doivent pas être implémentées uniquement pour des raisons de commodité, mais pour la sémantique

Ils étaient absolument corrects. Une interface fluide, ou un chaînage de méthodes, communique quelque chose en soi qui pourrait ne pas être vrai.

Greg Burghardt
la source
Cela suppose que le chaînage des méthodes et la configuration complexe vont toujours de pair. Ce sont des entités distinctes et la présence de l'une ne doit pas vous faire assumer l'autre.
Jack
Ce n'est pas seulement une «configuration complexe», c'est aussi «des appels de méthode ultérieurs à partir de la précédente». Le chaînage de méthode a une méta-communication à ce sujet qui n'est pas toujours fidèle à l'objectif d'une classe.
Greg Burghardt
1
Les appels de méthode suivants s'appuyant sur les précédents sont également distincts du chaînage de méthode, et je ne pense pas que le fait de traiter la syntaxe du chaînage de méthode comme une communication forte pour la sémantique des séries d'opérations d'effet secondaire dépendant de l'ordre soit fiable ou utile. C'est un raccourci syntaxique, rien de plus. Utilisez-le là où il rend les choses plus courtes et plus lisibles.
Jack
1
Je comprends que vous pensez de méthodes enchaînées est séparée, mais je dis que d' autres programmeurs qui ne sont pas dans votre tête et utiliser d' autres bibliothèques de classes qui ne mettent en œuvre de méthodes enchaînées pour ces raisons pourrait finir par faire des suppositions au sujet de votre code qui sont faux. N'oubliez pas que le chaînage de méthode peut impliquer quelque chose que vous, l'auteur du code, n'aviez pas l'intention. Un code qui communique clairement est tout aussi important qu'un code facile à lire. Ne sacrifiez pas l'un pour l'autre.
Greg Burghardt
1
When an object's methods always return the object, it communicates a couple of things- Je pense que c'est une opinion personnelle; il est difficile de prétendre que tous ceux qui étudient les méthodes chaînées supposeront les mêmes choses.
Sam Dufel
1

Le principal inconvénient est une perte de clarté. Par exemple:

x.foo();
x.bar();
x.baz();

Puisqu'aucune de ces instructions ne retourne une valeur (ou si elles le font, elle a été ignorée), elles ne peuvent être utiles que si elles produisent des effets secondaires. Comparez cela à:

x.foo()
 .bar()
 .baz();

Tout d' abord, on ne sait pas que baret bazfonctionnent sur des objets du même type que x, à moins que vous savez pertinemment que xla classe « est la seule classe avec ces méthodes. Même si c'est le cas, il n'est pas clair que les méthodes fonctionnent xou les nouveaux objets.

La mise en évidence des parties du code qui ont des effets secondaires est utile, car vous devez suivre ces effets secondaires pour raisonner sur le programme. Vous devez peser la perte potentielle de clarté par rapport au gain potentiel de facilité d'écriture de code, mais considérez également que le code est lu plus qu'il n'est écrit.

Doval
la source
0

Tenez compte de tous les éléments stylistiques des langages de programmation (par opposition au langage machine à codage manuel), et cela affaiblit l'argument «sémantique et non commodité».

Une grande partie de ce que nous faisons en tant qu'ingénieurs fournit la commodité autour de la sémantique.

Rob
la source