INF145 : DEUXIÈME COURS Les fonctions (première partie) Rappelons-nous quelques
INF145 : DEUXIÈME COURS Les fonctions (première partie) Rappelons-nous quelques considérations générales toutes issues du travail fait sur les algorithmes numériques (théorie comme exercices du premier cours) Dans l’implémentation d’un algorithme, on trouve au tout début les déclarations des variables nécessaires aux conditions initiales (CI) qui recevront des valeurs choisies librement par l’utilisateur. Puis viennent les déclarations des variables de travail avec leurs initialisations correctes (à valeurs contraintes, ces variables ne sont pas libres, les variables de travail servent au maintien du résultat et des valeurs transitoires des calculs). Vient ensuite le groupe cohérent d’instructions {expressions, conditionnelles et itératives} qui mènent au résultat. Seules les conditions initiales (CI) peuvent changer lors d’une exécution de l’algorithme. Tout le reste (initialisations des variables de travail et instructions) reste invariant et c’est fondamental pour l’assurance de qualité du logiciel : La méthode de calcul est bien spécifiée, l’utilisateur de ce code (le client) peut être assuré de sa performance. L’ensemble des variables de travail et des instructions doit être considéré comme une boîte noire aux comportements bien définis par son auteur Conceptuellement, un algorithme porte un nom, ce sera l’identificateur de la fonction bien choisi par son auteur. Ce nom doit être représentatif du résultat obtenu à son utilisation. Les Conditions Initiales essentielles pour obtenir une exécution correcte formeront ses paramètres -- et donner des valeurs cohérentes aux paramètres lors d’un appel de la fonction sera l’unique responsabilité du client – Grâce aux fonctions, peu importe la langue de programmation, on parle de gains fonctionnels. La création d’une fonction introduit un outil logiciel qui 1. donne un passage automatique des Conditions Initiales (C.I.) du client à l’algorithme, sans intervention humaine. C’est le procédé de paramétrisation analogue à celui bien connu des mathématiques. 2. donne un retour automatique du résultat de l’algorithme au client de la fonction 3. assure l’indépendance totale de l’algorithme. 4. donne une sérieuse assurance de résultat puisque l’auteur de la fonction a eu la responsabilité de lui faire subir toute une batterie de tests assurant la validité et l’universalité de son code. 5. bénéficie d’une excellente description à travers un système d’aide complet et standardisé. C’est encore la responsabilité de l’auteur de donner dans l’aide les spécifications d’exécution qui varient selon les valeurs données en paramètres 6. permet une réutilisation naturelle et sécuritaire de la fonction dans de nombreux projets où cet algorithme est nécessaire (et je tiens beaucoup à la métaphore de la montre, le fabricant ne conseille jamais au client de la démonter) Toute la conception moderne de qualité du logiciel, après à peine 70 ans d’existence de l’informatique, est d’abord issue de la factorisation possible du code en fonctions et aux tests systématiques qui peuvent être faits sur des parties fonctionnelles indépendantes bien identifiées et bien documentées. C’est la véritable base du développement modulaire ou objet des logiciels modernes Maintenant, on doit se rappeler des spécificités des blocs du C : Les instructions en C doivent être dans des blocs On peut faire des déclarations de variables « locales » dans tout bloc avant les instructions contenues dans ce bloc Les blocs peuvent être imbriqués « à volonté » Les blocs les plus externes – un bloc qui n’est pas dans un bloc – sont différents, ils possèdent un identificateur -- un nom -- Ce sont les fonctions qui peuvent recevoir des paramètres et structurent notre code On formalise aujourd’hui le concept de fonction avec trois règles fondamentales sur leur existence un standard obligé dans la présentation d’une fonction, le commentaire à la déclaration d’une fonction un deuxième standard, le commentaire à la définition d’une fonction le concept de variable locale à une fonction le passage par référence ( dans la partie 2) Règle #1 : l’appel d’une fonction existante par un client Dans une expression, un identificateur immédiatement suivi d’une parenthèse ouvrante indique l’appel de la fonction portant ce nom Les expressions séparées par des virgules à l’intérieur des parenthèses sont d’abord évaluées et forment les paramètres effectifs de cet appel Lors d’un appel, la fonction reçoit les valeurs des paramètres effectifs et s’exécute alors avec ces valeurs librement choisies par le client de la fonction. La fonction retourne une valeur qui prendra littéralement la place de l’appel de la fonction dans le code client. Tout ce procédé fonctionne de façon très intuitive et on considère l’appel d’une fonction comme une expression qui sera évaluée les paramètres effectifs sont les valeurs à donner aux conditions initiales (CI) de l’algorithme numérique implémenté par la fonction. Ce sont des variables libres, le client de la fonction a la possibilité de les choisir et ce choix est réalisé avec notre règle #1 le nombre de paramètres effectifs nécessaires au déclenchement d’une fonction est bien défini et invariant si la fonction n’a pas de paramètres, ce qui reste rare en programmation scientifique, l’identificateur avec des parenthèses vides déclenche son exécution Prenez bien note que l’identificateur seul d’une fonction ne déclenche pas l’exécution du code. Le nom seul d’une fonction pourra servir comme expression correcte en C dans un contexte nettement plus avancé – on verra qu’une fonction peut être passée en paramètre -- Exemples d’appel Soit une fonction nommée pgcd qui retourne le plus grand commun diviseur de deux entiers, un appel correct serait pgcd(12*15, cpt_num %14) en assumant que cpt_num est entier L’expression sin( 2.56 * pgcd(35672, 89*56)) est un appel correct du sinus offert dans la librairie classique (math.h) du C qui donnera la valeur -0.9140915941 de type double. Règle #2 : la déclaration d’une fonction ( la responsabilité de l’auteur ) Comme tout identificateur doit être déclaré avant d’être utilisé à l’intérieur d’une expression, une fonction doit être déclarée avec la syntaxe : modif_acces type identificateur(liste de paramètres formels); dont chaque élément est décrit par : modif_acces sert à limiter la disponibilité de la fonction, sa valeur se limite aux deux mots réservés (extern, static). static sert à limiter l’accessibilité de cette fonction à son unité de compilation (elle sera privée à son fichier). En absence de spécification, la valeur par défaut considérée par le compilateur est extern et l’accès du client est illimité. type indique un type connu du compilateur auquel appartient la valeur retournée par un appel correct de la fonction. Identificateur est le nom choisi pour la fonction par son auteur. Ce sera le nom d’usage normal d’un appel de la fonction par un client. On aura le même nombre de paramètres formels dans la déclaration que de paramètres effectifs dans l’appel (pour satisfaire la règle #1) Un paramètre formel, c’est la déclaration d’une variable locale à la fonction qui sera initialisée par son paramètre effectif correspondant lors d’un appel. Cette initialisation vous est gracieusement offerte par le compilateur. Si la liste de paramètres formels est vide, on l’indique avec le mot réservé void. Si la fonction ne retourne rien – ce qui reste relativement rare en C – on l’indique avec le mot réservé void. Dans la littérature plus ancienne du C, on retrouve souvent le mot prototype de fonction à la place de déclaration de fonction. Le terme prototype fait référence à l’action du compilateur qui traite l’appel d’une fonction en vérifiant la bonne compatibilité du type de chaque paramètre effectif avec le type du paramètre formel correspondant. On trouve souvent un prototype incomplet, il omet volontairement les identificateurs des paramètres formels ( qu’on ne retrouvera alors que dans la définition de la fonction). Cette variante provoque la perte d’identificateurs représentatifs et implique malheureusement une perte de qualité du code. Nous éviterons la plupart du temps cette pratique (mais pas toujours, puisqu’elle est sans danger dans les cas où le contexte d’utilisation est évident, citons double sin(double); Exemples de déclarations La déclaration de la fonction pgcd déjà vue devra donc être extern int pgcd(int n1, int n2); Et la déclaration de la fonction sinus dans math.h doit être extern double sin(double) ; Commentaires à la déclaration d’une fonction ( de la responsabilité de l’auteur ) Ce sont les commentaires les plus importants. Ils s’adressent à tout client éventuel de la fonction et lui expliquent le service offert par cette fonction comme les limites normales prévues à son utilisation Ce sont les vrais commentaires d’aide, les seuls prévus à tout client éventuel de la fonction qui lui expliquent : 1. le service offert par cette fonction 2. le sens à donner à chaque paramètre 3. les limites normales prévues à son utilisation – par exemple, pas de valeur négative donnée en paramètre au log de math.h sinon… -- Toute déclaration de fonction suit un modèle immuable dans l’institution où vous travaillez. Je vous donne ici un modèle minimal que vous devrez obligatoirement suivre pendant toute la session Ce modèle est basé sur une suite ordonnée : 1. Un séparateur seul ou possiblement avec l’identificateur de la fonction en majuscules à l’intérieur. 2. Une description succincte du but visé par cette fonction uploads/s3/ aut2015-145.pdf
Documents similaires










-
30
-
0
-
0
Licence et utilisation
Gratuit pour un usage personnel Attribution requise- Détails
- Publié le Mar 27, 2022
- Catégorie Creative Arts / Ar...
- Langue French
- Taille du fichier 0.2200MB