190 votes

Le chaînage de méthode - pourquoi est-il une bonne pratique, ou pas?

Le chaînage de méthode est la pratique de méthodes de l'objet de retour de l'objet lui-même dans l'ordre pour que le résultat soit appelé pour une autre méthode. Comme ceci:

participant.addSchedule(events[1]).addSchedule(events[2]).setStatus('attending').save()

Cela semble être considéré comme une bonne pratique, car il produit un code lisible, ou une "interface fluide". Cependant, pour moi, il semble plutôt de casser l'objet appelant la notation implicite par l'orientation de l'objet lui-même - que le code résultant ne représente pas l'exécution des actions à la suite d'une précédente méthode, qui est la façon dont le code orienté objet est généralement s'attendre à ce travail:

participant.getSchedule('monday').saveTo('monnday.file')

Cette différence parvient à créer deux significations différentes pour la dot notation de "l'appel de l'objet": Dans le contexte de l'enchaînement, l'exemple ci-dessus serait de lire que l'enregistrement du participant de l'objet, même si l'exemple est en fait destiné à enregistrer la planification de l'objet reçu par getSchedule.

Je comprends que la différence ici est de savoir si la méthode appelée devrait revenir à quelque chose ou pas (auquel cas, il serait de retour l'objet appelé lui-même pour chaînage). Mais ces deux cas ne se distinguent pas de la notation elle-même, seulement à partir de la sémantique de la méthode appelée. Lorsque la méthode de chaînage n'est pas utilisé, je peux toujours savoir qu'un appel de méthode fonctionne sur quelque chose en rapport avec le résultat de l'appel précédent - avec chaînage de cette hypothèse, les pauses, et je sémantiquement processus de l'ensemble de la chaîne de comprendre ce que l'objet même d'être appelé vraiment. Par exemple:

participant.attend(event).setNotifications('silent').getSocialStream('twitter').postStatus('Joining '+event.name).follow(event.getSocialId('twitter'))

Il y a les deux derniers appels de méthode reportez-vous à la suite de getSocialStream, tandis que ceux d'avant reportez-vous au participant. Peut-être que c'est une mauvaise pratique de l'écriture de chaînes où les changements de contexte (est-il?), mais même alors, vous aurez à vérifier constamment si point-chaînes semblables sont en fait rester dans le même contexte, ou ne fonctionnent que sur le résultat.

Pour moi, il semble que, bien que la méthode de chaînage superficiellement n'produire un code lisible, la surcharge de la signification de la dot notation seuls les résultats dans une plus grande confusion. Comme je ne me considère pas comme un expert en programmation, je suppose que la faute est la mienne. Donc: Ce qui me manque? Dois-je comprendre la méthode de chaînage quelque chose de mauvais? Y at-il des cas où la méthode de chaînage est particulièrement bonne, ou quelques-uns où il est particulièrement mauvais?

Note: je comprends que cette question pourrait être lu comme l'expression d'une opinion masqué sous la forme d'une question. Il, cependant, n'est - sincèrement, je veux comprendre pourquoi le chaînage est considéré comme une bonne pratique, et où dois-je aller de mal en pensant qu'il rompt le inhérents orientée objet de la notation.

96voto

Vilx- Points 37939

Je suis d'accord que c'est subjectif. Pour la plupart j'ai éviter le chaînage de méthode, mais récemment, j'ai aussi trouvé un cas où c'était juste la bonne chose - j'ai eu une méthode qui a accepté quelque chose comme 10 paramètres, et la plus nécessaire, mais la plupart du temps vous n'aviez qu'à préciser un peu. Avec les remplacements cela est devenu très lourd, très rapide. Au lieu de cela, j'ai opté pour le chaînage de l'approche:

MyObject.Start()
    .SpecifySomeParameter(asdasd)
    .SpecifySomeOtherParameter(asdasd)
    .Execute();

C'est quelque chose comme un modèle de fabrique. Le chaînage de méthode d'approche est facultatif, mais il a fait écrire du code plus facile (surtout avec l'IntelliSense). Vous l'esprit que ce est un cas isolé, bien que, et n'est pas une pratique générale dans mon code.

Le point est dans 99% des cas, vous pouvez probablement faire aussi bien ou même mieux sans chaînage de méthode. Mais il y a le 1% dans le cas où c'est la meilleure approche.

96voto

RAY Points 1622

Juste mes 2 cents;

Le chaînage de méthode rend le débogage délicate: - Vous ne pouvez pas placer le point d'arrêt dans un concise point de sorte que vous pouvez mettre en pause le programme exactement où vous le souhaitez - Si l'une de ces méthodes déclenche une exception, et vous obtenez un numéro de ligne, vous n'avez aucune idée de la méthode de la "chaîne" à l'origine du problème.

Je pense que c'est généralement une bonne pratique de toujours écrire très court et concis lignes. Chaque ligne doit simplement faire un appel de méthode. Préférez plus de lignes pour les lignes les plus longues.

51voto

bmoeskau Points 13136

Personnellement, je préfère le chaînage des méthodes qui agissent uniquement sur l'objet d'origine, par exemple la création de multiples propriétés, ou en appelant à l'utilité des méthodes de type.

foo.setHeight(100).setWidth(50).setColor('#ffffff');
foo.moveTo(100,100).highlight();

Je ne l'utilise pas lorsque l'une ou plusieurs des enchaînés méthodes de retour d'autre objet que de foo dans mon exemple. Alors que du point de vue syntaxique, vous pouvez la chaîne de rien, tant que vous utilisez la bonne API pour l'objet dans la chaîne, changer les objets à mon humble avis rend les choses moins lisible et peut être très déroutant si l'Api pour les différents objets ont des similitudes. Si vous faites un peu de vraiment commun de l'appel de méthode à la fin (toString(), print(), peu importe) quel objet allez-vous obtenir? Quelqu'un hasard de la lecture du code peut ne pas attraper qu'il serait un certain implicitement objet retourné dans la chaîne plutôt que celui d'origine.

Le chaînage de différents objets peuvent également aboutir à des null erreurs. Dans mes exemples, en supposant que foo est valide, tous les appels de méthode sont "sûrs" (par exemple, valable pour les foo). Dans votre exemple:

participant.getSchedule('monday').saveTo('monnday.file')

...il n'y a pas de garantie (en dehors de développeur en regardant le code) qui getSchedule sera effectivement de retour valide, non-nulle de l'annexe de l'objet. Aussi, le débogage de ce type de code est souvent beaucoup plus difficile depuis de nombreuses IDEs n'évaluera pas l'appel de méthode à déboguer le temps comme un objet que vous pouvez inspecter. De l'OMI, à tout moment vous pourriez avoir besoin d'un objet à inspecter pour des fins de débogage, je préfère l'avoir dans une variable explicite.

29voto

0xA3 Points 73439

Martin Fowler est un bon sujet de discussion ici:

Le Chaînage De Méthode

Quand l'utiliser

Le Chaînage de méthode peuvent ajouter beaucoup à la lisibilité d'un DSL interne et comme un résultat est presque devenu un synonum interne DSLs dans certains esprits. Le Chaînage de méthode est la meilleure, toutefois, lorsqu'il est utilisé en conjonction avec d'autres associations de fonctions.

Le Chaînage de méthode est particulièrement efficace avec des grammaires comme parent::= (un | une)*. L'utilisation de différents méthodes fournit lisible de voir quel argument est a venir. De même, les arguments optionnels peuvent être facilement ignorés par la Méthode Le chaînage. Une liste de clauses obligatoires, comme parent::= première seconde n'est pas travail si bien avec la forme de base, bien qu'il puisse être pris en charge par utilisation progressive des interfaces. La plupart des le temps que je préfère Fonction Imbriquée pour ce cas.

Le plus gros problème pour la Méthode Le chaînage est la finition problème. Bien qu'il existe des solutions de contournement, généralement si vous avez ce qui vous convient le mieux en utilisant une Fonction Imbriquée. Imbriquée La fonction est également un meilleur choix si vous avez trouvé dans un bazar avec Les Variables De Contexte.

27voto

Tom Dalling Points 10656

À mon avis, la méthode de chaînage est un peu une nouveauté. Bien sûr, il a l'air cool mais je ne vois pas de réels avantages.

Comment est:

someList.addObject("str1").addObject("str2").addObject("str3")

mieux que:

someList.addObject("str1")
someList.addObject("str2")
someList.addObject("str3")

L'exception pourrait être quand addObject() renvoie un nouvel objet, auquel cas le unchained code peut être un peu plus lourd comme:

someList = someList.addObject("str1")
someList = someList.addObject("str2")
someList = someList.addObject("str3")

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