Article de reference

Programmation impérative

En informatique , la programmation impérative est un paradigme de programmation de logiciels qui utilise des instructions qui modifient l' état d'un programme . De la même maniè...

En informatique , la programmation impérative est un paradigme de programmation de logiciels qui utilise des instructions qui modifient l' état d'un programme . De la même manière que le mode impératif dans les langues naturelles exprime des commandes, un programme impératif se compose de commandes que l' ordinateur doit exécuter. La programmation impérative se concentre sur la description du fonctionnement d'un programme étape par étape, plutôt que sur des descriptions de haut niveau de ses résultats attendus.

Le terme est souvent utilisé en contraste avec la programmation déclarative , qui se concentre sur ce que le programme doit accomplir sans spécifier tous les détails de la manière dont le programme doit atteindre le résultat.

Programmation procédurale

La programmation procédurale est un type de programmation impérative dans lequel le programme est construit à partir d'une ou plusieurs procédures (également appelées sous-routines ou fonctions). Les termes sont souvent utilisés comme synonymes, mais l'utilisation de procédures a un effet considérable sur la façon dont les programmes impératifs apparaissent et sur la façon dont ils sont construits. La programmation procédurale lourde, dans laquelle les changements d'état sont localisés dans les procédures ou limités aux arguments explicites et aux retours des procédures, est une forme de programmation structurée . Depuis les années 1960, la programmation structurée et la programmation modulaire en général ont été promues comme des techniques pour améliorer la maintenabilité et la qualité globale des programmes impératifs. Les concepts qui sous-tendent la programmation orientée objet tentent d'étendre cette approche.

La programmation procédurale peut être considérée comme une étape vers la programmation déclarative. Un programmeur peut souvent dire, simplement en regardant les noms, les arguments et les types de retour des procédures (et les commentaires associés), ce qu'une procédure particulière est censée faire, sans nécessairement regarder les détails de la façon dont elle obtient son résultat. En même temps, un programme complet est toujours impératif car il fixe dans une large mesure les instructions à exécuter et leur ordre d'exécution.

Fondements et fondements de la programmation impérative

Le paradigme de programmation utilisé pour créer des programmes pour presque tous les ordinateurs suit généralement un modèle impératif. Le matériel informatique numérique est conçu pour exécuter du code machine , qui est natif de l'ordinateur et est généralement écrit dans le style impératif, bien que des compilateurs et des interprètes de bas niveau utilisant d'autres paradigmes existent pour certaines architectures telles que les machines Lisp .

De ce point de vue de bas niveau, l'état du programme est défini par le contenu de la mémoire et les instructions sont des instructions dans le langage machine natif de l'ordinateur. Les langages impératifs de niveau supérieur utilisent des variables et des instructions plus complexes, mais suivent toujours le même paradigme. Les recettes et les listes de contrôle des processus , bien que n'étant pas des programmes informatiques , sont également des concepts familiers qui sont similaires dans leur style à la programmation impérative ; chaque étape est une instruction et le monde physique contient l'état. Étant donné que les idées de base de la programmation impérative sont à la fois familières sur le plan conceptuel et directement incorporées dans le matériel, la plupart des langages informatiques sont de style impératif.

Les instructions d'affectation , dans le paradigme impératif, effectuent une opération sur des informations situées en mémoire et stockent les résultats en mémoire pour une utilisation ultérieure. Les langages impératifs de haut niveau permettent en outre l' évaluation d' expressions complexes , qui peuvent consister en une combinaison d' opérations arithmétiques et d'évaluations de fonctions , et l'affectation de la valeur résultante à la mémoire. Les instructions de boucle (comme dans les boucles while , do while et for ) permettent d'exécuter plusieurs fois une séquence d'instructions. Les boucles peuvent soit exécuter les instructions qu'elles contiennent un nombre prédéfini de fois, soit les exécuter de manière répétée jusqu'à ce qu'une condition soit remplie. Les instructions de branchement conditionnel permettent d'exécuter une séquence d'instructions uniquement si une condition est remplie. Sinon, les instructions sont ignorées et la séquence d'exécution continue à partir de l'instruction qui les suit. Les instructions de branchement inconditionnel permettent de transférer une séquence d'exécution vers une autre partie d'un programme. Il s'agit notamment du saut (appelé goto dans de nombreux langages), du switch et de l'appel de sous-programme, de sous-routine ou de procédure (qui revient généralement à l'instruction suivante après l'appel).

Au début du développement des langages de programmation de haut niveau , l'introduction du bloc a permis la construction de programmes dans lesquels un groupe d'instructions et de déclarations pouvait être traité comme s'il s'agissait d'une seule instruction. Ceci, associé à l'introduction des sous-routines , a permis d'exprimer des structures complexes par décomposition hiérarchique en structures procédurales plus simples.

De nombreux langages de programmation impératifs (tels que Fortran , BASIC et C ) sont des abstractions du langage assembleur .

Histoire des langages impératifs et orientés objet

Les premiers langages impératifs étaient les langages machines des premiers ordinateurs. Dans ces langages, les instructions étaient très simples, ce qui facilitait l'implémentation matérielle mais entravait la création de programmes complexes. FORTRAN , développé par John Backus chez International Business Machines (IBM) à partir de 1954, fut le premier langage de programmation majeur à supprimer les obstacles présentés par le code machine dans la création de programmes complexes. FORTRAN était un langage compilé qui autorisait les variables nommées, les expressions complexes, les sous-programmes et de nombreuses autres fonctionnalités désormais courantes dans les langages impératifs. Les deux décennies suivantes ont vu le développement de nombreux autres langages de programmation impératifs de haut niveau. À la fin des années 1950 et 1960, ALGOL a été développé afin de permettre aux algorithmes mathématiques d'être plus facilement exprimés et a même servi de langage cible du système d'exploitation pour certains ordinateurs. MUMPS (1966) a poussé le paradigme impératif à l'extrême logique, en n'utilisant aucune instruction du tout, en s'appuyant uniquement sur des commandes, au point même de rendre les commandes IF et ELSE indépendantes l'une de l'autre, reliées uniquement par une variable intrinsèque nommée $TEST. COBOL (1960) et BASIC (1964) étaient tous deux des tentatives pour rendre la syntaxe de programmation plus proche de l'anglais. Dans les années 1970, Pascal a été développé par Niklaus Wirth et C a été créé par Dennis Ritchie alors qu'il travaillait aux Bell Laboratories . Wirth a ensuite conçu Modula-2 et Oberon . Pour les besoins du ministère de la Défense des États-Unis , Jean Ichbiah et une équipe de Honeywell ont commencé à concevoir Ada en 1978, après un projet de 4 ans visant à définir les exigences du langage. La spécification a été publiée pour la première fois en 1983, avec des révisions en 1995, 2005 et 2012.

Les années 1980 ont vu une croissance rapide de l'intérêt pour la programmation orientée objet . Ces langages étaient de style impératif, mais ont ajouté des fonctionnalités pour prendre en charge les objets . Les deux dernières décennies du 20e siècle ont vu le développement de nombreux langages de ce type. Smalltalk -80, conçu à l'origine par Alan Kay en 1969, a été publié en 1980 par le Xerox Palo Alto Research Center ( PARC ). S'inspirant des concepts d'un autre langage orienté objet, Simula (considéré comme le premier langage de programmation orienté objet au monde , développé dans les années 1960), Bjarne Stroustrup a conçu C++ , un langage orienté objet basé sur C. La conception de C++ a commencé en 1979 et la première implémentation a été achevée en 1983. À la fin des années 1980 et dans les années 1990, les langages impératifs notables s'appuyant sur des concepts orientés objet étaient Perl , publié par Larry Wall en 1987, Python , publié par Guido van Rossum en 1990, et Visual Basic et Visual C++ (qui incluait Microsoft Foundation Class Library (MFC) 2.0), publiés par Microsoft respectivement en 1991 et 1993 ; PHP , publié par Rasmus Lerdorf en 1994 ; Java , par James Gosling ( Sun Microsystems ) en 1995, JavaScript , par Brendan Eich ( Netscape ), et Ruby , par Yukihiro « Matz » Matsumoto, tous deux publiés en 1995. Le .NET Framework (2002) de Microsoft est impératif à sa base, tout comme ses principaux langages cibles, VB.NET et C# qui s'exécutent dessus ; cependant, le F# de Microsoft , un langage fonctionnel, s'exécute également dessus.

Exemples

Fortran

FORTRAN (1958) a été présenté comme le « système de traduction de formules mathématiques d'IBM ». Il a été conçu pour les calculs scientifiques, sans fonctionnalités de gestion de chaînes . Outre les déclarations , les expressions et les instructions , il prenait en charge :

Cela a réussi parce que :

  • les coûts de programmation et de débogage étaient inférieurs aux coûts de fonctionnement de l'ordinateur
  • il a été soutenu par IBM
  • les applications à l'époque étaient scientifiques.

Cependant, des fournisseurs non IBM ont également écrit des compilateurs Fortran, mais avec une syntaxe qui aurait probablement fait échouer le compilateur d'IBM. L' American National Standards Institute (ANSI) a développé la première norme Fortran en 1966. En 1978, Fortran 77 est devenu la norme jusqu'en 1991. Fortran 90 prend en charge :

COBOL

COBOL (1959) signifie « Common Business Oriented Language ». Fortran manipulait des symboles. On s'est vite rendu compte que les symboles n'avaient pas besoin d'être des nombres, donc des chaînes de caractères ont été introduites. Le Département de la Défense américain a influencé le développement de COBOL, Grace Hopper étant l'un des principaux contributeurs. Les instructions étaient de type anglais et verbeuses. L'objectif était de concevoir un langage permettant aux gestionnaires de lire les programmes. Cependant, le manque d'instructions structurées a entravé cet objectif.

Le développement de COBOL a été étroitement contrôlé, de sorte que des dialectes n'ont pas émergé pour nécessiter des normes ANSI. Par conséquent, il n'a pas été modifié pendant 15 ans jusqu'en 1974. La version des années 1990 a apporté des modifications conséquentes, comme la programmation orientée objet .

Algol

ALGOL (1960) signifie « ALGOrithmic Language ». Il a eu une profonde influence sur la conception des langages de programmation. Issu d'un comité d'experts européens et américains en langages de programmation, il utilisait une notation mathématique standard et avait une conception structurée lisible. Algol a été le premier à définir sa syntaxe en utilisant la forme Backus–Naur . Cela a conduit à des compilateurs orientés syntaxe . Il a ajouté des fonctionnalités telles que :

Les descendants directs d'Algol incluent Pascal , Modula-2 , Ada , Delphi et Oberon sur une branche. Sur une autre branche, il y a C , C++ et Java .

Basique

BASIC (1964) signifie « Code d'instruction symbolique polyvalent pour débutants ». Il a été développé au Dartmouth College pour que tous ses étudiants puissent l'apprendre. Même si un étudiant ne passait pas à un langage plus puissant, il se souvenait toujours du Basic. Un interpréteur Basic a été installé dans les micro-ordinateurs fabriqués à la fin des années 1970. Au fur et à mesure que l'industrie des micro-ordinateurs s'est développée, le langage a également grandi.

Basic a été le pionnier de la session interactive . Il offrait des commandes de système d'exploitation au sein de son environnement :

  • La commande « nouveau » a créé une page vide
  • Déclarations évaluées immédiatement
  • Les instructions peuvent être programmées en les précédant d'un numéro de ligne
  • La commande « liste » affiche le programme
  • La commande « run » a exécuté le programme

Cependant, la syntaxe de base était trop simple pour les programmes volumineux. Les dialectes récents ont ajouté une structure et des extensions orientées objet. Visual Basic de Microsoft est toujours largement utilisé et produit une interface utilisateur graphique .

C

Le langage de programmation C (1973) doit son nom au remplacement du langage BCPL par le langage B , et AT&T Bell Labs a appelé la version suivante « C ». Son but était d'écrire le système d'exploitation UNIX . C est un langage relativement petit, ce qui facilite l'écriture de compilateurs. Sa croissance a reflété la croissance du matériel dans les années 1980. Sa croissance est également due au fait qu'il dispose des fonctionnalités du langage assembleur , mais utilise une syntaxe de haut niveau . Il a ajouté des fonctionnalités avancées telles que :

Carte mémoire de l'ordinateur

Le C permet au programmeur de contrôler dans quelle région de la mémoire les données doivent être stockées. Les variables globales et les variables statiques nécessitent le moins de cycles d'horloge pour être stockées. La pile est automatiquement utilisée pour les déclarations de variables standard . La mémoire de tas est renvoyée à une variable pointeur à partir de la malloc()fonction.

  • La région des données globales et statiques est située juste au-dessus de la région du programme . (La région du programme est techniquement appelée la région du texte . C'est là que les instructions de la machine sont stockées.)
  • La région des données globales et statiques est techniquement composée de deux régions. Une région est appelée segment de données initialisé , où sont stockées les variables déclarées avec des valeurs par défaut. L'autre région est appelée bloc démarré par segment , où sont stockées les variables déclarées sans valeurs par défaut.
  • Les adresses des variables stockées dans la région de données globales et statiques sont définies au moment de la compilation. Elles conservent leurs valeurs tout au long de la vie du processus.
  • La région globale et statique stocke les variables globales qui sont déclarées au-dessus (à l'extérieur) de la main()fonction. Les variables globales sont visibles par main()et toutes les autres fonctions dans le code source.
En revanche, les déclarations de variables à l'intérieur de main(), d'autres fonctions ou à l'intérieur { } de délimiteurs de blocs sont des variables locales . Les variables locales incluent également des variables de paramètres formelles . Les variables de paramètres sont placées entre les parenthèses des définitions de fonctions. Elles fournissent une interface à la fonction.
  • Les variables locales déclarées à l'aide du staticpréfixe sont également stockées dans la région de données globales et statiques . Contrairement aux variables globales, les variables statiques ne sont visibles que dans la fonction ou le bloc. Les variables statiques conservent toujours leur valeur. Un exemple d'utilisation serait la fonctionint increment_counter(){ static int counter = 0; counter++; return counter;}
  • La région de pile est un bloc de mémoire contigu situé près de l'adresse mémoire supérieure. Les variables placées dans la pile sont renseignées de haut en bas. Un pointeur de pile est un registre à usage spécial qui garde la trace de la dernière adresse mémoire renseignée. Les variables sont placées dans la pile via l' instruction PUSH du langage assembleur . Par conséquent, les adresses de ces variables sont définies pendant l'exécution . La méthode permettant aux variables de pile de perdre leur portée est via l'instruction POP.
  • Les variables locales déclarées sans staticpréfixe, y compris les variables de paramètres formels, sont appelées variables automatiques et sont stockées dans la pile. Elles sont visibles à l'intérieur de la fonction ou du bloc et perdent leur portée à la sortie de la fonction ou du bloc.
  • La zone de tas est située sous la pile. Elle est remplie de bas en haut. Le système d'exploitation gère le tas à l'aide d'un pointeur de tas et d'une liste de blocs de mémoire alloués. Comme la pile, les adresses des variables de tas sont définies pendant l'exécution. Une erreur de manque de mémoire se produit lorsque le pointeur de tas et le pointeur de pile se rencontrent.
  • C fournit la malloc()fonction de bibliothèque permettant d' allouer la mémoire du tas. Le remplissage du tas avec des données est une fonction de copie supplémentaire. Les variables stockées dans le tas sont transmises de manière économique aux fonctions à l'aide de pointeurs. Sans pointeurs, l'intégralité du bloc de données devrait être transmise à la fonction via la pile.

C++

Dans les années 1970, les ingénieurs logiciels avaient besoin d'un support linguistique pour décomposer les grands projets en modules . Une fonctionnalité évidente était de décomposer physiquement les grands projets en fichiers séparés . Une fonctionnalité moins évidente était de décomposer logiquement les grands projets en types de données abstraits . À l'époque, les langages prenaient en charge les types de données concrets ( scalaires ) comme les nombres entiers , les nombres à virgule flottante et les chaînes de caractères . Les types de données concrets ont leur représentation dans le cadre de leur nom. Les types de données abstraits sont des structures de types de données concrets — avec un nouveau nom attribué. Par exemple, une liste d'entiers pourrait être appelée . integer_list

Dans le jargon orienté objet, les types de données abstraits sont appelés classes . Cependant, une classe n'est qu'une définition ; aucune mémoire n'est allouée. Lorsque de la mémoire est allouée à une classe, elle est appelée un objet .

Les langages impératifs orientés objet se sont développés en combinant le besoin de classes et le besoin d' une programmation fonctionnelle sûre . Une fonction, dans un langage orienté objet, est assignée à une classe. Une fonction assignée est alors appelée méthode , fonction membre ou opération . La programmation orientée objet consiste à exécuter des opérations sur des objets .

Les langages orientés objet prennent en charge une syntaxe pour modéliser les relations sous-ensemble/sur-ensemble . Dans la théorie des ensembles , un élément d'un sous-ensemble hérite de tous les attributs contenus dans le sur-ensemble. Par exemple, un étudiant est une personne. Par conséquent, l'ensemble des étudiants est un sous-ensemble de l'ensemble des personnes. En conséquence, les étudiants héritent de tous les attributs communs à toutes les personnes. De plus, les étudiants ont des attributs uniques que les autres personnes n'ont pas. Les langages orientés objet modélisent les relations sous-ensemble/sur-ensemble à l'aide de l'héritage . La programmation orientée objet est devenue le paradigme de langage dominant à la fin des années 1990.

C++ (1985) s'appelait à l'origine « C avec classes ». Il a été conçu pour étendre les capacités de C en ajoutant les fonctionnalités orientées objet du langage Simula .

Un module orienté objet est composé de deux fichiers. Le fichier de définitions est appelé fichier d'en-tête . Voici un fichier d'en-tête C++ pour la classe GRADE dans une application scolaire simple :

// note.h 
// -------
// Utilisé pour permettre à plusieurs fichiers sources d'inclure 
// ce fichier d'en-tête sans erreurs de duplication. 
// Voir : https://en.wikipedia.org/wiki/Include_guard 
// ---------------------------------------------- 
#ifndef GRADE_H 
#define GRADE_H
classe GRADE { public : // Ceci est l'opération du constructeur. // ---------------------------------- GRADE ( const char letter );
// Ceci est une variable de classe. 
// ------------------------- char letter ;
// Il s'agit d'une opération membre. 
// --------------------------- int grade_numeric ( const char letter );
// Ceci est une variable de classe. 
// ------------------------- int numeric ; }; #endif

Une opération de constructeur est une fonction portant le même nom que le nom de la classe. Elle est exécutée lorsque l'opération appelante exécute l' newinstruction.

L'autre fichier d'un module est le fichier source . Voici un fichier source C++ pour la classe GRADE dans une application scolaire simple :

// note.cpp 
// --------- 
#include "note.h"
GRADE :: GRADE ( const char letter ) { // Référencez l'objet en utilisant le mot-clé 'this'. // ---------------------------------------------- this -> letter = letter ;
// Ceci est la cohésion temporelle 
// ------------------------- this -> numeric = grade_numeric ( letter ); }
int GRADE :: grade_numeric ( const char lettre ) { si ( ( lettre == 'A' || lettre == 'a' ) ) renvoie 4 ; sinon si ( ( lettre == 'B' || lettre == 'b' ) ) renvoie 3 ; sinon si ( ( lettre == 'C' || lettre == 'c' ) ) renvoie 2 ; sinon si ( ( lettre == 'D' || lettre == 'd' ) ) renvoie 1 ; sinon si ( ( lettre == 'F' || lettre == 'f' ) ) renvoie 0 ; sinon renvoie -1 ; }

Voici un fichier d'en-tête C++ pour la classe PERSON dans une application scolaire simple :

// personne.h 
// -------- 
#ifndef PERSON_H 
#define PERSON_H
classe PERSONNE { public : PERSONNE ( const char * nom ); const char * nom ; }; #endif

Voici un fichier source C++ pour la classe PERSON dans une application scolaire simple :

// personne.cpp 
// ---------- 
#include "personne.h"
PERSONNE :: PERSONNE ( const char * nom ) { ceci -> nom = nom ; }

Voici un fichier d'en-tête C++ pour la classe STUDENT dans une application scolaire simple :

// étudiant.h 
// --------- 
#ifndef ÉTUDIANT_H 
#define ÉTUDIANT_H
#include "personne.h" #include "note.h"
// Un ÉTUDIANT est un sous-ensemble de PERSONNE. 
// -------------------------------- 
class ÉTUDIANT : public PERSONNE { public : ÉTUDIANT ( const char * nom ); ~ ÉTUDIANT (); GRADE * note ; }; #endif

Voici un fichier source C++ pour la classe STUDENT dans une application scolaire simple :

// étudiant.cpp 
// ----------- 
#include "étudiant.h" #include "personne.h"
STUDENT :: STUDENT ( const char * name ) : // Exécute le constructeur de la superclasse PERSON. // ------------------------------------------------- PERSON ( name ) { // Rien d'autre à faire. // ------------------- }
ÉTUDIANT ::~ ÉTUDIANT () { // désallouer la mémoire de note // pour éviter les fuites de mémoire. // ------------------------------------------------- supprimer ceci -> note ; }

Voici un programme pilote pour démonstration :

// student_dvr.cpp 
// --------------- 
#include <iostream> #include "student.h"
int main ( void ) { ÉTUDIANT * étudiant = nouvel ÉTUDIANT ( "L'étudiant" ); étudiant -> note = nouvelle GRADE ( 'a' );
std :: cout // Notez que l'étudiant hérite du nom de la PERSONNE << étudiant -> nom << ": Note numérique = " << étudiant -> note -> numérique << " " ;
// désallouer la mémoire de l'étudiant 
// pour éviter les fuites de mémoire. // ------------------------------------------------- supprimer l'étudiant ;
retourner 0 ; }

Voici un makefile pour tout compiler :

# makefile 
# -------- 
tous : student_dvr
nettoyer : rm student_dvr *.o student_dvr : student_dvr . cpp grade . o étudiant . o personne . o c++ student_dvr.cpp grade.o étudiant.o personne.o -o student_dvr note.o : note.cpp note.h c ++ -c note.cppétudiant.o : étudiant . cpp étudiant . h c++ -c étudiant.cpp personne.o : personne . cpp personne . h c++ -c personne.cpp 

Plus d articles de Worldlex Wiki

Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

Explorer l index