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

89

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

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

S'il vous plaît donner quelques exemples de causes qui créent des effets secondaires.

Amir Rezaei
la source
7
Cela ressemble beaucoup à des devoirs.
gnasher729
3
@ gnasher729 qui se soucie de cela est génialement utile :)
Charlie Parker

Réponses:

109

Un effet secondaire fait simplement référence à la modification d'un type d'état - par exemple:

  • Changer la valeur d'une variable;
  • Écrire des données sur le disque;
  • Activer ou désactiver un bouton dans l'interface utilisateur.

Contrairement à ce que certaines personnes semblent dire:

  • Un effet secondaire ne doit pas nécessairement être caché ou inattendu (cela peut ê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 idempotency. Une fonction idempotente peut avoir des effets secondaires, et une fonction non-idempotente peut ne pas en avoir (par exemple, obtenir la date et l'heure actuelles du système).

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

PS Comme le commente Benjol l'a fait remarquer, plusieurs personnes peuvent associer la définition d'un effet secondaire à la définition d'une fonction pure , fonction qui est (a) idempotente et (b) ne produit pas d'effets secondaires. L’un n’implique pas l’autre en informatique générale, mais les langages de programmation fonctionnels tendent généralement à imposer ces deux contraintes.

Aaronaught
la source
38
L'expression "effet secondaire" donne l'impression que quelque chose d' autre est en train d'être modifié, autre que ce qui était prévu. En médecine, un médicament aura pour effet principal de réduire la douleur et parfois aussi de causer des saignements de nez, des vertiges, etc. Le but du médicament n'est pas de provoquer des saignements de nez résultat supplémentaire non prévu .
FrustratedWithFormsDesigner
15
@ Frustré: +1. Chaque fois que je vois ce terme, je ne peux m'empêcher de me demander si les défenseurs de la PF n'ont pas choisi de créer précisément cette connotation subtilement sinistre.
Mason Wheeler
6
@Mason Wheeler. Cela existait bien avant la FP. Et ce n'est pas une connotation subtilement sinistre. C'est le mal absolu et l'a toujours été. Depuis trois décennies que je code, la déclaration de "crypto-assignation" - l'effet secondaire - inquiète les gens. Il est beaucoup plus facile de composer avec une ancienne déclaration de mission.
S.Lott
7
@Mason Wheeler: En C ++a.. Ne ressemble pas à une cession. b = ++a;a deux effets secondaires. L'évident et la crypto-assignation de a. C'est le genre de chose qui est un effet secondaire (pour certains) souhaitable. Mais a été appelé un effet secondaire pour toute ma carrière pour le rendre pas subtile.
S.Lott
5
@ Zachary, s'il vous plaît voir le dernier point de ma réponse. Vous faites référence à un comportement idempotent (ou à son absence). Cela ne vous dit rien sur les effets secondaires. La vérification de l'horloge système n'est pas un effet secondaire. En fait, toute fonction ou méthode précédée du mot "get" est une fonction à laquelle vous devriez raisonnablement vous attendre sans effets secondaires.
Aaronaught
36

Toute opération qui modifie l'état de l'ordinateur ou qui interagit avec le monde extérieur est réputée avoir un effet secondaire. Voir Wikipedia sur les effets secondaires .

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

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

En revanche, l’appel de 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 d’écrire des données dans 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); }
Kristopher Johnson
la source
1
C'est une bonne définition, mais je ne suis pas folle de l'élaboration - tout comme dans la réponse de Thorbjørn, une partie de celle-ci semble confondre la question des effets secondaires avec celle des fonctions idempotentes; Comme votre Writeexemple le montre, avoir des effets secondaires n'implique pas que la fonction modifie jamais sa sortie par rapport à ses entrées, ni même que sa sortie dépend de l'entrée.
Aaronaught
6
Il ne s'agit pas d'être idempotent. Le fait qu'il produise une sortie signifie qu'il a un effet secondaire.
Kristopher Johnson
Dans certains systèmes, l'appel square(x)peut entraîner le chargement du disque du module où la fonction est définie. Cela devrait-il être considéré comme un effet secondaire? Après tout, ce mois-ci que le (premier) appel prend un temps inattendu, l'utilisation de la RAM augmente, etc.
Hagen von Eitzen
1
@HagenvonEitzen Chaque opération modifie réellement l'état de l'ordinateur (registres du processeur, mémoire, consommation électrique, chaleur, etc.). "Effet secondaire" fait généralement référence à un environnement d'exécution idéalisé imaginaire où rien ne change dans cet environnement, à moins que le programme ne le modifie explicitement. Mais si vous appelez square(x) pour que l'état de votre ordinateur externe change, vous pouvez considérer cela comme un effet secondaire.
Kristopher Johnson
Pour moi, la première illustration est parfaitement logique. Cependant, le second l'est moins. Je pense que l’effet secondaire devrait être défini par rapport à un certain environnement / champ d’application. Si vous considérez l’ensemble de l’univers, il n’existe aucun effet secondaire. Même si vous le limitez à l'ordinateur, votre fonction affectera d'autres processus en ce sens que le processeur ne se comportera pas de la même manière. Si vous limitez la portée aux éléments accessibles dans une étendue de fonction locale, nous avons quelque chose à discuter.
funct7
21

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

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

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

  1. Il calcule une fonction au sens mathématique, c’est-à-dire à partir de valeurs d’entrée, il renvoie un résultat, ou
  2. Cela produit un effet, par exemple, affiche quelque chose à l'écran, modifie une valeur dans 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 également à d’autres aspects tels que 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 l’objet même de la fonction elle-même. Je suppose que, puisque le terme fonction a été utilisé à l'origine en mathématiques, le calcul d'une valeur est considéré comme le principal effet d'une fonction, alors que tout autre effet est considéré comme un effet secondaire . 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 renvoyant une valeur spéciale None, ou unitou ()ou ..., ce qui indique simplement que le calcul s'est terminé correctement.
Giorgio
la source
2
À mon humble avis, cela devrait être la réponse acceptée. La notion d'effet secondaire n'a de sens que pour les fonctions mathématiques. Une procédure est conçue pour regrouper simplement un ensemble d’instructions de manière structurée tout en vous permettant d’y accéder facilement à partir de cet emplacement et de revenir à l’arrière. Il n'y a pas d'effet primaire ni d'effet secondaire. Vous pourriez peut-être dire que le fait de lever une exception est un effet secondaire d'une procédure, car cela brise le sens de la procédure qui est de vous ramener à l'endroit où vous l'avez laissé et de continuer à exécuter le formulaire là-bas.
Didier A.
4

Un effet secondaire survient lorsqu'une opération a un effet sur une variable / un objet 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 pour cette raison que vous l'avez appelée (vous l'avez peut-être appelée pour extraire quelque chose d'une base de données).

J'avoue que j'ai du mal à trouver un exemple simple qui n'a pas l'air totalement artificiel, et des exemples de choses sur lesquelles j'ai travaillé sont trop longs à publier 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 quelque temps) était une fonction qui ouvrait une connexion à une base de données si la connexion était dans un état fermé. Le problème était qu'il était supposé fermer la connexion à la fin de la fonction, mais le développeur avait oublié d'ajouter ce code. Donc, ici, il y avait un effet secondaire non intentionnel : l'appel d'une procédure était supposé faire uniquement une requête et l'effet secondaire était que la connexion restait ouverte et si la fonction était appelée deux fois de suite, une erreur serait générée en indiquant que la connexion était déjà ouvert.


Ok, 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_xa un premier effet de retourner le résultat de certains calculs, et un côté pour effet de modifier éventuellement une variable globale.

Bien sûr, ce qui est l'effet primaire et qui est le côté pourrait être ouvert à l' interprétation et peut 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 renvoyée, je dirais que la modification du global est l'effet principal.

FrustratedWithFormsDesigner
la source
2
Je ne pense pas que ce soit une bonne définition universelle. De nombreux programmeurs utilisent intentionnellement des constructions spécifiquement pour leurs effets secondaires.
CB Bailey
@ Charles: Assez bien. Dans ce cas, comment le définiriez-vous?
FrustratedWithFormsDesigner
2
Je pense que @KristopherJohnson a la définition la plus claire. Tout ce qui modifie cet état du programme ou de son environnement ou produit un effet réel tel que la production de sortie.
CB Bailey
@ Charles Bailey: Cela ne change pas la définition. Utiliser des choses pour les effets secondaires, c'est bien. Tant que vous comprenez qu'il y a un effet secondaire. Cela ne change rien à cette définition.
S.Lott
1
@SLott: La définition dans cette réponse (c'est-à-dire le premier paragraphe) inclut la clause: "en dehors de l'usage prévu". Je pense que mon commentaire était juste.
CB Bailey le
3

En informatique, une fonction ou une expression est dite avoir un effet secondaire si elle modifie un état ou a une interaction observable avec des fonctions appelantes ou avec le monde extérieur.

De Wikipedia - Effet secondaire

Une fonction, au sens mathématique, est un mappage d’entrée en 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, mais si elle a un comportement qui ne mappe pas l'entrée vers la sortie, ce comportement est connu pour être un effet secondaire.

En termes plus généraux, un effet secondaire est un 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 un message texte de séparation à ma petite amie, qui affecte un groupe d'acteurs, moi-même, elle-même, le réseau de l'entreprise de téléphonie mobile, etc. Le seul effet recherché en appelant une fonction sans effets secondaires, c'est pour la fonction pour me retourner un mappage de mon entrée. Donc pour:

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

Si cela est censé être une fonction, la seule chose à faire est de retourner vide. S'il était sans effet secondaire, il ne devrait pas 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 conçus pour pouvoir produire beaucoup plus d’effets. Dans le langage courant de la programmation, personne ne se soucie vraiment de l’intention de ce qu’est une méthode ou une procédure, ainsi quand on dit que cette fonction a un effet secondaire, ils veulent dire en réalité que cette construction ne se comporte pas comme une fonction mathématique. Et quand quelqu'un dit que cette fonction est sans effet secondaire, ils veulent dire que cette construction se comporte efficacement comme une fonction mathématique.

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

Je défie quiconque de me dire quand une fonction sans effets secondaires ne serait pas pure. À moins que l'effet recherché principal du contexte de la phrase utilisant les termes pur et effet secondaire secondaire ne soit pas celui de l'effet recherché mathématique d'une fonction, ceux-ci sont toujours égaux.

En tant que tel, parfois, bien que plus rarement, et je crois que c'est la distinction qui manque et qui égare les gens (car ce n'est pas l'hypothèse la plus courante) dans la réponse acceptée, mais on suppose parfois que l'effet recherché d'une fonction de programmation est: mapper l'entrée sur la sortie, entrée non contrainte aux paramètres explicites de la fonction, mais sortie limitée à la valeur de retour explicite. Si vous supposez que c'est l'effet recherché, alors une fonction lisant un fichier et renvoyant un résultat différent en fonction de son contenu est toujours sans effet secondaire, car vous avez autorisé les entrées provenant d'autres endroits de l'effet souhaité.

Alors, pourquoi est-ce si important?

Tout est question de contrôle et de maintien. Si vous appelez une fonction et que cette dernière renvoie une valeur, il est difficile de raisonner sur son comportement. Vous devrez aller à l'intérieur de la fonction pour que le code réel devine ce qu'il fait et affirme son exactitude. La situation idéale est qu’il est très clair et facile de savoir quelle entrée est utilisée par la fonction et qu’elle ne fait rien d’autre que de renvoyer une sortie pour elle. Vous pouvez vous détendre un peu et dire que savoir exactement quelle entrée il utilise n’est pas aussi utile que d’être certain de ne rien faire d’autre que vous pourriez ne pas être au courant, puis de renvoyer une valeur. Vous êtes donc peut-être content qu'il ne fait rien d'autre que mapper l'entrée, peu importe d'où il provient, à la sortie.

Dans presque tous les cas, le but d'un programme est d'avoir des effets autres que la cartographie des éléments entrant dans les éléments à venir. 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ù regarder et de croire que c'est tout ce qui se passe, pas plus. Si vous souhaitez que l'entrée soit très explicite également, cela permet de tester le comportement de différentes entrées, et il est plus facile à utiliser, car vous n'avez pas besoin de modifier l'entrée dans de nombreux endroits différents. Certains peuvent ne pas être évidents, pour obtenir ce que vous voulez.

Parce que le meilleur moyen de comprendre, de raisonner et de contrôler le comportement d’un programme est de regrouper toutes les entrées de manière claire et explicite, et de regrouper et d’expliciter tous les effets secondaires, c’est généralement ce dont les gens parlent quand ils disent: effet secondaire, pur, etc.

Parce que le plus utile est le regroupement des effets secondaires et de leur caractère explicite, parfois les gens ne veulent que le dire, et le différencient en disant que ce n'est pas pur, mais qu'il reste "sans effets secondaires". Mais l’effet secondaire est relatif à l’effet supposé «effet primaire voulu», il s’agit donc d’un terme contextuel. Je trouve que cela est moins souvent utilisé, bien qu’étonnamment, on en parle beaucoup dans ce fil.

Enfin, idempotent signifie que si vous appelez cette fonction plusieurs fois avec les mêmes entrées (peu importe d'où elles viennent), vous obtiendrez toujours les mêmes effets (effets secondaires ou non).

Didier A.
la source
Je pense qu'un gros problème avec l'explication des effets secondaires est que tant que vous n'avez pas utilisé un langage comme Ocaml ou Haskell, il peut être très difficile de raisonner à propos de la programmation gratuite (presque!) À effets secondaires.
Jamie Strauss
2

En programmation, un effet secondaire survient lorsqu'une procédure modifie une variable en dehors 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 suis pas sûr qu'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.

indyK1ng
la source
Pour être plus précis, les langages fonctionnels purs séparent clairement le code libre d'effets secondaires des autres codes, alors que les autres langages ne disposent pas de mécanisme permettant de distinguer les codes purs des codes impurs. La plupart des programmes doivent avoir des effets secondaires pour être utiles.
Giorgio
Je pense que certains langages de programmation pré-gui, tels que MS-BASIC et QBasic, ont pu être aussi proches que possible d’un langage à «effets secondaires». Et oui, vous pouvez avoir des effets secondaires internes et externes.
James K
0

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 des effets secondaires n’est pas spécifique à la programmation; imaginez simplement les effets secondaires de vos médicaments ou de l’alimentation.

ChaosPandion
la source
Mais si le message entre comme référence et que vous modifiez le message dans votre méthode, cela pourrait être un effet secondaire. Ai-je raison?
Amir Rezaei
Le fait que l'expression x++modifie la variable xest généralement considéré comme un effet secondaire. Cette valeur de l'expression est la valeur de pré-incrémentation de x; C’est la partie de l’effet non secondaire.
CB Bailey
@ Charles - Je suis d'accord, bien que l'exemple initial ne soit pas aussi clair que l'actuel.
ChaosPandion
@Amir - Cela dépend vraiment de la langue. S'il s'agissait de C #, cela ne serait pas considéré comme un effet secondaire.
ChaosPandion
@ ChaosPandion: Personnellement, je ne suis pas d'accord. L'exemple original était beaucoup plus simple et clair.
CB Bailey
-2

Un effet secondaire est ce qui se passe dans le code et qui n'est pas évident.

Par exemple, disons que vous avez cette classe

public class ContrivedRandomGenerator {
   public int Seed { get; set; }

   public int GetRandomValue()
   {
      Random(Seed);
      Seed++;
   }
}

Lorsque vous créez initialement la classe, vous lui donnez une graine.

var randomGenerator = new ContrivedRandomGenerator();
randomGenerator.Seed = 15;
randomGenerator.GetRandomValue();

Vous ne connaissez pas les composants internes, vous vous attendez simplement à obtenir une valeur aléatoire et vous vous attendez à ce que randomGenerator.Seed soit toujours 15 ... mais ce n'est pas le cas.

L’appel de fonction a eu l’effet secondaire de changer la valeur de la graine.

CaffGeek
la source
10
Les effets secondaires ne doivent pas être cachés. Vous pensez à un usage familier ou médical; en programmation, un effet secondaire fait simplement référence à la modification d'un état.
Aaronaught
1
L'impression sur la console est un effet secondaire. Ce n'est pas caché. From Wikipedia : "En informatique, une fonction ou une expression est dite avoir un effet secondaire si, en plus de renvoyer une valeur, elle modifie également un état ou a une interaction observable avec des fonctions appelantes ou avec le monde extérieur ."
Les effets secondaires sont la manière dont les non-fonctions (procédures) effectuent le travail. X = 1; X = Y (10) sont deux fonctions pures. Lorsque vous sortez du domaine "x = quel que soit", vous devez écrire le résultat dans le lecteur d'écran ou le lire au format "x = y" ou simplement changer la valeur d'une variable d'une chose à une autre. , c’est un effet secondaire.
James K
Je pense que par «caché», il veut dire non évident. Comme dans x = f (y, z) x peut être supposé être basé sur y et z. Alors que proc (x, y, z) ne vous dit rien de ce qui se passe. Chaque variable peut être modifiée ou aucune. Proc pourrait être un analogue de f, ou complètement indépendant. Une fonction pure a une réponse unique: 'x'. Allez au-delà, c'est un effet secondaire. Entièrement prévu, mais effets secondaires.
James K
Tout comme pour comprendre 0, vous devez d'abord comprendre 1: pour comprendre les effets secondaires, vous devez d'abord comprendre les fonctions.
James K