web-dev-qa-db-fra.com

Qu'est-ce qu'un "effet secondaire"?

Je n'ai pas clairement compris le concept d'effet secondaire.

  • Quel est l'effet secondaire dans la programmation?
  • Est-ce que cela dépend du langage de programmation?
  • Existe-t-il des effets secondaires externes et internes?

Veuillez donner un exemple de causes qui créent des effets secondaires.

101
Amir Rezaei

Un effet secondaire se réfère simplement à la modification d'une sorte d'état - par exemple:

  • Changer la valeur d'une variable;
  • Écriture de certaines données sur disque;
  • Activation ou désactivation d'un bouton dans l'interface utilisateur.

Contrairement à ce que certaines personnes semblent dire:

  • Un effet secondaire ne doit pas être caché ou inattendu (il peut l'être, mais cela n'a rien à voir avec la définition telle qu'elle s'applique à l'informatique) ;

  • Un effet secondaire n'a rien à voir avec l'idempotence. Une fonction idempotente peut avoir des effets secondaires et une fonction non idempotente peut n'avoir aucun effet secondaire (comme obtenir la date et l'heure actuelles du système).

C'est vraiment très simple. Effet secondaire = changer quelque chose quelque part.

P.S. Comme le souligne le commentateur benjol, plusieurs personnes peuvent confondre la définition d'un effet secondaire avec la définition d'un fonction pure , qui est une fonction qui est (a) idempotente et (b) n'a pas de côté- effets. L'un n'implique pas l'autre en informatique générale, mais les langages de programmation fonctionnels auront généralement tendance à imposer les deux contraintes.

114
Aaronaught

Toute opération qui modifie l'état de l'ordinateur ou qui interagit avec le monde extérieur aurait un effet secondaire. Voir Wikipedia sur effet secondaire .

Par exemple, cette fonction n'a aucun effet secondaire. Son résultat dépend uniquement de ses arguments d'entrée, et rien sur l'état du programme ou son environnement ne change quand il est appelé:

int square(int x) { return x * x; }

En revanche, appeler ces fonctions vous donnera des résultats différents selon l'ordre dans lequel vous les appelez, car elles changent quelque chose sur l'état de l'ordinateur:

int n = 0;
int next_n() { return n++; }
void set_n(int newN) { n = newN; }      

Cette fonction a pour effet secondaire d'écrire des données sur la sortie. Vous n'appelez pas la fonction parce que vous voulez sa valeur de retour; vous l'appelez parce que vous voulez l'effet qu'il a sur le "monde extérieur":

int Write(const char* s) { return printf("Output: %s\n", s); }
38
Kristopher Johnson

Je pense que les réponses existantes sont assez bonnes. Je voudrais préciser certains aspects sur lesquels l'OMI n'a pas été suffisamment soulignée.

En mathématiques, une fonction n'est qu'un mappage d'un tuple de valeurs à une valeur. Donc, étant donné une fonction f et une valeur x, f(x) sera toujours le même résultat y. Vous pouvez bien remplacer f(x) par y partout dans une expression et rien ne changera.

Ce que l'on appelle une fonction (ou procédure) dans de nombreux langages de programmation est une construction (morceau de code) qui peut être exécutée car:

  1. Il calcule une fonction au sens mathématique, c'est-à-dire des valeurs d'entrée données, il renvoie un résultat, ou
  2. Il produit un certain effet, par exemple imprime quelque chose à l'écran, modifie une valeur sur une base de données, lance des missiles, dort pendant 10 secondes, envoie un SMS.

Les effets peuvent donc être liés à l'état mais aussi à d'autres aspects comme le tir d'un missile ou la suspension de l'exécution pendant quelques secondes.

Le terme effet secondaire peut sembler négatif, mais normalement, l'appel d'une fonction est le but même de la fonction elle-même. Je suppose que, puisque le terme fonction a été initialement utilisé en mathématiques, le calcul d'une valeur est considéré comme effet primaire d'une fonction tandis que tout autre effet est considéré effets secondaires . Certains langages de programmation utilisent le terme procédure pour éviter toute confusion avec les fonctions au sens mathématique.

Notez que

  1. Certaines procédures sont utiles à la fois pour leur valeur de retour et leur effet secondaire.
  2. Certaines procédures ne calculent qu'une valeur de résultat et n'ont aucun autre effet. On les appelle souvent des fonctions pures car elles ne font que calculer une fonction au sens mathématique.
  3. Certaines procédures, par exemple sleep() en Python, ne sont utiles que pour leurs effets (secondaires),. Celles-ci sont souvent modélisées comme des fonctions qui renvoient une valeur spéciale None, ou unit ou () ou ..., qui indique simplement que le calcul s'est terminé correctement.
24
Giorgio

Un effet secondaire est lorsqu'une opération a un effet sur une variable/un objet qui est en dehors de l'utilisation prévue.

Cela peut arriver lorsque vous appelez une fonction complexe qui a pour effet secondaire de modifier une variable globale, même si ce n'est pas la raison pour laquelle vous l'avez appelée (peut-être l'avez-vous appelée pour extraire quelque chose d'une base de données).

J'avoue que j'ai du mal à trouver un exemple simple qui ne semble pas totalement artificiel, et les exemples de choses sur lesquelles j'ai travaillé sont trop longs pour être publiés ici (et comme c'est lié au travail, je ne devrais probablement pas de toute façon ).

Un exemple que j'ai vu (il y a un certain temps) était une fonction qui ouvrait une connexion à une base de données si la connexion était fermée. Le problème était qu'il était censé fermer la connexion à la fin de la fonction, mais le développeur a oublié d'ajouter ce code. Donc, ici, il y avait un effet secondaire involontaire : l'appel d'une procédure était censé faire seulement une requête et l'effet secondaire était que la connexion restait ouverte et si la fonction a été appelée deux fois de suite, une erreur serait survenue indiquant que la connexion était déjà ouverte.


Ok, donc puisque tout le monde donne des exemples maintenant, je pense que je le ferai aussi;)

/*code is PL/SQL-styled pseudo-code because that's what's on my mind right now*/

g_some_global int := 0; --define a globally accessible variable somewhere.

function do_task_x(in_a in number) is
begin
    b := calculate_magic(in_a);
    if b mod 2 == 0 then
        g_some_global := g_some_global + b;
    end if;
    return (b * 2.3);
end;

La fonction do_task_x a un effet principal de renvoi du résultat de certains calculs, et un effet côté de modification éventuelle d'une variable globale.

Bien sûr, qui est le principal et qui est l'effet secondaire pourrait être sujet à interprétation et pourrait dépendre de l'utilisation réelle. Si j'appelle cette fonction dans le but de modifier le global et que je rejette la valeur retournée, je dirais que modifier le global est le principal effet.

En informatique, une fonction ou une expression est censée avoir un effet secondaire si elle modifie un état ou a une interaction observable avec les fonctions d'appel ou le monde extérieur.

De Wikipedia - Effet secondaire

Une fonction, au sens mathématique, est un mappage de l'entrée à la sortie. L'appel d'une fonction a pour effet de mapper l'entrée sur la sortie qu'elle renvoie. Si la fonction fait autre chose, peu importe quoi, mais si elle a un comportement qui ne mappe pas l'entrée à la sortie, ce comportement est connu pour être un effet secondaire.

En termes plus généraux, un effet secondaire est tout effet qui n'est pas l'effet recherché par le concepteur de la construction.

Un effet est tout ce qui affecte un acteur. Si j'appelle une fonction qui envoie à ma copine un message texte de rupture, qui affecte un groupe d'acteurs, moi, elle, le réseau de la société de téléphonie mobile, etc. Le seul effet prévu d'appeler une fonction sans effet secondaire est pour la fonction pour me renvoyer un mappage de mon entrée. Donc pour:

   public void SendBreakupTextMessage() {
        Messaging.send("I'm breaking up with you!")
   }

Si cela est destiné à être une fonction, alors la seule chose à faire est de retourner void. S'il était exempt d'effets secondaires, il ne devrait pas réellement envoyer le message texte.

Dans la plupart des langages de programmation, il n'y a pas de construction pour une fonction mathématique. Aucune construction n'est destinée à être utilisée en tant que telle. C'est pourquoi la plupart des langues disent que vous avez des méthodes ou des procédures. De par leur conception, ceux-ci sont destinés à être en mesure de faire beaucoup plus d'effets. Dans le langage de programmation courant, personne ne se soucie vraiment de l'intention de ce qu'est une méthode ou une procédure, donc quand quelqu'un dit que cette fonction a un effet secondaire, cela signifie effectivement que cette construction ne se comporte pas comme une fonction mathématique. Et quand quelqu'un dit que cette fonction est exempte d'effets secondaires, ils veulent dire que cette construction se comporte effectivement comme une fonction mathématique.

Une fonction pure est toujours sans effet secondaire, par définition. Une fonction pure est une façon de dire que cette fonction, même si elle utilise une construction qui permet plus d'effets, n'a pour effet qu'un égal à celui d'une fonction mathématique.

Je mets au défi quiconque de me dire quand une fonction sans effet secondaire ne serait pas pure. À moins que l'effet principal prévu du contexte de la phrase utilisant le terme pur et effet secondaire libre ne soit pas celui de l'effet mathématique prévu d'une fonction, ceux-ci sont toujours égaux.

En tant que tel, parfois, bien que plus rarement, et je pense que c'est la distinction qui fait défaut et qui induit également en erreur (car ce n'est pas l'hypothèse la plus courante) dans la réponse acceptée, mais parfois on suppose que l'effet recherché d'une fonction de programmation est pour mapper l'entrée à la sortie, où l'entrée n'est pas limitée aux paramètres explicites de la fonction, mais la sortie est contrainte à la valeur de retour explicite. Si vous supposez que c'est l'effet recherché, une fonction lisant un fichier et renvoyant un résultat différent en fonction de ce qui se trouve dans le fichier est toujours sans effet secondaire, car vous autorisez les entrées à provenir d'autres endroits dans l'effet recherché.

Alors, pourquoi est-ce si important?

Il s'agit de contrôler et de garder. Si vous appelez une fonction et qu'elle fait autre chose puis renvoie une valeur, il est difficile de raisonner sur son comportement. Vous devrez aller chercher à l'intérieur de la fonction le code réel pour deviner ce qu'il fait et affirmer son exactitude. La situation idéale est qu'il est très clair et facile de savoir quelle entrée la fonction utilise et qu'elle ne fait rien d'autre que de renvoyer une sortie pour elle. Vous pouvez assouplir cela un peu et dire que savoir exactement quelle entrée il utilise n'est pas aussi utile qu'être certain qu'il ne fait rien d'autre dont vous pourriez ne pas être conscient, puis renvoyer une valeur, alors peut-être êtes-vous satisfait de ne faire appliquer que qu'il ne fait rien d'autre que mapper l'entrée, peu importe d'où il vient, à la sortie.

Dans presque tous les cas, le but d'un programme est d'avoir des effets autres que le mappage des choses entrant dans les choses sortant. L'idée de contrôler l'effet secondaire est que vous pouvez organiser le code d'une manière plus facile à comprendre et à raisonner. Si vous mettez tous les effets secondaires ensemble, dans un endroit très explicite et central, il est facile de savoir où chercher et de croire que c'est tout ce qui se passe, plus maintenant. Si vous avez également une entrée très explicite, cela permet de tester le comportement pour différentes entrées, et il est plus facile à utiliser, car vous n'avez pas besoin de modifier l'entrée à de nombreux endroits différents, certains qui pourraient ne pas être évidents, juste pour obtenir ce que vous voulez.

Parce que le plus utile pour comprendre, raisonner et contrôler le comportement d'un programme est de regrouper et d'expliciter clairement toutes les contributions, ainsi que de regrouper et d'expliciter tous les effets secondaires, c'est généralement ce dont les gens parlent lorsqu'ils disent effet secondaire, pur, etc.

Parce que le plus utile est le regroupement des effets secondaires et de leur explication, parfois les gens ne signifient que cela, et le distinguent en disant que ce n'est pas pur, mais toujours "sans effet secondaire" libre. Mais l'effet secondaire est relatif à l '"effet principal escompté" supposé, c'est donc un terme contextuel. Je trouve que cela est moins souvent utilisé, bien que, de façon surprenante, il en soit beaucoup question dans ce fil.

Enfin, idempotent signifie que l'appel de cette fonction plusieurs fois avec les mêmes entrées (peu importe d'où elles viennent) aura toujours les mêmes effets (effet secondaire ou non).

3
Didier A.

En programmation, un effet secondaire survient lorsqu'une procédure modifie une variable de l'extérieur de sa portée. Les effets secondaires ne dépendent pas de la langue. Il existe certaines classes de langages qui visent à éliminer les effets secondaires (langages fonctionnels purs), mais je ne sais pas s'il en existe qui nécessitent des effets secondaires, mais je peux me tromper.

Pour autant que je sache, il n'y a pas d'effets secondaires internes et externes.

2
indyK1ng

Voici un exemple simple:

int _totalWrites;
void Write(string message)
{
    // Invoking this function has the side effect of 
    // incrementing the value of _totalWrites.
    _totalWrites++;
    Debug.Write(message);
}

La définition de l'effet secondaire n'est pas spécifique à la programmation, alors imaginez simplement les effets secondaires de vos médicaments ou de manger trop de nourriture.

0
ChaosPandion