Effet de bord (informatique)

Un article de Wikipédia, l'encyclopédie libre.
Sauter à la navigation Sauter à la recherche
Page d'aide sur l'homonymie Pour les articles homonymes, voir Effet de bord.

En informatique, une fonction est dite à effet de bord (traduction mot à mot de l'anglais side effect, dont le sens est plus proche d'effet secondaire) si elle modifie un état en dehors de son environnement local, c'est-à-dire a une interaction observable avec le monde extérieur autre que retourner une valeur. Par exemple, les fonctions qui modifient une variable locale statique, une variable non locale ou un argument mutable passé par référence, les fonctions qui effectuent des opérations d'entrées-sorties ou les fonctions appelant d'autres fonctions à effet de bord[1]. Souvent, ces effets compliquent la lisibilité du comportement des programmes et/ou nuisent à la réutilisabilité des fonctions et procédures. Un langage comme Haskell les restreint délibérément dans des composants nommés monades.

Plus communément, un effet de bord apparaît la plupart du temps lorsqu'une modification d'un programme cohérent (valeurs et états pris conformes aux spécifications) aboutit à des valeurs ou des comportements non prévus, à cause de la non prise en compte de la portée, de l'ensemble de définition de variables, ou du contrat des fonctions.

Langages[modifier | modifier le code]

La programmation impérative permet l'emploi des effets de bord dans le fonctionnement de ses programmes, voire l'utilise délibérément (par exemple la déclaration COMMON en FORTRAN) en permettant au compilateur d'en tenir compte (mot-clé volatile en C).

La spécification du langage Fortran interdisait qu'une fonction modifie ses paramètres d'appel, et la plupart des compilateurs y veillaient.

La programmation fonctionnelle cherche au contraire à les minimiser et les isole souvent pour cela dans des structures prévues entre autres pour cela : les monades.

Matériel[modifier | modifier le code]

Dans la conception des processeurs, des instructions peuvent modifier l'état interne du processeur sans le déclarer explicitement. Ainsi une instruction d'addition peut ou non modifier des variables de conditions (retenue, zéro, débordement…). Cela pose un problème de conception si le processeur comporte un pipeline d'instructions. Ainsi, le 360/91 d'IBM, muni de quatre unités arithmétiques et logiques travaillant simultanément, rapportait parfois une IMPRECISE INTERRUPT (déroutement mal localisé) « dans les parages » d'une certaine adresse, sans pouvoir préciser davantage laquelle.

On peut éviter ces aléas en limitant le jeu d'instructions à des instructions sans effet de bord. Dans le pire des cas, des circuits additionnels détectent les effets de bord et invalident le pipeline si l'instruction suivante dans celui-ci dépend des valeurs affectées. Le calcul est donc simplement un peu retardé.

Opérateurs à effet de bord[modifier | modifier le code]

Par extension[2], on dit d'un opérateur qu'il a un effet de bord lorsqu'il modifie la valeur de l'un de ses opérandes.

La valeur résultant de l'opération peut être utilisée (stockée dans une variable ou transmise en paramètre d'une fonction, par exemple), mais de tels opérateurs sont souvent employés uniquement pour leur effet de bord. L'expression, comportant une opération dont le résultat est ignoré, devient alors une instruction.

Exemples en C++ :

++x;         // ++ incrémente x
c = b += a;  // le résultat de += est stocké dans c mais celui de = est ignoré

L'opérateur d'affectation = est souvent employé par erreur à la place de l'opérateur d'égalité ==. Son effet de bord est de modifier son 1er opérande en lui affectant la valeur de son 2e opérande. Son résultat est la valeur qui a été affectée.

if (x = 0) {           // x est modifiée et devient 0
  std::cout << "nul";  // "nul" n'est jamais affichée car x = 0 renvoie toujours 0
}

Transparence référentielle[modifier | modifier le code]

Ne pas avoir d'effet de bord est une condition nécessaire mais non suffisante pour la transparence référentielle. La transparence référentielle signifie qu'une expression (telle qu'un appel de fonction) peut être remplacée par sa valeur sans affecter le comportement du programme. L'expression doit pour cela être pure, c'est-à-dire avoir la même valeur pour les mêmes entrées et son évaluation ne doit pas avoir d'effets de bord. Une fonction sans effets de bord peut retourner des valeurs différentes selon son histoire ou son environnement externe, par exemple si sa sortie dépend de la valeur d'une variable locale statique ou d'une variable non locale respectivement.

Exemple d'un programme utilisant un effet de bord en C++[modifier | modifier le code]

#include <iostream>
 
int x = 0;

void f() {
  x = 1;
}

int main() {
  std::cout << x << std::endl;
  f();
  std::cout << x << std::endl;
  return 0;
}

Ce programme imprime sur la sortie standard :

0
1

L'effet de bord de la fonction f est de modifier la valeur de la variable globale x.

Notes et références[modifier | modifier le code]

  1. (en) David A. Spuler et A. Sayed Muhammed Sajeev, « Compiler Detection of Function Call Side Effects », sur CiteSeerX, (consulté le 18 août 2018) : « The term Side effect refers to the modification of the nonlocal environment. Generally this happens when a function (or a procedure) modifies a global variable or arguments passed by reference parameters. But here are other ways in which the nonlocal environment can be modified. We consider the following causes of side effects through a function call: 1. Performing I/O. 2. Modifying global variables. 3. Modifying local permanent variables (like static variables in C). 4. Modifying an argument passed by reference. 5. Modifying a local variable, either automatic or static, of a function higher up in the function call sequence (usually via a pointer). »
  2. Les opérateurs pouvant être considérés comme des fonctions

Voir aussi[modifier | modifier le code]