5.1. Pourquoi les fonctions

Lorsque l’on programme, il arrive régulièrement que l’on souhaite utiliser le même groupe d’instructions en plusieurs endroits et parfois dans de différents contextes, au sein d’un même programme, afin par exemple de résoudre un problème particulier ou d’effectuer une action complexe. La fonction est une structure qui permet de donner un nom à un tel bloc de code et de l’appeler (pour l’exécuter) à de multiples reprises.

Les fonctions sont d’excellents moyens de structurer le code, en le rendant plus lisible, plus court, plus modulable, et en subdivisant les problèmes complexes en plusieurs sous-problèmes plus simples. En outre, une modification du code d’une fonction se reflétera à chaque appel de cette dernière. Cette propriété est particulièrement utile lors de la correction d’erreurs car il suffit de modifier le code en un seul endroit !

On peut voir les fonctions comme de petits sous-programmes dans un grand programme. Généralement, une fonction reçoit des valeurs en entrée (les paramètres ou arguments) et renvoie une ou plusieurs valeurs en sortie (le résultat), mais cela n’est pas obligatoire. On peut alors faire le rapprochement entre les fonctions informatiques et les fonctions mathématiques : la fonction sin(x), par exemple, reçoit la valeur d’un angle x en entrée et renvoie la valeur de son sinus en sortie.

\[a \rightarrow \boxed{\sin(x)} \rightarrow \sin(a)\]

De manière plus générale, une fonction f() se comporte comme une boîte qui reçoit en paramètre un ensemble de valeurs et produit un résultat sur la base de ces valeurs.

\[a, b, \ldots \rightarrow \boxed{f(x, y, \ldots)} \rightarrow f(x{=}a, y{=}b, \ldots)\]

5.1.1. Un exemple concret

Avant d’apprendre à déclarer des fonctions, voyons un exemple concret d’utilisation. On souhaite écrire un programme qui lit un fichier chiffré sur le disque, le déchiffre, puis crée un deuxième fichier de texte et y inscrit le message en clair. Ce programme, plutôt complexe, peut se diviser en 3 blocs, soit 3 fonctions :

  1. Une fonction qui ouvre un fichier sur le disque et en lit le contenu.

  2. Une fonction qui reçoit du texte chiffré en entrée et qui le déchiffre en clair.

  3. Une fonction qui reçoit du texte, crée un fichier sur le disque et y inscrit le texte.

En assemblant ces 3 fonctions, on obtient le programme final. Cependant, elles se chargent chacune d’une tâche bien plus simple. Par exemple, la deuxième fonction ne se préoccupe pas de savoir d’où vient le message chiffré, ni de ce qui en sera fait par la suite. De la même manière, la troisième fonction n’a pas connaissance que le message qu’elle écrit sur le disque est un message qui a été préalablement déchiffré.

Le premier avantage de cette structure est qu’en cas d’erreur, il est facile d’en trouver la provenance. Il suffit de tester chaque fonction une à une, en isolation, avec des entrées dont on connaît le résultat attendu pour localiser l’erreur. Comme deuxième avantage, on remarquera que chacune de ces fonctions peut être utilisée en dehors du contexte pour lequel elle a été créée. Par exemple, on pourrait réutiliser la première fonction pour un programme qui lit le contenu d’un fichier et l’affiche simplement dans la console, sans qu’il s’agisse pour autant de texte chiffré.

Pour parvenir à combiner (ou chaîner) plusieurs fonctions de la sorte, il est important que la sortie de l’une corresponde à l’entrée de la suivante, et ainsi de suite. Il faudra sinon ajouter des opérations pour convertir les données entre les différents appels de fonctions.