réseau informatique
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
-45%
Le deal à ne pas rater :
PC Portable LG Gram 17″ Intel Evo Core i7 32 Go /1 To
1099.99 € 1999.99 €
Voir le deal

Fonctions et procédures

Aller en bas

Fonctions et procédures Empty Fonctions et procédures

Message par dare_devil Mar 11 Mar - 19:34

1. Fonctions personnalisées



1.1 De quoi s'agit-il ?



Une application,
surtout si elle est longue, a toutes les chances de devoir procéder aux
mêmes traitements, ou à des traitements similaires, à plusieurs endroits de
son déroulement. Par exemple, la saisie d’une réponse par oui ou par non
(et le contrôle qu’elle implique), peuvent être répétés dix fois à des
moments différents de la même application, pour dix questions différentes.


La manière la plus évidente, mais aussi la moins habile, de programmer ce genre de choses,
c'est bien entendu de répéter le code correspondant autant de fois que nécessaire.
Apparemment, on ne se casse pas la tête : quand il faut que la machine
interroge l'utilisateur, on recopie les lignes de codes
voulues en ne changeant que le nécessaire, et roule Raoul. Mais en procédant de cette manière, la pire qui
soit, on se prépare des lendemains qui déchantent...


D'abord, parce que si la structure d'un programme écrit de cette manière peut paraître simple, elle est
en réalité inutilement lourdingue. Elle contient des répétitions, et pour peu que le programme soit joufflu, il peut
devenir parfaitement illisible. Or, le fait d'être facilement modifiable
donc lisible, y compris - et surtout - par ceux qui ne l'ont pas écrit est
un critère essentiel pour un programme informatique ! Dès que l'on
programme non pour soi-même, mais dans le cadre d'une organisation
(entreprise ou autre), cette nécessité se fait sentir de manière aiguë.
L'ignorer, c'est donc forcément grave.


En plus, à un autre niveau, une telle structure pose des
problèmes considérables de maintenance : car en cas de modification du code, il va
falloir traquer toutes les apparitions plus ou moins identiques de ce code pour faire convenablement
la modification ! Et si l'on en oublie une, patatras, on a laissé un
bug.


Il faut donc opter pour une autre stratégie, qui consiste à séparer ce traitement du
corps du programme et à regrouper les instructions qui le composent en un
module séparé. Il ne restera alors plus qu'à appeler ce groupe d'instructions (qui n'existe donc
désormais
qu’en un exemplaire unique) à chaque fois qu’on en a besoin. Ainsi, la
lisibilité est assurée ; le programme devient
modulaire,
et il suffit de faire une seule modification au bon endroit, pour que cette modification prenne
effet dans la totalité de l’application.


Le corps du programme s’appelle alors la
procédure principale,
et ces groupes d’instructions auxquels on a recours s’appellent des
fonctions et des sous-procédures
(nous verrons un peu plus loin la différence entre ces deux termes).


Reprenons un exemple de question à laquelle l’utilisateur doit répondre par oui ou par
non.
Mauvaise Structure :


...
Ecrire "Etes-vous marié ?"
Rep1 ← ""
TantQue Rep1 <> "Oui" et Rep1 <> "Non"

Ecrire
"Tapez Oui ou Non"

Lire
Rep1
FinTantQue
...
Ecrire "Avez-vous des enfants ?"
Rep2 ← ""
TantQue Rep2 <> "Oui" et Rep2 <> "Non"

Ecrire
"Tapez Oui ou Non"

Lire
Rep2
FinTantQue
...












On le voit bien,
il y a là une répétition quasi identique du traitement à accomplir. A chaque
fois, on demande une réponse par Oui ou Non, avec contrôle de saisie. La
seule chose qui change, c'est le nom de la variable dans laquelle on range
la réponse. Alors, il doit bien y avoir un truc.


La solution, on vient de le voir,
consiste à isoler les instructions
demandant une réponse par Oui ou Non, et à appeler ces instructions à chaque
fois que nécessaire. Ainsi, on évite les répétitions inutiles, et on a
découpé notre problème en petits morceaux autonomes.


Nous allons donc créer une fonction dont le rôle sera de
renvoyer la réponse (oui ou non) de
l'utilisateur. Ce mot de "
fonction", en l'occurrence, ne doit pas nous
surprendre : nous avons étudié précédemment des fonctions fournies avec le
langage, et nous avons vu que le but d'une fonction était de
renvoyer une
valeur. Eh bien, c'est exactement la même chose ici, sauf que c'est nous qui
allons créer notre propre fonction, que nous appellerons RepOuiNon :


Fonction RepOuiNon() en caractère
Truc ← ""
TantQue Truc <> "Oui" et Truc <> "Non"

Ecrire
"Tapez Oui ou Non"

Lire
Truc
FinTantQue
Renvoyer Truc
Fin







On remarque au
passage l’apparition d’un nouveau mot-clé :

Renvoyer, qui indique quelle valeur doit prendre la fonction
lorsqu'elle est utilisée par le programme. Cette
valeur renvoyée par la fonction (ici, la valeur de la variable Truc) est en
quelque sorte contenue dans le nom de la fonction lui-même, exactement comme
c’était le cas dans les fonctions prédéfinies.


Une fonction
s'écrit toujours
en-dehors de la procédure principale.
Selon les langages,
cela peut prendre différentes formes. Mais ce qu'il faut comprendre, c'est
que ces quelques lignes de codes sont en quelque sorte des satellites, qui
existent en dehors du traitement lui-même. Simplement, elles sont à sa
disposition, et il pourra y faire appel chaque fois que nécessaire. Si l'on
reprend notre exemple, une fois notre fonction RepOuiNon écrite, le
programme principal comprendra les lignes :
Bonne structure :

...
Ecrire
"Etes-vous marié ?"
Rep1 ← RepOuiNon()
...
Ecrire
"Avez-vous des enfants ?"
Rep2 ← RepOuiNon()
...





Et le tour est
joué ! On a ainsi évité les répétitions inutiles, et si d'aventure, il y
avait un bug dans notre contrôle de saisie, il suffirait de faire une seule
correction dans la fonction RepOuiNon pour que ce bug soit éliminé de toute
l'application. Elle n'est pas belle, la vie ?


Toutefois, les plus sagaces d'entre vous auront remarqué, tant dans le titre de la fonction
que dans chacun des appels, la présence de

parenthèses. Celles-ci, dès qu'on déclare ou qu'on appelle une
fonction, sont obligatoires. Et si vous avez bien compris tout ce qui
précède, vous devez avoir une petite idée de ce qu'on va pouvoir mettre
dedans...



1.2 Passage d'arguments



Reprenons
l’exemple qui précède et analysons-le. On écrit un message à l'écran, puis
on appelle la fonction RepOuiNon pour poser une question ; puis, un peu plus
loin, on écrit un
autre message à l'écran, et on appelle de nouveau la fonction pour poser la même question, etc.
C’est une démarche acceptable, mais qui peut encore être améliorée : puisque
avant chaque question, on doit écrire un message, autant que cette écriture
du message figure directement dans la fonction appelée. Cela implique deux
choses :




  • lorsqu’on appelle la fonction, on doit lui préciser quel message elle doit
    afficher avant de lire la réponse

  • la fonction doit être « prévenue » qu’elle recevra un message, et être capable
    de le récupérer pour l’afficher.



En langage algorithmique, on dira que
le message devient un
argument (ou un paramètre) de la fonction.
Cela n'est certes pas une découverte pour vous : nous
avons longuement utilisé les arguments à propos des fonctions prédéfinies.
Eh bien, quitte à construire nos propres fonctions, nous pouvons donc
construire nos propres arguments. Voilà
comment l’affaire se présente...


La fonction sera dorénavant déclarée comme suit :


Fonction RepOuiNon(Msg en Caractère) en Caractère
Ecrire Msg
Truc ← ""
TantQue Truc <> "Oui" et Truc <> "Non"

Ecrire
"Tapez Oui ou Non"

Lire
Truc
FinTantQue
Renvoyer Truc
Fin Fonction









Il y a donc
maintenant entre les parenthèses une variable, Msg, dont on précise le type, et qui signale à la
fonction qu’un argument doit lui être envoyé à chaque appel. Quant à ces
appels, justement, ils se simplifieront encore dans la procédure principale,
pour devenir :

...
Rep1 ← RepOuiNon("Etes-vous marié ?")
...
Rep2 ← RepOuiNon("Avez-vous des enfants ?")
...

Et voilà le travail.


Une remarque importante : là,
on n'a passé qu’un seul argument en entrée. Mais bien entendu, on peut en
passer autant qu’on veut, et créer des fonctions avec deux, trois, quatre,
etc. arguments ; Simplement, il faut éviter d'être gourmands, et il suffit
de passer ce dont on en a besoin, ni plus, ni moins !


Dans le cas que
l'on vient de voir, le passage d'un argument à la fonction était élégant, mais pas
indispensable. La preuve, cela marchait déjà très bien avec la première
version. Mais on peut imaginer des situations où il faut absolument
concevoir la fonction de sorte qu'on doive lui transmettre un certain nombre
d'arguments si l'on veut qu'elle puisse remplir sa tâche. Prenons, par
exemple, toutes les fonctions qui vont effectuer des calculs. Que ceux-ci
soient simples ou compliqués, il va bien falloir envoyer à la fonction les
valeurs grâce auxquelles elle sera censé produire son résultat (pensez tout
bêtement à une fonction sur le modèle d'Excel, telle que celle qui doit
calculer une somme ou une moyenne). C'est
également vrai des fonctions qui traiteront des chaînes de caractères. Bref,
dans 99% des cas, lorsqu'on créera une fonction, celle-ci devra comporter
des arguments.



1.3 Deux mots sur l'analyse fonctionnelle



Comme souvent en algorithmique, si l'on s'en tient à la manière dont
marche l'outil, tout cela n'est en réalité pas très compliqué. Les fonctions
personnalisées se déduisent très logiquement de la manière nous nous avons
déjà expérimenté les fonctions prédéfinies.

Le plus difficile, mais aussi le plus important, c'est d'acquérir
le réflexe de
constituer systématiquement les fonctions adéquates quand on doit traiter
un problème donné, et
de flairer la bonne manière de découper son algorithme
en différentes fonctions pour le rendre léger, lisible et performant.

Cette partie de la réflexion s'appelle d'ailleurs l'analyse
fonctionnelle d'un problème, et c'est toujours par elle qu'il faut
commencer : en gros, dans un premier temps, on découpe le traitement en
modules (algorithmique fonctionnelle), et dans un deuxième temps, on écrit chaque module
(algorithmique classique). Cependant, avant
d'en venir là, il nous faut découvrir deux autres outils, qui prennent le relais
là où les fonctions deviennent incapables de nous aider.
exercice
2. Sous-Procédures


2.1 Généralités




Les fonctions, c'est bien, mais dans certains cas, ça ne nous rend guère
service.


Il peut en effet arriver que dans un programme, on ait à réaliser des tâches
répétitives, mais que ces tâches n'aient pas pour rôle de générer une
valeur particulière, ou qu'elles aient pour rôle d'en générer plus d'une à
la fois. Vous ne voyez pas de quoi je veux parler ? Prenons deux exemples.


Premier exemple. Imaginons qu'au cours de mon application, j'aie plusieurs
fois besoin d'effacer l'écran et de réafficher un bidule comme un petit logo
en haut à gauche. On pourrait se dire qu'il faut créer une fonction pour
faire cela. Mais quelle serait la valeur renvoyée par la fonction ? Aucune !
Effacer l'écran, ce n'est pas produire un résultat stockable dans une
variable, et afficher un logo non plus. Voilà donc une situation ou j'ai
besoin de répéter du code, mais où ce code n'a pas comme rôle de produire
une valeur.


Deuxième exemple. Au cours de mon application, je dois plusieurs fois faire
saisir un tableau d'entiers (mais à chaque fois, un tableau différent). Là
encore, on serait tenté d'effectuer toutes ces saisies de tableaux dans une
seule fonction. Mais problème, une fonction ne peut renvoyer qu'une seule
valeur à la fois. Elle ne peut donc renvoyer un tableau, qui est une série
de valeurs distinctes.


Alors, dans ces deux cas, faute de pouvoir traiter l'affaire par une fonction,
devra-t-on en rester au
code répétitif dont nous venons de dénoncer si vigoureusement les faiblesses
? Mmmmmh ? Vous vous doutez bien que non. Heureusement, tout est prévu, il y a
une solution. Et celle-ci consiste à utiliser des

sous-procédures.
en préparation de la suite...
Twisted Evil Twisted Evil Twisted Evil
dare_devil
dare_devil
Admin
Admin

Messages : 80
Date d'inscription : 13/02/2008

Revenir en haut Aller en bas

Revenir en haut


 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
Ne ratez plus aucun deal !
Abonnez-vous pour recevoir par notification une sélection des meilleurs deals chaque jour.
IgnorerAutoriser