4.1 Modèles de calcul
Objectifs d'apprentissage
À la fin de cette section, vous serez capable de :
- Définir les langages de programmation de bas niveau, y compris le langage d'assemblage
- Définir les langages de programmation de niveau intermédiaire et de haut niveau, tels que C et JavaScript
- Comparer et opposer les différents paradigmes de programmation
Les algorithmes sont utilisés pour résoudre des problèmes de calcul et créer des modèles de calcul. Un modèle de calcul (computational model) est un système qui définit ce qu'un algorithme fait et comment l'exécuter. Des exemples de tels modèles de calcul incluent des dispositifs physiques capables d'exécuter des logiciels, des langages de programmation ou une spécification de conception de ceux-ci. Un langage de programmation est une application linguistique d'un algorithme, qui utilise des modèles de calcul axés sur la définition de notations pour l'écriture de code.
De nombreux modèles de calcul ont été conçus pour une multitude d'autres applications. Il existe de nombreux rôles et perspectives différents dans les mondes de l'informatique et du développement de logiciels. L'objectif final du développement de logiciels est de créer des logiciels fonctionnels qui peuvent s'exécuter sur un modèle matériel (hardware model), qui lui-même utilise une réalisation (matérielle) d'un algorithme permettant à des ordinateurs physiques spécifiques d'exécuter des programmes logiciels. Un modèle matériel est conçu pour la commodité d'une machine, et non pour un auteur de logiciel humain, de sorte que les modèles matériels sont mal adaptés à l'écriture de code. Les informaticiens ont créé des langages de programmation qui sont conçus spécifiquement pour que les programmeurs développent des applications pratiques. Ces langages sont généralement classés en langages de haut niveau et de bas niveau. Un langage de programmation de haut niveau (high-level programming language) opère à un niveau d'abstraction élevé, ce qui signifie que les détails de bas niveau tels que la gestion de la mémoire sont automatisés. En revanche, un langage de programmation de bas niveau (low-level programming language) opère à un faible niveau d'abstraction. Des langages comme C et C++ peuvent effectuer des tâches de haut niveau et de bas niveau.
La plupart des logiciels sont conçus, écrits et discutés en termes de la manière dont un programme devrait fonctionner. Il s'agit essentiellement d'une série d'étapes qui indiquent comment le programme doit être exécuté. Un exemple serait le « modèle Map Reduce » qui est utilisé dans des systèmes distribués comme le moteur de recherche Google pour produire des résultats de recherche pour de grands ensembles de données à l'aide d'un algorithme complexe. S'éloignant encore plus des modèles matériels, les informaticiens ont également défini un modèle abstrait (abstract model), qui est une technique dérivant des modèles conceptuels de haut niveau plus simples pour un ordinateur tout en explorant la science de ce que les nouveaux algorithmes peuvent ou ne peuvent pas faire.
Les ordinateurs modernes sont équipés d'un processeur central, appelé unité centrale de traitement (CPU) (central processing unit (CPU)), qui est une puce informatique capable d'exécuter des programmes. Le modèle matériel d'un CPU repose sur une architecture de jeu d'instructions (ISA) (instruction set architecture (ISA)) spécifique au CPU qui définit une liste d'opérations que le CPU peut exécuter, telles que le stockage des résultats de calculs (Figure 4.2). Avec les avancées technologiques, les ingénieurs en informatique ont conçu des architectures d'ordinateurs avec une sophistication et une puissance croissantes. Des exemples de modèles matériels incluent l'architecture MOS Technology 6502 utilisée par la Nintendo Entertainment System, l'architecture ARM utilisée par les téléphones mobiles, et les architectures x86-64 et AMD64 utilisées par les ordinateurs personnels modernes. Les ingénieurs en informatique conçoivent des architectures en tenant compte des spécifications matérielles, telles que la vitesse d'exécution ou la consommation d'énergie. Par conséquent, les modèles matériels ne sont pas adaptés à l'utilisation par les humains pour la communication d'algorithmes.
Un modèle de programmation (programming model) est conçu pour être lu et écrit par des humains. Un modèle de programmation axé sur la définition d'une notation pour l'écriture de code peut également être appelé un langage de programmation. Un modèle de programmation peut être utilisé pour implémenter un algorithme logiciel en utilisant un ensemble strict de règles syntaxiques. La syntaxe d'un langage peut définir des mots-clés tels que « if ». La syntaxe peut inclure un opérateur (operator) mathématique, une opération de programmation fondamentale qui combine des valeurs, comme « + ». La syntaxe peut définir la ponctuation telle que « ; ». Essentiellement, la syntaxe donne la signification précise de ce que chacun de ces éléments ordonne à un ordinateur de faire. Le texte d'un programme écrit dans un langage de programmation est appelé code source (source code). Les ingénieurs logiciels ont créé pratiquement tous les logiciels en écrivant du code source dans divers langages de programmation. Puisqu'un modèle de programmation ne peut pas exécuter directement un programme, un compilateur (compiler) ou un interpréteur (interpreter) doit traduire le code source d'un langage de niveau intermédiaire ou de haut niveau en quelque chose qu'un ordinateur peut exécuter.
Comme mentionné, les modèles abstraits sont des modèles de calcul utilisés pour penser aux algorithmes de manière abstraite, plutôt que pour créer et exécuter des logiciels. L'objectif d'un modèle abstrait est de faciliter la conception et la transmission d'algorithmes par les personnes. Les informaticiens utilisent des modèles abstraits pour créer de nouveaux algorithmes, analyser l'efficacité des algorithmes et prouver des faits sur ce que les algorithmes peuvent ou ne peuvent pas faire. Un modèle abstrait ne se soucie pas des détails des architectures informatiques, ce qui facilite la concentration sur ce genre de questions profondes. Des exemples de modèles abstraits incluent la machine à accès aléatoire, la machine de Turing et le calcul lambda. La machine à accès aléatoire (Random Access Machine) (Figure 4.3) est un CPU qui se compose de cellules de mémoire illimitées pouvant stocker n'importe quelle valeur arbitraire. Tout comme n'importe quel autre CPU, le PC détermine l'instruction à exécuter ensuite. Une machine à accès aléatoire peut être utilisée pour analyser l'efficacité des algorithmes. Une machine de Turing (Figure 4.4) est un modèle mathématique qui peut implémenter n'importe quel algorithme. Le calcul lambda (Lambda calculus) est un concept de calcul théorique utilisant des fonctions lambda. Il a été défini par Alonzo Church et a inspiré le paradigme de programmation fonctionnelle, que vous étudierez plus en détail dans Paradigmes de langages de programmation.
Une fonction définit comment convertir une entrée en une sortie, et la programmation fonctionnelle (functional programming) est un paradigme dans lequel les algorithmes sont écrits comme des fonctions mathématiques. Un exemple de paradigme de programmation fonctionnelle est la récursivité, où une fonction est utilisée pour s'appeler elle-même. La factorielle d'un entier peut être calculée à l'aide d'une fonction récursive.
import java.util.*;
public class Recursion {
public static int Factorial_Recursion(int Val){
if(Val==0){
return 1;
}
else
return Val*Factorial_Recursion(Val-1);
}
public static void main(String[] args){
Scanner s =new Scanner(System.in);
System.out.println("Enter an input value: ");
int Val=s.nextInt();
System.out.println("The factorial of " + Val + " is: " + Factorial_Recursion(Val));
}
}
Un algorithme décrit dans un modèle abstrait ne peut pas être exécuté directement. Premièrement, un développeur de logiciels doit implémenter l'algorithme, ce qui signifie traduire l'algorithme abstrait en code source dans un langage de programmation.
Il peut être surprenant qu'il puisse exister autant de modèles de programmation différents, et que les algorithmes puissent être traduits d'un modèle à l'autre. Cependant, cette traduction est intentionnelle ; l'informatique a établi la thèse de Church-Turing (Church-Turing Thesis), qui est une théorie scientifique affirmant qu'un algorithme peut être converti d'un modèle de calcul (computational model) raisonnable à un autre. La thèse de Church-Turing offre une perspective à travers laquelle les informaticiens peuvent inventer de nombreuses architectures d'ordinateurs et langages de programmation, tous capables d'exécuter des algorithmes.
Les informaticiens ont créé une terminologie pour comprendre les similitudes et les différences entre tous ces langages de programmation. Par exemple, tout langage de programmation peut être de bas niveau ou de haut niveau, ou se situer n'importe où sur le spectre.
Programmation de bas niveau
Le niveau d'abstraction (level of abstraction) d'un langage de programmation est le degré auquel un modèle de calcul, un langage de programmation (programming language) ou un logiciel se rapporte au matériel informatique. Un langage de bas niveau a un faible niveau d'abstraction, tandis qu'un langage de haut niveau a un niveau d'abstraction élevé. Dans un langage de bas niveau, le programmeur doit décrire un algorithme en termes que le matériel informatique peut comprendre directement. Le code source doit décrire des détails tels que l'emplacement des données en mémoire et les particularités de la façon dont l'ordinateur calcule l'arithmétique.
Généralement, les programmes de bas niveau s'exécutent plus rapidement mais sont plus exigeants en main-d'œuvre pour être créés et maintenus. Dans un langage de bas niveau, le programmeur est contraint de réfléchir délibérément à la manière dont le matériel informatique exécute, de sorte que le programme fini s'exécute généralement efficacement. Cependant, cette réflexion délibérée prend du temps et des efforts. Dans un langage de haut niveau, le programmeur n'est pas accablé par la pensée de tant de détails et peut terminer son travail plus rapidement tout en évitant certains types d'erreurs de programmation. Un compilateur automatise la conversion du code de haut niveau en code de bas niveau, mais ce processus automatisé peut introduire une certaine inefficacité. Dans certains contextes, la performance du code est plus importante, et dans d'autres, la productivité du programmeur est plus importante, c'est pourquoi nous avons les deux types de langages.
Nous pouvons considérer les langages de programmation de bas niveau en termes de cuisine : lorsque vous préparez un repas à partir de zéro, vous contrôlez chaque ingrédient et chaque détail de la préparation, de sorte que le repas fini a précisément le goût et la nutrition que vous désirez. Une alternative est de préparer un repas qui utilise des ingrédients préparés, et lorsque vous faites cela, vous perdez beaucoup de contrôle sur les détails, mais le processus est significativement plus rapide et plus facile.
Il existe de nombreux exemples de langages de programmation de bas niveau, mais le langage le plus fondamental compris par les ordinateurs est composé d'une séquence de chiffres.
Code machine
La séquence de chiffres binaires qui peut être comprise et exécutée directement par un ordinateur est appelée code machine (machine code) (Figure 4.5). Le code machine est le langage le plus bas niveau. Il est également connu sous le nom de code binaire (binary code). C'est un programme au format natif qui peut être compris par un CPU, sous la forme d'une longue série de 0 et de 1. Le code machine, ou code binaire, est le seul modèle de calcul qu'un ordinateur peut exécuter ; un programme écrit dans tout autre langage doit être compilé ou interprété en code machine avant que le programme ne puisse s'exécuter. Le CPU d'un ordinateur est une puce informatique capable d'exécuter des programmes en code machine (Figure 4.6). Il est peu pratique pour les humains de travailler directement avec le code machine car un programme en code machine n'est pas conçu pour être lisible par l'homme. Les motifs de 0 et de 1 sont conçus pour être pratiques à décoder par un CPU, et non pour être manipulés par des humains ; et de tels programmes sont longs, typiquement des millions ou des milliards de bits. Un autre obstacle est que le code machine est dépendant du matériel. Comme discuté dans 5.3 Représentation de l'information au niveau machine, chaque architecture de processeur a son propre langage machine, de sorte que le langage machine écrit pour une architecture ne peut pas fonctionner sur une autre architecture. Lorsque les tout premiers ordinateurs numériques ont été construits, et que les langages de programmation n'avaient pas encore été inventés, les programmeurs n'avaient d'autre choix que d'écrire le code machine à la main. Cependant, cela est extrêmement chronophage et sujet aux erreurs, de sorte que ce n'est presque jamais fait aujourd'hui.
Langage d'assemblage
Le langage de bas niveau dans lequel chaque instruction correspond directement à une instruction machine est appelé langage d'assemblage (assembly language). Le langage d'assemblage est un petit pas au-dessus du code machine mais reste un langage de très bas niveau. Le langage d'assemblage est une représentation textuelle du code machine. Tout comme un programme en code machine, un programme en langage d'assemblage est une série d'instructions qu'un CPU exécutera. Cependant, plutôt que d'écrire les instructions dans un format binaire de 0 et de 1, chaque instruction a un nom textuel tel que « ADD » ou « MOVE ». Un assembleur (assembler) est un programme qui traduit le code source du langage d'assemblage en code machine. Comme le montre la Figure 4.7, un assembleur traduit chaque instruction textuelle en la liste correspondante de bits 0 et 1.
Bien qu'il soit pratiquement impossible pour un humain d'écrire un programme complet en code machine, l'écriture de programmes en langage d'assemblage est viable. Parce que le langage d'assemblage est extrêmement bas niveau, ces programmes ont tendance à s'exécuter rapidement, mais ils sont exigeants en main-d'œuvre à écrire et sont dépendants de la machine. Ce type de programmation était suffisant dans les années 1960, 1970 et 1980, lorsque les logiciels étaient écrits pour des machines uniques à forte intensité de capital, telles que des mainframes de plusieurs millions de dollars ou des véhicules spatiaux. Le travail des programmeurs était alors relativement bon marché, et il n'était pas nécessaire de déplacer les programmes vers différents matériels. Mais aujourd'hui, nous nous attendons à ce que les applications soient compatibles avec plusieurs types de plateformes, y compris les téléphones, les ordinateurs et les systèmes de jeu. Le travail des programmeurs est plus coûteux que le matériel informatique, de sorte qu'écrire des programmes entiers en langage d'assemblage n'est pas rentable. Par conséquent, les programmes sont souvent écrits principalement dans un langage de haut niveau, le langage d'assemblage étant utilisé pour écrire de courts extraits au besoin. Écrire du code dans un langage de niveau supérieur facilite l'écriture de code correct et sans défaut.
Lien interactif
Le langage d'assemblage a été utilisé dans des projets de grande envergure et à gros budget, tels qu'Apollo 11, le vol spatial de la NASA qui a fait atterrir les premiers humains sur la Lune. Vous pouvez examiner le code d'assemblage des ordinateurs embarqués dans les véhicules spatiaux, qui a été rendu public. Remarquez à quel point il est de bas niveau, peut-être difficile à suivre, et reflète une quantité immense de travail méticuleux.
Programmation de niveau intermédiaire et de haut niveau
Comme son nom l'indique, un langage de programmation de niveau intermédiaire (middle-level programming language) se situe à un niveau d'abstraction (level of abstraction) entre le langage de bas niveau et le langage de haut niveau, et permet un accès direct au matériel. Le langage de programmation C (C) est un langage de niveau intermédiaire largement utilisé depuis les années 1970. Le langage de programmation C++ (C++) est un langage orienté objet de niveau intermédiaire basé sur C. En général, le compromis entre les langages de bas niveau et de haut niveau est que l'écriture de code de bas niveau est laborieuse et sujette aux erreurs, mais le code fini s'exécute très rapidement ; le code de haut niveau est plus rapide, plus facile et plus sûr à écrire mais ne s'exécute pas aussi rapidement. Le code de niveau intermédiaire est un compromis qui s'exécute presque aussi vite que le code de bas niveau tout en offrant certains des avantages de productivité du code de haut niveau. Comme les langages de bas niveau, les langages de niveau intermédiaire permettent un accès direct au matériel informatique, ce qui rend possible l'écriture de programmes spécifiques au matériel tels que les systèmes d'exploitation et les pilotes de périphériques. Un système d'exploitation (operating system) est le logiciel qui fournit une plateforme pour les applications et gère les composants matériels. Un pilote de périphérique (device driver) est un morceau de code responsable de la connexion à un composant matériel, tel qu'une carte vidéo ou un clavier. Figure 4.8 résume les compromis entre les langages de programmation de bas niveau, de niveau intermédiaire et de haut niveau (high-level programming language).
Les langages de niveau intermédiaire sont idéalement adaptés à l'écriture de logiciels système (systems software), des programmes qui fournissent l'infrastructure et les plateformes sur lesquelles d'autres programmes s'appuient. La partie cœur (core) d'un système d'exploitation qui est responsable de la gestion et de l'interface avec les composants matériels est appelée le noyau (kernel). Les noyaux nécessitent un accès direct au matériel, de sorte que les langages de haut niveau sont inadéquats. Pratiquement tous les noyaux répandus sont écrits en C et/ou C++ (tels que Windows, MacOS, Linux (Linux), iOS, Android, Xbox et PlayStation). Les compilateurs pour les langages de haut niveau, tels que Python, Java et C#, sont eux-mêmes implémentés dans des langages de niveau intermédiaire tels que C.
Figure 4.9 résume les différents types de langages de programmation (programming language) et comment les langages de niveau intermédiaire chevauchent les langages de programmation de bas niveau et de haut niveau.
Un langage de haut niveau est plus éloigné d'un modèle matériel (hardware model), et plus proche d'un modèle abstrait. Le code source dans un langage de haut niveau n'aborde pas les détails de bas niveau, et se concentre plutôt sur la manière dont un algorithme procède, comme « visiter chaque élément d'une liste ». Un langage de haut niveau est comme observer la Terre à haute altitude, révélant de grandes caractéristiques telles que les contours des rivières et des autoroutes, tandis qu'un langage de bas niveau est comme observer la Terre au niveau du sol, ce qui permet de se concentrer sur des détails fins tels que l'activité des personnes et des animaux individuels.
Les cadriciels d'applications web sont écrits dans des langages de haut niveau, principalement JavaScript. Un cadriciel web est un outil spécial pour construire et gérer des applications web. Certains des plus courants utilisés dans les clients web sont HTML5, CSS et JavaScript. Les applications Android natives sont principalement écrites dans le langage de haut niveau Java, et les applications iOS sont principalement écrites dans le langage de haut niveau Swift.
Paradigmes de langages de programmation
Jusqu'à présent, nous avons catégorisé les langages de programmation selon leur niveau d'abstraction en langages de bas niveau, de niveau intermédiaire et de haut niveau. Une approche différente consiste à catégoriser les langages en paradigmes. Un paradigme de langage de programmation (programming language paradigm) est une philosophie et une approche pour organiser le code, les idées dans un programme et la disposition de son code source. Les programmes du monde réel impliquent de nombreux milliers de lignes de code source, ce qui est trop pour qu'un humain puisse le digérer sans une sorte de structure organisationnelle. Les informaticiens ont développé plusieurs paradigmes différents pour créer cette structure.
Contrairement au niveau d'abstraction, les paradigmes ne se situent pas sur un spectre. Au lieu de cela, un langage de programmation particulier adhère à la philosophie d'un paradigme, ou il n'y adhère pas. Par exemple, C est un langage procédural structuré et non un langage orienté objet. Sans entrer dans trop de détails, C est procédural car il permet aux programmeurs de placer du code dans des fonctions qui peuvent être appelées depuis divers endroits d'un programme. Cependant, C n'est pas orienté objet car C ne permet pas, comme Java, la création d'objets qui sont des instances de classes. Nous explorerons largement ces différents types de paradigmes plus tard dans cette section, mais le Chapitre 7 Langages de programmation de haut niveau développe ces paradigmes et d'autres plus en détail.
Le paradigme de programmation impérative
En programmation impérative (imperative programming), le programmeur écrit une série d'étapes qui doivent être suivies dans l'ordre. Le code source énonce une série précise d'opérations que l'ordinateur doit exécuter dans l'ordre. Puisque l'ordinateur est invité à prendre des actions spécifiques et à exécuter ces instructions, le langage est qualifié d'« impératif ». Un impératif est un ordre ou une commande. Les langages de bas niveau sont des langages impératifs, et les langages de niveau intermédiaire, tels que C, sont impératifs et incluent un autre paradigme. Bien que les langages de bas niveau puissent imiter le style d'un langage structuré, ces propriétés ne sont pas inhérentes au langage lui-même et doivent être imposées par le programmeur comme une pratique. Le code d'assemblage peut facilement être écrit de manière non structurée.
Programmation déclarative et fonctionnelle
Un autre type de programmation, la programmation déclarative (declarative programming), est un paradigme dans lequel le code dicte un résultat souhaité sans spécifier comment ce résultat est atteint. Les langages déclaratifs sont une alternative aux langages impératifs. Dans un langage déclaratif, le programmeur déclare le résultat souhaité, et c'est le travail du compilateur (compiler) de créer une série d'étapes impératives qui obtiennent ce résultat. Par exemple, le Structured Query Language utilisé pour interroger les systèmes de bases de données permet de spécifier quelles données doivent être récupérées d'une base de données, sans spécifier comment le système de base de données doit récupérer ces données.
Les langages fonctionnels sont une autre alternative aux langages impératifs. Rappelons qu'une fonction (function) est un objet (object) mathématique qui définit comment convertir une entrée en une sortie. Par exemple, étant donné x = 4, la fonction convertit l'entrée 4 en la sortie 7. Les fonctions peuvent être définies dans la plupart des langages de programmation et correspondent à de petites sections de code qui effectuent une tâche spécifique telle qu'un calcul. Les fonctions peuvent être définies dans la plupart des langages de programmation.
La programmation fonctionnelle est un paradigme de programmation dans lequel les algorithmes sont écrits comme des fonctions mathématiques (Figure 4.10). En programmation fonctionnelle, pratiquement chaque partie du programme est écrite comme une fonction. Le programmeur écrit des fonctions qui convertissent les entrées en sorties, et c'est le travail du compilateur de créer des étapes impératives pour évaluer les fonctions.
Les langages déclaratifs et fonctionnels sont considérés comme des langages de haut niveau car le compilateur crée ces étapes au nom du programmeur. Les langages fonctionnels sont discutés plus en détail dans le Chapitre 7 Langages de programmation de haut niveau.
Programmation structurée
Dans les langages de bas niveau et les premiers langages de haut niveau tels que BASIC (BASIC), certaines instructions spéciales appelées instructions conditionnelles (utilisant « if/then ») et itération (appelées « boucles ») sont programmées à l'aide d'une opération appelée GOTO (GOTO), une opération non structurée qui ordonne à un ordinateur de sauter à une partie entièrement différente du programme. Dans les grands programmes, ces sauts d'un endroit à l'autre interagissent de manière complexe, de sorte que le flux d'exécution est difficile à comprendre lors de la lecture du code. Ces types de programmes sont critiqués pour être du « code spaghetti » désordonné (Figure 4.11).
De nouveaux langages ont été développés pour aider à éviter le code spaghetti. Dans un langage de programmation structurée (structured programming), le flux de contrôle utilise des conditionnelles (par exemple, « if-then ») et des instructions d'itération (par exemple, « while » ou « do while ») et n'utilise jamais d'instructions GOTO. Par exemple, C est un langage structuré qui inclut les instructions conditionnelles « if » et « switch », et les instructions d'itération « for », « while » et « do ». En C correct, toutes les sections de code qui impliquent des conditionnelles et des itérations sont écrites avec ces instructions, et GOTO ne devrait pas être utilisé. Notez que le fait que GOTO soit fourni comme mot-clé dans le langage C est lié au fait que C est un langage de bas niveau et que les programmeurs à ce niveau ont le choix d'utiliser la programmation non structurée si nécessaire, bien que ce ne soit pas recommandé.
Lien interactif
Lisez cet article séminal sur la façon dont les instructions GOTO peuvent être considérées comme nuisibles écrit par Edgar Dijkstra.
L'avantage d'utiliser ces instructions est qu'elles rendent le flux d'exécution clair dans le code source. Lors de l'écriture d'un « if », par exemple, il est clair quel code se trouve à l'intérieur du « if » et quel code se trouve à l'extérieur. Et lors du mélange d'un « if » avec une boucle « for », il est clair si le « if » est à l'intérieur du « while » ou vice-versa. Ces types de relations intérieur/extérieur sont difficiles à percevoir dans le code non structuré. Dans une instruction conditionnelle comme « if », le compilateur exécute une ligne si la condition a été remplie ou est vraie. Sinon, il passe à l'instruction suivante :
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Enter an input value: ");
int Val = s.nextInt();
int Curr_Val = 10;
if (Val > Curr_Val) {
System.out.println("The Value that you entered is greater than the current.");
} else {
System.out.println("The Current value is greater than the value that you entered.");
}
}
}
À l'intérieur d'une boucle, comme « while », les instructions ne sont exécutées que si la condition de la boucle est vraie. Sinon, l'exécution de la boucle se termine, et le compilateur passe aux instructions après la boucle :
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("Enter an input value: ");
int Val = s.nextInt();
int Prod = 1;
while (Val != 0) {
Prod = Prod * Val;
Val--;
}
System.out.println("The factorial is " + Prod);
}
}
Il y a un avantage substantiel à rendre un langage structuré, et le seul inconvénient significatif est que cela rend le langage un peu plus de haut niveau. Par conséquent, parmi les langages de programmation actuellement largement utilisés, tous les langages de niveau intermédiaire et de haut niveau sont structurés.
Programmation procédurale
Dans un langage procédural, chaque partie du programme est une procédure (procedure), qui est une fonction dans le contexte de la programmation. Connue sous le nom de programmation procédurale (procedural programming), c'est un paradigme dans lequel le code est organisé en procédures (Figure 4.12). C'est un sous-type de programmation impérative. Tous les langages procéduraux sont donc impératifs, mais tous les langages impératifs ne sont pas procéduraux. Un programmeur conçoit chaque procédure pour accomplir une tâche spécifique et lui donne un nom descriptif. Cela permet au programmeur de diviser un programme vaste et compliqué en morceaux plus petits et plus gérables, qui sont plus faciles à écrire et plus faciles à comprendre pour les autres programmeurs. Cette propriété du code divisé en petites pièces réutilisables est appelée modularité (modularity), et elle est considérée comme une vertu.
Par exemple, en C, une procédure qui ouvre une socket (socket), ou une connexion Internet entre deux ordinateurs, est appelée g_socket_connect()(Figure 4.13). Cette procédure implique l'exécution d'une série de commandes impératives qui utilisent les fonctionnalités du système d'exploitation, les appels système et le matériel réseau (tels que les cartes d'interface réseau, ou NIC), pour établir une connexion socket. Pour fermer cette connexion et terminer la communication, C (C) utilise la procédure g_socket_close(), qui exécute une série de commandes qui ferment la connexion. Ces procédures utilisent l'approche impérative pour accomplir leurs tâches respectives, de sorte que chaque fonction contient une série d'instructions impératives.
Un langage de programmation procédurale (procedural programming) fournit une syntaxe pour définir des procédures mais ne peut pas forcer les programmeurs individuels à diviser leur code en petites procédures et à donner des noms descriptifs aux procédures. Ainsi, même lorsqu'un programme est écrit dans un langage procédural, le code source peut ne pas nécessairement être écrit dans un style procédural.
Programmation orientée objet
Le code orienté objet est organisé autour d'objets. Un objet (object) possède à la fois des données, ou variables, et des procédures qui travaillent ensemble pour représenter un concept humain spécifique. Par exemple, dans une application de bureau ou mobile, chaque bouton à l'écran est un objet. Chaque bouton a des variables pour représenter des informations, telles que l'emplacement et la couleur du bouton, et des procédures qui effectuent des tâches, telles que cliquer, masquer ou afficher le bouton. Ce paradigme de programmation est connu sous le nom de programmation orientée objet (object-oriented programming). C'est un paradigme de programmation dans lequel le code est organisé en objets, où chaque objet a à la fois des données et des procédures. C'est un sous-type de programmation procédurale. Tous les langages orientés objet sont donc procéduraux (et par extension, impératifs), mais tous les langages procéduraux ne sont pas orientés objet. Un exemple simple d'objet peut être un rectangle utilisé pour représenter des concepts significatifs dans la vie réelle, tels que les pièces d'une maison ou une personne ou un robot et ce qu'il peut faire. Différentes pièces peuvent avoir différents attributs, représentant des caractéristiques spécifiques à une cuisine, un salon ou une chambre. Un robot peut avoir un nom et un âge et peut recevoir des commandes d'entrée et répondre ou imprimer un message d'accueil, comme illustré dans la Figure 4.14.
input(), output(), et
print(). (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)
La programmation orientée objet a été inventée pour aider les programmeurs à organiser leur code, et elle a connu un grand succès. Les langages de haut niveau les plus largement utilisés, y compris C++ (C++), C#, Java, JavaScript et Swift, sont tous orientés objet. La programmation orientée objet est discutée plus en détail dans le Chapitre 7 Langages de programmation de haut niveau.