234 votes

Quel est le meilleur nom pour une méthode "add" non mutable sur une collection immuable ?

Désolé pour ce titre vague - si je pouvais trouver un titre concis, je n'aurais pas à poser la question.

Supposons que j'ai un type de liste immuable. Il possède une opération Foo(x) qui renvoie une nouvelle liste immuable avec l'argument spécifié comme élément supplémentaire à la fin. Ainsi, pour construire une liste de chaînes de caractères avec les valeurs "Hello", "immutable", "world", vous pourriez écrire :

var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");

(Il s'agit de code C#, et je suis plus intéressé par une suggestion en C# si vous pensez que le langage est important. Ce n'est pas fondamentalement une question de langage, mais les idiomes du langage peuvent être importants).

L'important est que les listes existantes soient pas modifié par Foo - donc empty.Count retournerait toujours 0.

Une autre façon (plus idiomatique) d'arriver au résultat final serait :

var list = new ImmutableList<string>().Foo("Hello")
                                      .Foo("immutable")
                                      .Foo("word");

Ma question est la suivante : Quel est le meilleur nom pour Foo ?

EDIT 3 : Comme je le révèle plus tard, le nom du type pourrait ne pas être en réalité. ImmutableList<T> ce qui rend la position claire. Imaginez plutôt que c'est TestSuite et qu'il est immuable parce que l'ensemble du cadre dont il fait partie est immuable...

(Fin de l'édition 3)

Les options que j'ai trouvées jusqu'à présent :

  • Add : commun en .NET, mais implique une mutation de la liste originale.
  • Cons : Je crois que c'est le nom normal dans les langages fonctionnels, mais sans signification pour ceux qui n'ont pas d'expérience dans ces langages.
  • Plus : mon préféré jusqu'à présent, il n'implique pas de mutation. pour moi . Apparemment, c'est aussi utilisé en Haskell mais avec des attentes légèrement différentes (un programmeur Haskell pourrait s'attendre à ce qu'il ajoute deux listes ensemble plutôt que d'ajouter une seule valeur à l'autre liste).
  • With Il est cohérent avec d'autres conventions immuables, mais n'a pas tout à fait la même "additionnalité", selon moi.
  • And : pas très descriptif.
  • Surcharge de l'opérateur + : je n'aime pas vraiment cela ; je pense généralement que les opérateurs ne devraient être appliqués qu'aux types de niveau inférieur. Mais je suis prêt à me laisser convaincre !

Les critères que j'utilise pour choisir sont les suivants :

  • Donne l'impression correcte du résultat de l'appel de la méthode (c'est-à-dire qu'il s'agit de la liste originale avec un élément supplémentaire).
  • Indique aussi clairement que possible qu'il ne modifie pas la liste existante.
  • Cela semble raisonnable quand on les enchaîne comme dans le deuxième exemple ci-dessus.

Veuillez demander plus de détails si je ne suis pas assez clair...

EDIT 1 : Voici mon raisonnement pour préférer Plus à Add . Considérons ces deux lignes de code :

list.Add(foo);
list.Plus(foo);

A mon avis (et ceci est c'est une question personnelle), la seconde est clairement boguée - c'est comme si on écrivait "x + 5 ;" comme une déclaration à part entière. La première ligne semble correcte, jusqu'à ce que l'on se rappelle qu'elle est immuable. En fait, la manière dont l'opérateur plus ne modifie pas ses opérandes est une autre raison pour laquelle Plus est mon préféré. Sans les inconvénients de la surcharge des opérateurs, il donne toujours les mêmes connotations, qui incluent (pour moi) la non-mutation des opérandes (ou de la cible de la méthode dans ce cas).

EDIT 2 : Raisons pour lesquelles je n'aime pas Add.

Diverses réponses sont effectivement données : "Allez-y avec Add. C'est ce que DateTime fait, et String a Replace méthodes etc. qui ne rendent pas l'immuabilité évidente". Je suis d'accord - il y a un précédent ici. Cependant, j'ai vu beaucoup de personnes appeler DateTime.Add o String.Replace y s'attendre à une mutation . Il y a des tas de questions de newsgroups (et probablement des questions de SO si je creuse un peu) dont la réponse est "Vous ignorez la valeur de retour de String.Replace ; les chaînes sont immuables, une nouvelle chaîne est renvoyée."

Maintenant, je dois révéler une subtilité à la question - le type pourrait pas est en fait une liste immuable, mais un type immuable différent. En particulier, je travaille sur un cadre d'évaluation comparative où vous ajoutez des tests à une suite, et cela crée une nouvelle suite. Cela peut sembler évident :

var list = new ImmutableList<string>();
list.Add("foo");

ne va pas accomplir quoi que ce soit, mais cela devient une lot plus sombre lorsque vous le changez en :

var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);

On dirait que ça devrait aller. Alors que ceci, pour moi, rend l'erreur plus claire :

var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);

Ça ne demande qu'à l'être :

var suite = new TestSuite<string, int>().Plus(x => x.Length);

Idéalement, j'aimerais que mes utilisateurs n'aient pas à être informés que la suite de tests est immuable. Je veux qu'ils tombent dans la fosse du succès. Ce mai ne soit pas possible, mais j'aimerais essayer.

Je m'excuse d'avoir trop simplifié la question initiale en ne parlant que d'un type de liste immuable. Toutes les collections ne sont pas aussi autodescriptives que le type ImmutableList<T> :)

0 votes

Je pense qu'il n'y aurait aucune ambiguïté à "Ajouter" en supposant que la classe ne supporte pas à la fois les opérations mutantes et non-mutantes. Si c'était le cas, je pourrais comprendre qu'il faille être plus spécifique.

0 votes

Le problème n'est pas le nom, c'est que C# ignore automatiquement la valeur de retour. Ainsi, trouver des noms créatifs ne résoudra pas le problème sous-jacent, à savoir que la plupart des types en C# sont mutables. Sans parler de l'obtention de bons noms comme Plus pour d'autres cas (Insert, Remove, Push, Pop, etc.).

0 votes

Aussi, vous n'abusez pas assez de l'inférence de type. De BclExtras. var list = ImmutableList.CreateFromArguments("foo") ;

132voto

MojoFilter Points 3730

Dans ce genre de situation, j'opte généralement pour Concat . Pour moi, cela signifie généralement qu'un nouvel objet est créé.

var p = listA.Concat(listB);
var k = listA.Concat(item);

3 votes

C'est ce que j'utilise, car c'est ce que System.Linq.Enumerable utilise - la décision est déjà prise :) Je ne peux pas être la seule personne à avoir défini sa propre surcharge de l'extension Concat sur IEnumerable pour accepter une seule valeur à ajouter.

9 votes

+1 C'est le site réponse correcte pour maintenir la cohérence du nommage dans le cadre.

0 votes

Sauf erreur de ma part, System.Linq.Enumerable (et Linq en général) utilise Concat() uniquement pour "séquence + séquence", jamais pour "élément + séquence". Le problème que quelqu'un "pourrait s'attendre à ce qu'il ajoute deux listes ensemble plutôt que d'ajouter une seule valeur à l'autre liste" a été explicitement donné comme une raison de ne pas utiliser une des autres options originales.

119voto

Ken Points 1877

Je choisirais Cons, pour une raison simple : il signifie exactement ce que vous voulez.

  1. Je suis un grand fan de dire exactement ce que je veux dire, surtout dans le code source. Un débutant n'aura à chercher la définition de Cons qu'une seule fois, mais il la lira et l'utilisera des milliers de fois. Je trouve qu'à long terme, il est plus agréable de travailler avec des systèmes qui facilitent les cas courants, même si le coût initial est un peu plus élevé.

  2. Le fait que cela n'ait aucun sens pour les personnes n'ayant aucune expérience de la PF est en fait un gros avantage. Comme vous l'avez souligné, tous les autres mots que vous avez trouvés ont déjà une certaine signification, et cette signification est soit légèrement différente, soit ambiguë. Un nouveau concept debe avoir un nouveau mot (ou dans ce cas, un ancien). Je préfère que quelqu'un ait à chercher la définition de Cons, plutôt que de supposer à tort qu'il sait ce que fait Add.

  3. D'autres opérations empruntées aux langages fonctionnels conservent souvent leur nom d'origine, sans catastrophe apparente. Je n'ai pas vu d'effort pour trouver des synonymes de "map" et "reduce" qui soient plus familiers aux non-FPers, et je ne vois pas non plus d'avantage à le faire.

(Divulgation complète : je suis un programmeur Lisp, donc je sais déjà ce que signifie Cons).

16 votes

N'oubliez pas que la facilité de découverte est importante - si je tape "testSuite." et que je regarde la liste des méthodes, j'aimerais voir une méthode qui suggère la bonne chose. Je ne chercherai probablement pas un nom absurde (pour moi) en espérant que c'est ce que je veux.

33 votes

Si je me sentais d'humeur sarcastique, je créerais une méthode Add qui lèverait simplement une exception avec le message "Use Cons to prepend to an ImmutableList" :-)

2 votes

Cela ne tuera personne de lire quelques lignes de commentaires expliquant pourquoi le nom est ce qu'il est, et les renvoyant à, disons, "Structure and Interpretation of Computer Programs" de Abelson & Sussman.

59voto

tvanfosson Points 268301

En fait, j'aime bien And surtout de manière idiomatique. J'aimerais particulièrement que vous ayez une propriété statique en lecture seule pour la liste vide, et peut-être que vous rendiez le constructeur privé pour que vous deviez toujours construire à partir de la liste vide.

var list = ImmutableList<string>.Empty.And("Hello")
                                      .And("Immutable")
                                      .And("Word");

0 votes

J'aime l'idée du vide. Mais je ne suis toujours pas convaincu par And. C'est juste un peu blah.

0 votes

Cela ressemble plus à la façon dont je penserais à construire une liste de choses en langage naturel. Si vous le lisez à haute voix, il semble plus intuitif que Add ou Plus. "list" est la liste vide et "Hello" et "Immutable" et "Word". Je suis d'accord pour dire que c'est moins clair en isolation, cependant.

52voto

spoulson Points 13391

Quand j'ai un problème de nomenclature, je consulte les sites internet.

thesaurus.com retourne ceci pour "ajouter" :

Définition : jouxtent, augmentent ; font commentaire supplémentaire

Synonymes : affixe, annexer, ante, append, augmenter, boeuf up, boost, build up, charge up, continue, cue in, figure in, chair heat up, hike, hike up, hitch on, hook on, hook up with, include, jack l'inclure, l'enrichir, l'intégrer, le compléter, parabole, piggyback, brancher sur, le verser sur, répondre, courir vers le haut, dire plus loin, claquer sur, snowball, soup up, speed up, spike, step up, supplement, sweeten, ajouter, étiqueter

J'aime le son de Adjoin ou plus simplement Join . C'est ce que vous êtes en train de faire, non ? La méthode pourrait aussi s'appliquer pour rejoindre d'autres ImmutableList<> 's.

1 votes

J'aime bien "Join" aussi, mais dans la plupart des cas, lorsque vous joignez deux objets, vous obtenez un seul. Dans ce cas, si vous joignez deux objets, vous créez en fait un nouvel objet.

1 votes

Je ne connais pas de cas dans .NET, Perl, PHP ou même VBScript où Join implique une mutation. La conception est telle que A et B se rejoignent pour former C, où C est toujours une nouvelle entité.

0 votes

J'aime bien Join, et je suis totalement d'accord avec thesaurus.com :) Je l'utilise tout le temps quand j'ai un doute sur un nom.

48voto

LarryF Points 2761

Personnellement, j'aime bien .With(). Si j'utilisais l'objet, après avoir lu la documentation ou les commentaires du code, je saurais clairement ce qu'il fait, et il se lit bien dans le code source.

object.With("My new item as well");

Ou, vous ajoutez "Along" avec elle.. :)

object.AlongWith("this new item");

0 votes

+1. "WITH" est un opérateur infixe dans SETL qui fait la même chose. Si SETL l'utilise, c'est qu'il doit être correct :-)

1 votes

Bah... Qui utilise encore VB ? :) Uh... Opps... C'était à voix haute ? heh.. Mais non, plus sérieusement, c'est pour cela que j'ai envisagé le "AlongWith", qui supprimerait le problème de VB. Il n'y a qu'un million de façons différentes dont il pourrait s'y prendre... Je veux dire, même des folles comme : object.Plus(), ou Object.ExistingPlus()... etc... C'est une sacrée bonne question qu'il a postée, cependant... heh...

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