Origine de "une méthode doit renvoyer une valeur ou avoir des effets secondaires, mais pas les deux"

12

J'ai lu une fois qu'une méthode devrait avoir une valeur de retour (et être référentiellement transparente), ou avoir des effets secondaires, mais pas les deux. Je ne trouve aucune référence à cette règle, mais je souhaite en savoir plus.

Quelle est l'origine de ce conseil? De quelle personne ou communauté est-elle née?

Crédit supplémentaire: Quel est l'avantage revendiqué de suivre ces conseils?

Wayne Conrad
la source
1
@gnat Oui, il s'agit avant tout d'histoire. Je craignais que la partie crédit supplémentaire soit trop subjective pour être autonome et que l'histoire ait de meilleures chances d'échapper à la fermeture. Je vais ajouter la balise.
Wayne Conrad
certaines des réponses qui s'accumulent m'ont amené à me demander si vous posez des questions sur les prestations qui ont été réclamées par un auteur de ce conseil ou pour une liste de toutes les prestations qui peuvent être réclamées?
gnat
@gnat Je pose des questions sur les avantages revendiqués par l'auteur (encore une fois, par crainte de la fermeture), mais cela ne me dérange pas pour les raisons de l'empilement - ils répondent à la question que je voulais réellement poser. Si je supprimais «réclamé» de ma question, en faisant les réponses empilées sur le sujet, cela pousserait-il trop loin la question dans le subjectif?
Wayne Conrad
les "raisons de l'empilement" risquent de pousser la question à être jugée trop large . Si vous préférez qu'il "reste ouvert", je pense qu'il serait plus sûr de le restreindre au profit qui a été revendiqué par l'auteur
gnat
Un avantage est que si vous êtes payé en volume de code, cela produit un supplément. "doSomething; GetResultOfSomething; HandleErrorsFromSomething;"
ღ uі

Réponses:

13

Selon Greg Young, cette idée est née de Bertrand Meyer : séparation Command-Query .

Il indique que chaque méthode doit être soit une commande qui exécute une action, soit une requête qui renvoie des données à l'appelant, mais pas les deux. En d'autres termes, Poser une question ne devrait pas changer la réponse . 1 Plus formellement, les méthodes ne devraient renvoyer une valeur que si elles sont référentiellement transparentes et ne présentent donc aucun effet secondaire.

1: Eiffel: un langage pour le génie logiciel slide 43-48

Dans la conception pilotée par domaine, cela est similaire à la séparation / séparation de commande-requête-lecture (CQRS), comme l'a nommé Greg Young.

Greg Young a repris l'idée de CQS de Bertrand pour nommer CQRS comme mentionné par Martin Fowler dans cet article du CQRS

Avantages

  • La partie en lecture (requête) peut être mise à l'échelle / modifiée différemment de la partie en écriture (commande). Séparer les deux empêcherait l'un ou l'autre de se gêner lorsque l'optimisation / les performances sont essentielles.

Lisez l' article du lien Martin Fowler pour en savoir plus.

tunmise fasipe
la source
1
Naturellement, dans de nombreuses situations, générer un résultat utile et faire des modifications en même temps n'est pas plus cher que de faire le plus difficile des deux séparément.
Deduplicator
1
@Deduplicator Un exemple de cliché étant InterlockedCompareExchange?
ღ uі
1
Cependant, ce conseil ne s'applique évidemment pas lorsque le retour contient des informations sur ce qui a été fait dans la commande - une méthode pour supprimer des lignes d'un ensemble de données peut à peu près changer l'état de l'ensemble de données, en supprimant les lignes indiquées selon un critère donné, et puis retourner le nombre de lignes supprimées ou même une liste avec lesdites lignes.
T. Sar
4

Je ne sais pas d'où cela vient, mais c'est un bon conseil et assez simple à comprendre.

Tout programme sainement conçu sera divisé en différentes parties, combinées et composées de différentes manières. Plus il est difficile de raisonner sur ce que fait une partie en particulier, plus il sera difficile de s'assurer que votre programme réagira de manière prévisible.

Isoler les parties qui produisent des effets secondaires facilite le raisonnement, le test et le débogage du reste. La réduction du nombre d'effets secondaires dans chaque partie qui génère un effet secondaire rendra cette partie plus facile à utiliser de la même manière.

Si vous le décomposez encore plus, une valeur de retour est un effet. Les effets secondaires sont un effet. Une fonction ne devrait produire qu'un seul effet (si possible), car plus un nombre d'entrées et d'effets est important, plus il est difficile de raisonner sur ce qu'elle fait réellement.

Morgen
la source
cela n'essaie même pas de répondre à la question posée, voir Comment répondre
gnat
@gnat Ma question se composait de deux parties: la question principale ("qui") et le crédit supplémentaire ("pourquoi). Cela ne concerne-t-il pas la partie crédit supplémentaire?
Wayne Conrad
d'après ma lecture (" avantage revendiqué "), pourquoi une partie devrait être proposée par l'auteur de la citation. La question ne semble pas demander une liste de tous les avantages possibles
gnat
2
@gnat J'ai compris la question comme une tentative de comprendre ce conseil, à la fois la raison derrière cela et le contexte dans lequel il a été donné. Je ne pense pas qu'il était inapproprié de ne traiter qu'une partie de la question.
Morgen
1

Crédit supplémentaire: Quel est l' avantage initialement revendiqué de suivre ces conseils?

L'un des avantages de la séparation de la valeur de retour des effets secondaires est qu'elle élimine un problème potentiel qui peut être causé par une évaluation de court-circuit .

bool FooWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

bool BarWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

void BadShortCircuitEvaluation()
{
    // the programmer's intent is to have side effects of both functions
    if (FooWithSideEffect() && BarWithSideEffect() ) {
        // do something
    }

    // in case FooWithSideEffect() returns true, 
    // then BarWithSideEffect() is not called at all
    // because of short-circuit evaluation
}
Nick Alexeev
la source
est-ce un avantage revendiqué par l' auteur du conseil ?
gnat
@gnat J'ai mélangé historique et pratique, je le crains.
Nick Alexeev
1
le commentaire et le code ne correspondent pas, BarWithSideEffects n'est pas appelé si FooWithSideEffects renvoie false
jk.