LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION
Transcription
LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION
LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION CHAPITRE 1 LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION OBJECTIFS ■ CARACTÉRISER LES PROBLÈMES QUI PEUVENT ÊTRE RÉSOLUS PAR ORDINATEUR, EN LES ASSOCIANT À LA NOTION D’ALGORITHME. ■ EXPOSER LES FORMALISMES DE REPRÉSENTATION ET DE CODIFICATION DES ALGORITHMES. ■ INTRODUIRE LES CONCEPTS DE BASE DE LA PROGRAMMATION ET DE L’INGÉNIERIE DES LOGICIELS, DANS UN CONTEXTE DE RÉSOLUTION DE PROBLÈMES. 1 2 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION Le rôle essentiel de l’ordinateur est de traiter de l’information. D’où le terme informatique généralement utilisé pour désigner l’ensemble des techniques permettant d’automatiser un tel traitement. L’informatique, en tant que discipline scientifique, se révèle de nos jours un outil indispensable à la résolution de problème et s’applique à des domaines aussi variés que la gestion, les calculs scientifiques, l’ingénierie, le diagnostic médical, etc. Afin de mieux saisir les limites et les possibilités des ordinateurs, nous commençons ce chapitre par les concepts de décidabilité et d’algorithme. Par la suite, nous traitons de la représentation des algorithmes, puis de la méthodologie de programmation des ordinateurs. Nous terminons par une brève incursion dans le domaine de l’ingénierie des logiciels. 1.1 DÉCIDABILITÉ ET ALGORITHME L’ordinateur est principalement utilisé pour résoudre des problèmes. Par résolution de problème, nous entendons une démarche systématique permettant, à partir d’un certain jeu de données disponibles, d’apporter une réponse au problème en question. Pour illustrer notre propos, considérons le problème de la détermination de la paye des employés d’une entreprise, ce qui correspond à la question suivante : quel montant d’argent doit être versé directement à chaque employé, pour une période donnée de travail (situation décrite)? La réponse à cette question (solution du problème) sera le résultat final de l’exécution d’une série d’étapes bien définies (démarche systématique), en utilisant des données telles que le nombre d’heures de travail pour la période, le taux horaire, le taux d’imposition, entre autres. 1.1.1 La notion d’algorithme On appelle algorithme la démarche, lorsqu’elle existe, qui permet de résoudre un problème donné, c’est-à-dire d’obtenir un résultat certain en exécutant seulement les 3 4 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI opérations indiquées dans la séquence d’énoncés ou d’instructions définissant cette démarche. Il est donc évident que l’existence d’un algorithme, considéré comme une suite d’assertions ou de propositions logiques, établit le caractère résoluble du problème en question. L’étude systématique des algorithmes en informatique est connue sous le nom d’algorithmique. Nous pourrions croire que, disposant d’un ordinateur d’une certaine puissance, nous serions en mesure de résoudre tous les problèmes qui nous seraient posés. En fait, il n’en est rien. En informatique théorique, on distingue deux grandes classes de problèmes : celle des indécidables et celle des décidables. La caractérisation de ces deux classes fait l’objet des sections qui vont suivre. 1.1.2 La notion d’indécidabilité On dit qu’un problème est indécidable lorsqu’il n’existe aucun algorithme pour le résoudre. Le concept d’indécidabilité prend ses origines dans la logique mathématique et vient infirmer une vieille croyance selon laquelle une affirmation ne peut être que vraie ou fausse. En fait, peu importe la richesse d’une axiomatique, celle-ci ne permet pas de décider de manière systématique de la vérité ou de la fausseté des propositions qui en découlent. Autrement dit, il est possible de formuler dans une axiomatique donnée une affirmation qui a du sens mais dont autant l’exactitude que l’inexactitude ne peut être démontrée. En mathématique, de telles affirmations s’appellent des conjectures. À titre d’exemple, considérons l’affirmation de Fermat selon laquelle l’équation an +bn = cn, où a, b, c et n sont des nombres entiers, n’a pas de solution si n est supérieur à 2. On peut en effet remarquer que, pour n = 2, cette équation a une solution : 32 + 42 = 52. Cependant, il n’y en a aucune pour les valeurs de n égales à 3 ou plus. En particulier, on ne connaît pas de nombres entiers a, b et c tels que a3 + b3 = c3. En d’autres termes, un cube dont le côté a une valeur entière ne peut avoir un volume égal à la somme des volumes de deux cubes de côtés entiers. Aucune preuve formelle ni contre-exemple de cette assertion n’ont été trouvés, d’où son appellation de conjecture de Fermat. LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION On peut également mentionner l’affirmation de Goldbach, selon laquelle les nombres pairs peuvent être décomposés, d’au moins une façon, en la somme de deux nombres premiers. Voyons quelques exemples. 24 = 11 + 13 50 = 7 + 43 ou 13 + 37 ou 19 + 31 60 = 3 + 57 ou 7 + 53 ou 13 + 47 ou 17 + 43 Dans ce contexte, certaines questions demeurent encore ouvertes. En effet, une telle affirmation est-elle vérifiée pour tous les nombres pairs? En outre, existe-t-il des nombres pairs très grands dont la décomposition exigerait plus de deux nombres premiers? Autant d’interrogations qui font de cette affirmation de Goldbach une conjecture. Dans le domaine de l’informatique théorique, il existe des méthodes permettant de démontrer l’indécidabilité d’un problème. Malheureusement, celles-ci font appel à des notions qui dépassent nettement le cadre de ce manuel. 1.1.3 Les problèmes décidables Dès lors qu’un problème est classé indécidable, il est hors de propos de chercher à le résoudre par ordinateur, peu importe la taille de ce dernier. Ainsi, dans le cas de la conjecture de Goldbach, les ordinateurs ont simplement permis de constater l’exactitude de l’affirmation pour des nombres nettement plus grands que ceux qui avaient été analysés auparavant par des procédés manuels. Par conséquent, les seuls problèmes que nous savons vraiment résoudre par ordinateur sont ceux dits décidables ou calculables, c’est-à-dire ceux pour lesquels il existe au moins un algorithme capable de les résoudre. Lors même qu’un problème est décidable, il est intéressant d’identifier et d’évaluer les ressources nécessaires à sa résolution. Dans un système informatique, le temps de calcul et l’espace de mémoire sont considérés comme des ressources critiques dont il faut optimiser l’utilisation; ceci nous amène à subdiviser la classe des problèmes décidables en faciles et difficiles, selon la quantité de ces ressources qu’ils requièrent pour leur résolution. L’étude de l’efficacité et de la performance des algorithmes relève du domaine de la complexité de calcul. 5 6 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI La plupart des problèmes qui font l’objet de résolution par ordinateur sont décidables et faciles : leur algorithme de résolution fait appel à peu de ressources (temps de calcul et espace de mémoire) pour leur mise en œuvre. C’est le cas du problème de détermination de la paye des employés d’une entreprise, formulé précédemment. Cependant, on retrouve de temps à autre des problèmes décidables mais difficiles; il importe de bien les identifier avant de choisir une stratégie de résolution. Le « problème du commis-voyageur » – qui consiste essentiellement à trouver dans un graphe G un chemin fermé, le plus court possible, qui passe une et une seule fois à chaque nœud du graphe – en est un exemple. Dans le cadre de ce manuel, nous abordons principalement la classe des problèmes décidables et faciles. 1.2 LA REPRÉSENTATION DES ALGORITHMES Pour décrire un algorithme comme une démarche de résolution d’un problème, on utilise souvent un organigramme, sorte de représentation graphique qui permet de mieux visualiser cette démarche. Un organigramme est construit à partir d’un formalisme comprenant cinq symboles simples : l’indicateur de début et de fin, la boîte de traitement, la boîte de décision, la boîte d’interaction et le cercle de jonction; la figure 1.1 les illustre. Indicateur de début et de fin Boîte de traitement Boîte de décision Boîte d’interaction Cercle de jonction FIGURE 1.1 SYMBOLES DE BASE UTILISÉS DANS LES ORGANIGRAMMES. Un algorithme peut également être représenté par un pseudo-langage constitué de mots et de règles syntaxiques conduisant à une forme standardisée appelée pseudo-code. Dans le cadre de ce manuel, nous limitons notre vocabulaire à un ensemble de termes français et nos règles syntaxiques à quelques éléments de syntaxe du langage PASCAL. LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION Exemple 1.1 Lire un tableau contenant un nombre N de valeurs et les imprimer à l’écran est un problème évidemment décidable. De plus, il est facile, puisque sa résolution requiert peu d’espace de mémoire et peu d’opérations de base (lecture et affichage). L’algorithme de résolution peut se définir par le pseudo-code dont les étapes sont : 1. Lire une valeur du tableau. 2. Imprimer la valeur lue. 3. Si le tableau n’est pas vide, alors lire la valeur suivante du tableau et retourner à l’étape 2. Sinon, Arrêt. La figure 1.2 représente l’organigramme de résolution du problème posé dans l’exemple 1.1. DÉBUT Lire NON Imprimer Tableau vide? OUI FIN FIGURE 1.2 ORGANIGRAMME DU PROBLÈME POSÉ DANS L’EXEMPLE 1.1. 7 8 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI 1.2.1 La description des algorithmes Un algorithme est composé d’une série d’instructions qui font généralement appel à des opérateurs. Il existe trois types d’instructions : – Les instructions inconditionnelles indiquant une ou plusieurs opérations à effectuer à une étape donnée de la recherche de solution (exemple : Lire la première valeur du tableau). Dans cette catégorie, se trouvent les instructions d’affectation qui, comme leur nom l’indique, permettent d’affecter une valeur à une variable ou à une adresse de mémoire. – Les instructions conditionnelles ou logiques dont le format est le suivant : Si cela se produit, alors faire telle chose Sinon, faire autre chose. On les appelle aussi des sélections. Il existe deux types de sélection : la sélection simple et la sélection multiple. Contrairement à la sélection simple qui met en cause au plus deux possibilités, la sélection multiple met en jeu plus de deux possibilités. Voici un exemple. Si Total supérieur ou égal à 90, alors Note = A Sinon si Total supérieur ou égal à 80, alors Note B Sinon si Total supérieur ou égal à 70, alors Note = C Sinon si Total supérieur ou égal à 60, alors Note = D Sinon Note = E – Les instructions itératives ou boucles, dont l’un des formats est le suivant : Tant que telle condition n’est pas réalisée, exécuter telle action ou suite d’actions. Ces dernières peuvent être considérées comme une catégorie particulière d’instructions conditionnelles. LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION Il existe deux types d’opérations de base généralement utilisées dans la description des algorithmes : – Les opérations arithmétiques élémentaires telles l’addition, la soustraction, la multiplication et la division. – Les opérations logiques qui permettent d’exécuter les instructions conditionnelles mettant en jeu des opérateurs de comparaison et des connecteurs logiques. Toute opération logique donne lieu à un résultat binaire (vrai ou faux). Les opérateurs de comparaison ou de relation sont : égal à (A = B), inférieur à (A < B), inférieur ou égal à (A ≤ B), supérieur à (A > B), et supérieur ou égal à (A ≥ B). Les connecteurs logiques sont : la disjonction (A ou B), la conjonction (A et B) et la négation (non A). 1.2.2 La codification des algorithmes La notion de programme, résultat de la codification d’un algorithme, est bien plus vieille que l’informatique. En effet, on utilise depuis longtemps déjà en recherche opérationnelle les termes programme linéaire et programme non linéaire pour désigner certaines classes de problèmes d’optimisation; ce qui est quelque peu différent de la notion de programme fort courante en informatique. On désigne par programme d’ordinateur ou programme informatique, ou tout simplement programme, une séquence d’énoncés ou d’instructions, conformes à un langage de programmation donnée, dont l’exécution conduit à la solution d’un problème. Ainsi, lorsqu’on veut résoudre un problème, la première démarche consiste à s’assurer de la décidabilité de ce dernier. S’il s’agit d’un problème décidable, il importe alors de se poser la question : est-il facile ou difficile? C’est seulement lorsqu’on aura la réponse à cette question que l’on peut entreprendre de concevoir un algorithme de résolution, puis le programme d’ordinateur correspondant, selon une méthodologie qui fait l’objet de la prochaine section. 9 10 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI 1.3 LA MÉTHODOLOGIE DE PROGRAMMATION Comme on l’a vu précédemment, le concept de programme est intimement lié à la notion de résolution de problème. En effet, pour résoudre un problème donné par ordinateur, il importe préalablement de spécifier et d’analyser ce problème. Dans ce contexte, la programmation apparaît comme une étape d’un processus plus complexe débouchant sur la solution d’un problème, la spécification étant la première étape de ce processus. 1.3.1 La spécification d’un problème Spécifier un problème, c’est déterminer un ensemble de données et de contraintes dont on doit tenir compte, afin d’atteindre un objectif qui n’est autre que la solution du problème posé. Par exemple, si on désire préparer la paye des employés d’une entreprise, les spécifications d’un tel problème correspondent à indiquer : – les données nécessaires à la réalisation de cette tâche, c’est-à-dire, pour chaque employé, le nom, le nombre d’heures de travail fourni, leur taux horaire, le nombre de personnes à charge; – les contraintes, qui peuvent porter sur la présentation des résultats ou sur la façon de traiter les heures supplémentaires; – l’objectif, qui est de pouvoir fournir dans un certain format les relevés de paye pour l’entreprise. D’une manière générale, on peut distinguer deux types de problèmes : – ceux qui sont bien formalisés et qui proviennent généralement du champ des sciences exactes et appliquées, comme la résolution d’une équation du second degré ou la multiplication de deux matrices; – ceux qui sont moins formalisés et qui prennent pour la plupart leur origine dans la gestion des organisations. C’est en se basant sur une telle classification que l’on est venu à diviser l’informatique en informatique scientifique et informatique de gestion. La première aborde générale- LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION ment des problèmes bien formalisés, pour lesquels une démarche de spécification ne constitue qu’une étape accessoire. La deuxième, par contre, aborde essentiellement des problèmes de gestion, qui sont pour la plupart peu formalisés et qui nécessitent par conséquent un effort considérable de spécification. Dans la vie d’une organisation, il peut surgir des anomalies de fonctionnement qui conduisent à l’identification de problèmes. Il convient alors de définir celles-ci dans les moindres détails, de manière à bien spécifier le problème. Car, si on ne connaît pas la nature exacte d’un problème, il sera impossible de le résoudre convenablement. 1.3.2 L’analyse d’un problème L’analyse est une étape importante dans le processus de résolution de problème. On distingue deux niveaux d’analyse : l’analyse fonctionnelle et l’analyse organique. L’analyse fonctionnelle consiste à décomposer le problème spécifié en différentes étapes qui conduisent à des résultats conformes à l’objectif fixé. Chacune de ces étapes peut constituer un module, d’où le concept de programmation modulaire. Comme son nom l’indique, l’analyse fonctionnelle est une démarche qui vise à déterminer l’enchaînement logique des fonctions dont l’exécution fournira la solution du problème. Elle répond à la question : quoi faire pour résoudre le problème? La stratégie la plus répandue pour décomposer un problème demeure l’approche descendante. Elle consiste à décomposer progressivement le problème à traiter en sousproblèmes plus simples à résoudre, comme l’illustre l’exemple 1.2. Ainsi s’établit une hiérarchie entre les différents niveaux de sous-problème et le problème initial; d’où le concept de diagramme hiérarchique schématisant la phase finale de ce processus de décomposition. La figure 1.3 présente une version intermédiaire (non finale) du diagramme hiérarchique correspondant au problème de préparation de la paye. Si on prolonge le processus de décomposition par un raffinement plus poussé des niveaux de la figure 1.3, on aboutit alors à un diagramme hiérarchique plus complet donnant la solution finale du problème. La figure 1.4 en est l’illustration. 11 12 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI 000 Préparer paye 100 Payer un employé 110 Vérifier données 200 Imprimer sommaire 120 Vérifier salaire brut 130 Calculer paye normale FIGURE 1.3 DIAGRAMME HIÉRARCHIQUE INTERMÉDIAIRE DU PROBLÈME DE PRÉPARATION DE LA PAYE. 000 Préparer paye 100 Lire données d’un employé 200 Payer un employé 210 Vérifier données 230 Vérifier salaire brut 220 Imprimer ligne 300 Imprimer sommaire 250 Calculer paye normale 310 (220) Imprimer ligne 240 (100) Lire données d’un employé FIGURE 1.4 DIAGRAMME HIÉRARCHIQUE FINAL DU PROBLÈME DE PRÉPARATION DE PAYE. Le processus de raffinement progressif s’arrête lorsque les derniers modules obtenus ne peuvent plus être décomposés en modules plus petits. On doit surtout garder en tête, lors de chacune de ces décompositions, l’objectif que l’on veut atteindre ou le problème LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION que l’on cherche à résoudre. Ceci permet d’éviter la création d’étapes inutiles ou n’ayant aucun rapport avec le problème en question. L’approche descendante, schématisée par le diagramme hiérarchique, présente un certain nombre d’avantages intéressants. En effet, le but poursuivi est nettement mis en évidence : il correspond en général au nom du premier module du diagramme hiérarchique. De plus, chaque étape de la recherche de solution est clairement spécifiée, ce qui permet de la modifier facilement pour pouvoir tenir compte de contraintes additionnelles qu’on pourrait ajouter au problème ou utiliser dans la résolution de problèmes similaires. Notons qu’un diagramme hiérarchique n’est pas un algorithme et diffère conséquemment d’un organigramme. Cependant, on peut facilement, à partir des cases terminales du diagramme hiérarchique, construire l’algorithme de résolution du problème. Le passage du diagramme hiérarchique à l’algorithme relève de l’analyse organique. Celle-ci part de l’analyse fonctionnelle et de la réponse fournie à la question du « quoi faire » pour traiter la question du « comment faire ». Cette analyse est orientée vers la programmation et peut s’étendre jusqu’à la définition des structures de données à utiliser. Exemple 1.2 Considérons maintenant le problème qui consiste à évaluer le nombre de filles dans une école secondaire. Selon l’approche descendante, la décomposition du problème donnerait : 1. Déterminer le nombre de filles dans une école secondaire. L’étape (ou module) 1 peut être décomposée en quatre autres étapes élémentaires, soit : 1.1 Choisir une école secondaire. 1.2 Évaluer le nombre de niveaux différents dans cette école (secondaire 1 jusqu’à 5). 1.3 Évaluer le nombre de filles par niveau. 1.4 Évaluer le nombre total de filles pour l’ensemble des niveaux. 13 14 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI La figure 1.5 présente le diagramme hiérarchique correspondant à cette décomposition. L’étape 1.3 peut à son tour être décomposée de la façon suivante : 1.3.1 Évaluer le nombre de classes C pour le niveau courant. 1.3.2 Initialiser classe à 1. 1.3.3 Tant que le nombre de classes C n’est pas atteint : · évaluer le nombre de filles F dans la classe courante; · ajouter F au nombre de filles dans le niveau courant; · augmenter classe de 1. D’où la version finale du diagramme hiérarchique représentée à la figure 1.6. 000 Déterminer nombre de filles 100 Choisir école 200 Évaluer nombre de niveaux 300 Évaluer nombre de filles par niveau 400 Évaluer nombre total de filles FIGURE 1.5 DIAGRAMME HIÉRARCHIQUE INTERMÉDIAIRE DU PROBLÈME DE L’EXEMPLE 1.2. La solution algorithmique correspondant au diagramme hiérarchique de la figure 1.6 est définie par les étapes suivantes : 1. Choisir une école. 2. Évaluer le nombre de niveaux différents N dans cette école. 3. Tant que le nombre de niveaux N n’est pas atteint : – évaluer le nombre de classes C pour le niveau courant; – tant que le nombre de classes pour le niveau courant n’est pas atteint : · évaluer le nombre de filles F pour la classe courante, · augmenter de F le nombre de filles dans le niveau courant, · augmenter classe de 1; – augmenter niveau de 1. 4. Additionner le nombre de filles des divers niveaux. LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION 000 Déterminer nombre de filles 100 Choisir école 200 Évaluer nombre de niveaux 300 Évaluer nombre de filles par niveau 400 Évaluer nombre total de filles 310 Évaluer nombre de classes niveau courant 320 Initialiser classe 330 Évaluer nombre de filles dans classe courante FIGURE 1.6 DIAGRAMME HIÉRARCHIQUE FINAL DU PROBLÈME DE L’EXEMPLE 1.2. La figure 1.7 représente l’organigramme de la solution du problème qui consiste à déterminer le nombre de filles qu’il y a dans une école secondaire. Il existe également une approche ascendante pour décomposer les problèmes. Elle consiste à déterminer, puis à intégrer progressivement tous les éléments qui entrent dans la solution du problème à traiter. Toutefois, l’approche ascendante n’est véritablement applicable qu’à certaines classes de problèmes; on l’utilise surtout lors de la conception de logiciels, pour tester si les divers modules sont fonctionnels ou correspondent aux spécifications préétablies. 1.3.3 La phase de programmation La programmation constitue une phase critique dans le processus de résolution de problème, à partir de l’ordinateur. En effet, l’analyse du problème une fois terminée, un algorithme de résolution est disponible. Il convient alors de coder ce dernier dans un langage de programmation, avant de le soumettre à un traducteur qui, comme son nom l’indique, traduit le programme source reçu en code objet ou binaire. Le traducteur peut être un assembleur ou un compilateur, selon que le programme source est écrit en langage symbolique dit d’assemblage ou en langage évolué, sur lesquels nous reviendrons plus loin. C’est le code objet ainsi produit qui est exécuté par l’ordinateur. 15 16 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI DÉBUT Choisir école Évaluer nombre de niveaux N OUI Nombre de niveaux N atteint? NON Évaluer nombre de classes C du niveau OUI Nombre C atteint? NON Évaluer F Augmenter de F Augmenter classe Augmenter niveau Obtenir nombre total de filles FIN FIGURE 1.7 ORGANIGRAMME DU PROBLÈME DE L’EXEMPLE 1.2 SELON L’APPROCHE DESCENDANTE. LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION Il existe plusieurs modes de programmation. Outre la programmation orientée objet qui sera abordée au prochain chapitre, on peut citer la programmation séquentielle, la programmation parallèle ou concurrente, et la programmation heuristique. La programmation séquentielle La programmation séquentielle est le mode le plus répandu. En effet, les notions d’algorithme et d’organigramme que l’on a introduites précédemment s’inspirent de la « séquentialité » des opérations ou étapes conduisant à la solution d’un problème. Le codage de ces algorithmes ne peut donner lieu qu’à des programmes séquentiels, dans lesquels les instructions sont nécessairement exécutées l’une après l’autre, donc une à la fois. Un tel mode de fonctionnement est intimement lié à l’architecture courante des ordinateurs, communément appelée architecture de von Neumann. Bien que la démarche séquentielle soit la plus explicite pour résoudre, par programmation, la plupart des problèmes, elle reste néanmoins inefficace dans certains cas, comme on peut le constater dans l’exemple 1.3. Exemple 1.3 Pierre fabrique des porte-clés. Dans son atelier, outre ses outils et matériaux de travail, il a un téléphone (les clients peuvent appeler pour une commande) et un guichet où il remet les porte-clés et reçoit directement les commandes des clients. En planifiant son travail, Pierre peut décider de s’y prendre ainsi : 1. 2. 3. 4. Attendre une commande. Exécuter la commande suivant la description du client. Livrer le produit fini. Recommencer à l’étape 1. Cette façon de faire correspond à une programmation séquentielle de son travail. On se rend compte, cependant, que son procédé est inefficace parce qu’il peut faire perdre un certain nombre de commandes, étant donné qu’il ne répond pas au téléphone ou au guichet pendant qu’il travaille. De plus, certains clients peuvent s’impatienter en attendant qu’on leur livre leur commande, et lui-même, Pierre, perd du temps à attendre, une fois qu’il a remis son dernier porte-clés, qu’une nouvelle commande arrive. Il lui est 17 18 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI donc nécessaire d’introduire dans sa planification la notion d’interruption. Ce faisant, on tombe dans le domaine de la programmation parallèle. La programmation parallèle En programmation parallèle, qui entraîne une organisation différente du travail, on décomposerait le problème précédent en trois sous-problèmes. La solution de chacun porterait alors le nom de processus; et l’exécution de ces trois processus conduirait à la solution du problème de gestion d’un atelier de fabrication de porte-clés. Le premier processus consiste à prendre les commandes à partir du téléphone ou du guichet et à l’inscrire au carnet. Le second consiste à exécuter les commandes dans l’ordre où elles ont été inscrites dans le carnet et à les placer sur l’étagère. Le dernier processus est la remise du porte-clés au client par le guichet et l’enlèvement du nom de celui-ci du carnet. Chaque interruption fait exécuter un et un seul processus à la fois. Si le processus d’inscription des commandes dans le carnet est en train de s’exécuter (parce qu’il y a un client au téléphone) et qu’une personne arrive au guichet pour une commande, ce processus ne devrait pas s’arrêter. Car, cette prise de commande risque de conduire à une incohérence des informations inscrites dans le carnet : il s’agit là d’un problème d’exclusion mutuelle. Par ailleurs, le processus qui gère l’exécution des commandes devrait s’arrêter s’il n’y a plus de commande. De même, celui qui s’occupe de remettre au client sa commande ne devrait pas s’activer si la commande du client n’est pas prête. On parle alors de problème de synchronisation. Dans ce contexte, Pierre procéderait ainsi : – Il dispose d’un carnet où il note toutes les commandes des clients, ainsi que leur nom. – Il commence par exécuter la commande la plus ancienne dans son carnet et, lorsqu’il a terminé, range le porte-clés sur un étagère. – Si le téléphone sonne, Pierre interrompt son travail pour répondre, note la nouvelle commande dans son carnet s’il y a lieu, raccroche et reprend son travail. LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION – Si un client se présente au guichet, il arrête et demande au client s’il s’agit d’une commande, auquel cas il la note dans son carnet, sinon il remet au client le porteclés identifié à son nom et recommence son travail. Ainsi, Pierre ne perd guère son temps. En outre, les clients ne s’impatientent plus puisque les commandes sont prises au fur et à mesure qu’elles se présentent. La programmation parallèle est un outil puissant pour résoudre les problèmes complexes de gestion des périphériques d’entrée-sortie. Toutefois, son utilisation reste tributaire des langages de programmation supportant intrinsèquement la concurrence. Les langages ADA et MODULA-2 en sont des exemples. La programmation heuristique Tout ce que nous avons écrit jusqu’à maintenant sur la programmation ne touchait que les problèmes décidables et faciles, pour lesquels il existe au moins un algorithme de résolution. Qu’en est-il des problèmes décidables mais difficiles? Pour de tels problèmes, il est hors de propos de chercher une solution exacte, qui solliciterait une trop grande quantité de ressources informatiques (espace de mémoire et temps de calcul). La seule stratégie recommandée consiste à utiliser des méthodes informelles non garanties quant au succès, qualifiées d’heuristiques. La particularité d’une telle approche réside dans le fait qu’elle permet des retours en arrière lorsque le chemin initialement retenu ne conduit pas rapidement à la solution. Les programmes jouant aux échecs utilisent l’approche heuristique. En effet, on ne connaît, à l’heure actuelle, aucune méthode indiquant le meilleur coup à jouer dans chaque situation, un examen exhaustif de toutes les possibilités étant irréaliste. Dans ce contexte, l’approche heuristique fournira une méthode de résolution basée non pas sur la recherche systématique du meilleur coup, mais plutôt sur l’obtention du meilleur résultat qui peut être trouvé assez rapidement. 1.4 L’INGÉNIERIE DES LOGICIELS On appelle ingénierie des logiciels ou génie logiciel un ensemble de techniques qui permettent de concevoir des programmes de qualité et de gérer efficacement tout le cycle de vie des logiciels. Ce dernier regroupe l’ensemble des activités liées à la 19 20 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI spécification, à la conception, à l’implantation, à la mise au point, à la documentation et à la maintenance des programmes ou logiciels. Dans le cadre de vastes projets, comme la conception d’un compilateur ou d’un système d’exploitation, de telles techniques sont d’une grande utilité. 1.4.1 Les caractéristiques d’un bon logiciel De nos jours, les logiciels d’une certaine taille ne sont plus conçus par un seul individu mais plutôt par une équipe composée de programmeurs, d’analystes, de gestionnaires et de chercheurs travaillant tous en interaction. Leur souci commun est de produire de bons logiciels, ce qui nous amène à énoncer les qualités d’un bon logiciel : – satisfaire à toutes les spécifications qui le concernent, en accomplissant toutes les tâches auxquelles il est destiné et en donnant des résultats exacts; – être fiable et robuste, c’est-à-dire exempt d’erreurs; – utiliser efficacement les ressources de l’ordinateur en réduisant au minimum l’espace de mémoire et le temps de calcul; – pouvoir être modifié facilement pour répondre aux nouveaux besoins des utilisateurs ou s’adapter à un nouvel environnement; – être facile à maintenir, ce qui exige une approche de conception à la fois structurée et modulaire; – être conforme à l’échéancier et au budget fixés pour son développement. Les règles de conception des logiciels varient en fonction des applications visées. Il reste néanmoins un certain nombre de principes de base qui peuvent aider les concepteurs à développer un produit de qualité. 1.4.2 Le cycle de vie des logiciels Un logiciel dont le but est d’informatiser une tâche quelconque n’est pas une création spontanée : il se conçoit, se développe, se modifie. Pour illustrer la démarche, examinons un exemple. LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION Exemple 1.4 Supposons que Jacques, président-directeur général d’une petite entreprise, désire informatiser sa section de comptabilité et désigne Pierre pour le faire. Pierre, le responsable du projet, et Jacques, le directeur de l’entreprise, voudraient définir ce projet d’informatisation de la section de comptabilité, en décrivant de façon plus précise les tâches ou le travail humain qu’ils veulent informatiser. Pour ce faire, ils auraient besoin de l’aide du comptable en chef pour mieux spécifier le projet. La spécification La définition ou spécification d’un projet consiste à décrire globalement ce qu’on voudrait que l’ordinateur réalise; elle ne requiert en fait aucune connaissance en informatique. Dans ce contexte, Jacques, Pierre et Luc, le comptable en chef, peuvent décider d’informatiser les comptes clients, les dépenses, les comptes à recevoir et les comptes à payer. Ils peuvent aussi désirer obtenir le bilan de l’entreprise pour l’année précédente, par exemple; tout est fonction de leurs besoins. La conception La phase de conception renvoie à l’étape d’analyse que nous avons définie antérieurement. Elle comprend une analyse fonctionnelle et une analyse organique. C’est dans cette phase qu’on précise ce qu’on soumet à l’ordinateur comme information et ce que celui-ci doit transmettre comme résultat, ce qui amène souvent à : – – – – modifier ou limiter les tâches définies initialement; fixer un seuil d’erreur acceptable; déduire les contraintes et limites du projet; identifier les éléments dont on aurait besoin (type d’ordinateur, périphériques d’entrée-sortie nécessaires). Pour la toute petite entreprise de Jacques, un simple ordinateur muni d’un disque dur suffirait, avec comme entrée le clavier et comme sortie un écran et une imprimante. Comme limite du projet, Luc, le comptable en chef, peut accepter de ne pas pouvoir 21 22 INTRODUCTION À LA PROGRAMMATION EN PASCAL/DELPHI demander à l’ordinateur le bilan de l’entreprise pour les dix dernières années, parce que conserver toutes ces informations prendrait trop de place sur le disque. C’est aussi au cours de la phase d’analyse que l’on évalue la « portabilité » du logiciel, c’est-à-dire la possibilité qu’il puisse être installé sur d’autres systèmes informatiques, ainsi que le coût, la durée du projet et le personnel nécessaire. Le résultat ou produit de cette phase est un algorithme détaillé. La phase de conception d’un logiciel n’est jamais vraiment terminée. Car, tout au long de son développement et pendant sa durée de vie, de nouvelles contraintes ou de nouveaux besoins viennent modifier la structure des fonctions initialement décrites. L’implantation et la mise au point Un ordinateur ne résout pas de problèmes, il exécute les opérations menant à la solution préalablement élaborée par une personne. Il revient donc à ceux qui sont en charge du projet de rechercher la solution (algorithme) de chaque tâche que l’on veut informatiser et d’instruire la machine de la démarche à suivre : c’est ce qu’on appelle l’implantation. Plus précisément, cette phase consiste à traduire dans un langage de programmation l’algorithme issu de l’analyse organique. Une fois l’algorithme implanté, il devient un programme qui se doit d’être testé et validé. Le test consiste alors à s’assurer que le programme ne contienne pas d’erreurs, tandis que la validation consiste à en vérifier le bon fonctionnement à partir des données soumises et des résultats obtenus. Ces deux opérations contribuent conjointement à la mise au point du logiciel. La phase de mise au point est une des plus coûteuses et des plus fastidieuses du cycle de vie du logiciel. Sa réussite dépend à la fois de la qualité de la phase de conception et de l’habileté des programmeurs qui ont à la réaliser. De plus, elle détermine la qualité globale du logiciel, dans la mesure où elle sert à identifier et à corriger les erreurs que contient le programme en développement. LA RÉSOLUTION DE PROBLÈME ET LA PROGRAMMATION La documentation Une fois le programme testé et déclaré capable de produire des résultats valides conformément aux spécifications, il est opportun de le documenter. En effet, même si cela peut sembler fastidieux, il demeure utile d’ajouter aux lignes de code des commentaires appropriés et de choisir des noms significatifs pour les variables; c’est une façon d’accroître la lisibilité du programme. La documentation comprend également la rédaction d’un guide d’utilisation et d’un guide technique. Le guide d’utilisation, comme son nom l’indique, doit fournir toutes les informations relatives au programme et à son contexte d’utilisation. Un tel document doit être rédigé d’une manière compréhensible et dans un langage accessible à des utilisateurs qui ne sont pas nécessairement rompus à la science informatique. Le guide technique, quant à lui, est un document qui exige une plus grande précision et qui s’adresse plutôt à des programmeurs. Il doit indiquer d’une manière détaillée le fonctionnement du programme pour faciliter les éventuelles modifications de ce dernier par des personnes autres que les concepteurs initiaux, lors de la phase de maintenance. La maintenance De nouvelles contraintes, des erreurs, de nouveaux besoins peuvent amener le programmeur, ou quelqu’un d’autre, à effectuer certains changements dans la version actuelle du logiciel; c’est ce que l’on appelle la maintenance du logiciel. Pour que cela puisse se faire aisément, il faut que le programme soit lisible, compréhensible, bien documenté. Un programme bien documenté, découlant d’une approche de programmation modulaire, est nécessairement facile de maintenance. 23