Programmation/Version imprimable

Ceci est la version imprimable de Programmation.
  • Si vous imprimez cette page, choisissez « Aperçu avant impression » dans votre navigateur, ou cliquez sur le lien Version imprimable dans la boîte à outils, vous verrez cette page sans ce message, ni éléments de navigation sur la gauche ou en haut.
  • Cliquez sur Rafraîchir cette page pour obtenir la dernière version du wikilivre.
  • Pour plus d'informations sur les version imprimables, y compris la manière d'obtenir une version PDF, vous pouvez lire l'article Versions imprimables.


Programmation

Une version à jour et éditable de ce livre est disponible sur Wikilivres,
une bibliothèque de livres pédagogiques, à l'URL :
https://fr.wikibooks.org/wiki/Programmation

Vous avez la permission de copier, distribuer et/ou modifier ce document selon les termes de la Licence de documentation libre GNU, version 1.2 ou plus récente publiée par la Free Software Foundation ; sans sections inaltérables, sans texte de première page de couverture et sans Texte de dernière page de couverture. Une copie de cette licence est incluse dans l'annexe nommée « Licence de documentation libre GNU ».

Historique

Fondements technologiques

modifier

En 1946, lorsque fut créé le premier calculateur électronique, l'ENIAC, on ne pouvait guère parler d'ordinateur : la logique du système était directement câblée dans les composants, et la machine n'était donc pas programmable.

Il fallut attendre 1948 et le Mark I pour voir apparaître le premier ordinateur au sens où l'entendait Von Neumann : un calculateur doté d'une logique programmable, ce qui veut dire une machine capable d'exécuter différents programmes sans intervention sur le matériel. Ce n'est toutefois qu'en 1971 que l'invention du processeur permettra la programmation d'applications complexes.

Les principes logiques et mathématiques nécessaires à la programmation étaient déjà établis depuis longtemps : le binaire fut inventé par les Chinois il y a plusieurs millénaires, et fut introduit en Europe en 1697 par Leibniz, le principe du calcul par itération successive fut inventé par Ada Lovelace en 1843 (elle avait déjà eu l'idée d'une machine capable de calculer en 1840) et l'algèbre binaire fut inventée par Boole en 1854.

La programmation par câblage se faisait en reliant les différentes parties d'un calculateur permettant le transfert de signaux entre elles.

Évolution

modifier

L'arrivée de la logique programmable provoqua une cascade d'inventions : l'assembleur (c'est à dire l'utilisation de mnémoniques à la place des séquences de chiffres du langage machine) fut inventé en 1948, le premier langage évoluée, l'A0, en 1951, suivi du Fortran (1956), du Cobol (1959), du Lisp (1959) et de l'Algol (1960).

Le Basic est créé en 1965 et le Pascal en 1968. Le C et Prolog voient le jour en 1972 et Smalltalk, le premier langage objet, la même année.

La programmation orientée objet prendra son essor avec C++, créé en 1983. En 1986 est créé Perl. Python est créé en 1991 et 1995 verra l'apparition de Java, qui prétend être portable au niveau de l’exécutable, et de PHP. 2000 voit l'apparition du premier langage créé par Microsoft, C#.

Les langages de description, pas assez complets pour être considérés comme des langages de programmation, apparaissent vers 1969, avec le GML puis le SGML. Le HTML est créé en 1990. En 1996 est introduit XML. Ces deux derniers langages sont dérivés du SGML : leur syntaxe reprend différentes parties de celle du SGML.

Les travaux actuels semblent montrer que la tendance vers plus d'abstraction se poursuit, avec la programmation orientée aspect, par exemple.


Abstraction

Un programme à son niveau le plus fondamental est une suite de 0 et de 1, que le système interprète grâce au processeur qui effectue les opérations correspondantes : lecture et écriture de données (mémoire, fichier, ...), calculs, transfert de données, ...

Mais entre les composants électroniques au cœur du système et le mode de pensée du cerveau humain, il y a une succession de couches développées tout au long de l'histoire informatique destinées à traduire dans sa globalité nos pensées (abstraites) en instructions (concrètes) au sein de ce système de manière fiable et intuitive.

Le terme bit est la contraction du terme anglais binary digit (nombre binaire). En électronique numérique les signaux et les composants ne peuvent généralement se stabiliser que sur 2 états, habituellement 0 et 5 volts, auxquels on attribue arbitrairement la valeur 0 pour l'un et 1 pour l'autre. Ainsi, les composants informatiques rassemblent des millions de transistors qui ne peuvent fonctionner que selon une logique à deux états. Pour simplifier si on applique une tension de valeur binaire 1 à un transistor, celui-ci laisse passer le courant, si on lui applique une tension correspondant à la valeur binaire 0, il bloquera le courant. Le rôle des transistors est, rappelons-le, de contrôler le courant afin de l'utiliser précisément là où on en a besoin. Le courant lui même, s'il véhicule une information est bi-stable (stable sur deux états).

De même pour la représentation et stockage de données, toute image, toute information doit d'abord être convertie en une succession de 0 et de 1 pour que l'information puisse circuler dans les systèmes électroniques d'abord, puis stockée ou rendue.

Notion de "mot binaire"

modifier

Un mot binaire est un ensemble de bits qui sera interprété par le microprocesseur ou stocké dans une mémoire. Ces mots sont quantifiés par le nombre de bits que peut contenir un mot binaire. Par exemple 10110101 est un mot de 8 bits. Par définition un mot binaire de 8 bits est appelé octet. Cette façon d'assembler ces bits rend plus rapide le traitement et la circulation des données dans un calculateur. Chaque organe du calculateur est relié par un bus de données où circulent ces mots binaires de façon parallèle.

Notion de poids

modifier

En base 10 (décimal) le nombre 2453 est composé de différents chiffres ayant des valeurs différentes. Le 3 représente les unités, le 5 les dizaines, le 4 les centaines et le 2 les milliers. On peut dire que le 2 sur ce nombre en base 10 a plus de valeur (poids) que le 3.

En binaire c'est pareil : dans 100101010, le 1 est appelé MSB pour Most Signifiant Bit qui est le bit représentant le poids le plus fort du mot. Ainsi le 0 est appelé LSB pour Least Signifiant Bit le bit à la valeur la plus faible.

Représentation des nombres

modifier

Historiquement on a utilisé les ordinateurs pour manipuler des nombres décimaux, autrement dit pour faire des calculs. Le bit étant lui même un nombre, la conversion entre un nombre décimal (en base 10) en un nombre binaire (en base 2) peut se faire avec des procédures relativement simples.

La notion de base arithmétique

modifier

Dans un système numérique « basé », chaque chiffre d'un nombre est multiplié par la valeur de sa base, valeur qui elle-même est mise à une puissance correspondant à sa position dans le nombre par rapport au séparateur « décimal » (la virgule selon la norme française, le point selon la norme britannique).

Ainsi le nombre en base 10

 

veut dire

 

c'est à dire

 

ou encore

 

Le binaire pur

modifier

Pour savoir à quoi correspond   en base 2 (c'est à dire savoir à quoi ressemble une telle quantité dans une suite de chiffres compris entre 0 et 1) on modifie la base de calcul d'abord.

Ainsi en binaire,   voudrait (improprement) dire

 

Sauf que 7, 6, 5... ne sont pas des chiffres binaires à proprement parler. En décompte décimal on reporte une unité sur la rangée suivante lorsqu'on arrive à 9, en binaire on le fait dès qu'on arrive à 1, c'est à dire que 0 en base 10 correspond bien à 0 en base 2, de même que 1 en base 10 correspond bien à 1 en base 2 ; mais 2 en base 10 correspond à 10 en base 2 (si vous avez suivi), et ainsi de suite 3 correspond à 11, 4 à 100, 5 à 101... À titre indicatif voici le tableau de correspondance en binaire des 9 chiffres décimaux :

Correspondance entre les chiffres décimaux et leur valeur en binaire
0 1 2 3 4 5 6 7 8 9
0 1 10 11 100 101 110 111 1000 1001

Mais un 7 à la deuxième rangée d'un nombre décimal est fondamentalement différent d'une quelconque équivalence binaire à 7 à la même rangée. Le 7 de la base 10 est le résultat de 70 groupements de 10, on voit donc que si le groupement n'était pas fait sur une base 10, on n'aurait tout simplement pas de 7 ici : traduire un chiffre « basé » en tant que tel n'a tout simplement pas de sens mathématiquement parlant (bien que cela puisse en avoir informatiquement parlant comme on le verra plus loin). Il faut au contraire savoir combien de groupements de 2 peut on faire avec 765, en suivant un décompte binaire. Le moyen le plus rapide est d'effectuer des divisions successives par 2 en retenant la présence d'une partie fractionnée.

Ainsi

 

 

 

 

 

 

 

 

 

 

finalement   pour la partie entière. Mais comment représenter la partie fractionnée ?

La virgule idéale, fixe et flottante

modifier

Dans le meilleur des mondes la fraction est bien une subdivision d'une unité, où plus on monterait dans les rangées, plus la subdivision serait précise. À strictement parler on représenterait la partie fractionnaire suivant la même logique que la partie entière, c'est à dire qu'à chaque fois qu'on descend d'une rangée dans le nombre, on réduit la puissance.

Ainsi en base 10

  veut dire   donc  ,

  veut dire   donc  , ...

Et en base 2

  veut dire   donc  ,

  veut dire   donc  , ...

Ainsi pour convertir une partie fractionnée, on décompose la fraction en correspondances entre subdivisions décimales et binaires.

Correspondance entre nombres décimaux et leur valeur en binaire
Binaire 0,1 0,01 0,001 0,0001 0,00001 0,000001 ...
Équivalent décimal 0,5 0,25 0,125 0,0625 0,03125 0,015625 ...

Donc avec   pour trouver le correspondance binaire de   on y soustrait toutes les équivalences possibles en veillant à ne pas dépasser la valeur recherchée. Ainsi  .

Une autre manière est de multiplier récursivement la partie fractionnée par 2 en reportant la partie entière résultante dans le nombre binaire.

Ainsi

  • 0,432 × 2 = 0,864 -> 0
  • 0,864 × 2 = 1,728 -> 1
  • 0,728 × 2 = 1,459 -> 1
  • 0,459 × 2 = 0,918 -> 0
  • 0,918 × 2 = 1,836 -> 1
  • 0,836 × 2 = 1,672 -> 1
  • ...

  vaut donc en binaire approximativement 1011111101,011011... Il s'agit d'un nombre à fraction continue vu que ce que représente 765,432 en base 10 ne peut être représenté que par approximations successives en base 2.

On voit que pour la partie fractionnée des nombres, la notion de base est elle même biaisée. Par exemple si on voulait stocker la valeur réelle de   en base 10, il faudrait théoriquement un disque dur infini pour contenir tous les chiffres de la fraction récurrente (0,333333...). En base 3 la valeur réelle de   serait 0,1 et un simple Ruban perforé suffirait.

Pour éviter de générer des approximations qui n'existaient pas dans une base précédente, on adopte donc une solution plus pragmatique pour manipuler et stocker ce qui se trouve « après la virgule ». Dans un environnement binaire il est de toutes façons impossible de représenter autre chose qu'un 0 ou un 1, donc à fortiori les notions de virgule, de fraction, de signe et de tout autre symbole graphique que l'on grave sur du papier sont obligatoirement abstraits.

En informatique la virgule est en réalité une « étiquette » que l'on place dans une suite de chiffres finis dont les valeurs sont absolues.   valant 3,33333333333... devient donc 333333333333 (très exactement 12 « trois », ni un de plus, ni un de moins) et on déclare d'une manière ou d'une autre qu'après le premier chiffre se trouve le séparateur entre partie entière et fractionnée. La notion de subdivision disparait, on ne garde que les valeurs brutes de chaque chiffre composant le nombre, dans les limitations du matériel qui ne permettra jamais de stocker toutes les décimales d'un nombre irrationnel par exemple.

Dans le cas d'un nombre à « virgule fixe » la virgule peut soit ne simplement pas être stockée en mémoire. C'est au programmeur seul qu'incombe la tâche de déclarer la présence d'une virgule entre deux chiffres de ce nombre. C'est le rôle notamment de l'indicateur « V » utilisé en COBOL par exemple. Ou bien le nombre peut être enregistrée sous une forme dite décimale codée binaire (ou DCB), qui décompose le nombre binaires en chiffres et leur associe à chacun soit un quartet en DCB condensé, soit un octet en DCB étendu. Sachant que 4 bits sont nécessaires pour représenter tous les chiffres décimaux, cela veut dire qu'en étendu 4 bits vides seront consommés pour chaque chiffre stocké. Il est donc rapidement apparu la nécessité de trouver un moyen moins gourmand en ressources pour traiter les « nombres à virgules ».

Une solution fut d'utiliser le principe de nombre à « virgule flottante ». On y considère tous les chiffres comme un seul nombre appelé mantisse qui sera converti en binaire (dans sa valeur globale, et non chiffre par chiffre) et stocké dans un jeu de valeurs. La puissance à laquelle la base est élevée (grossièrement la position de la virgule), appelée exposant, est stockée dans un autre jeu de valeurs. Enfin un dernier jeu de valeurs indique le signe du nombre (un simple bit qui à 0 caractérise un nombre positif, à 1 un nombre négatif). L'ordonnancement de ces jeux de valeur varie selon la norme IBM ou IEEE (la première stocke le signe puis l'exposant puis la mantisse ; la deuxième stocke l'exposant puis le signe puis la mantisse).

Ce mécanisme de séparation décimale est majoritairement utilisé par les langages de programmation et permet de stocker des nombres allant de   à   environ. Les mots-clés real en PASCAL, float en C par exemple sont utilisés pour demander un stockage sous cette forme. Mais il faut néanmoins un processeur taillé sur mesure pour traiter les nombres à virgule flottante, et encore de nos jours il peut arriver qu'un constructeur en fasse l'économie et utilise le mécanisme à virgule fixe.

Les valeurs signées

modifier

Comme dit précédemment les deux seules choses concrètes que peut représenter un système informatique sont les deux états stables qu'on fait correspondre à 0 et 1. La notion de signe doit donc également être abstraite.

On l'a vu, avec les nombres flottants le signe est stocké dans un jeu de valeurs dédié. En DCB on utilise soit un quartet supplémentaire dans le cas du condensé, soit les 4 bits vides de l'octet le moins significatif dans le cas de l'étendue. Le signe est codé 0000 pour le signe + et 1111 pour le signe - (ou l'inverse), mais plus souvent 1011 pour le + et 1101 pour le - : 1011 et 1101 valant respectivement B et D en hexadécimal, sachant que les valeurs 2B et 2D codent respectivement les caractères + et - en ASCII.

Mais le système DCB est extrêmement gourmand en ressources, si bien que lorsqu'on veut représenter le signe d'un entier naturel sans aller jusqu'à utiliser les ressources demandées par un nombre à virgule flottante, on réserve un seul bit au sein du mot pour représenter le signe, et tous les autres bits pour stocker la valeur absolue du nombre. On utilise par convention le bit de poids le plus fort et on considère que si il vaut 0 le nombre est positif, sinon le nombre est négatif.

Ainsi avec un octet

0 0 0 0 0 0 1 0

vaut 2 tandis que

1 0 0 0 0 0 1 0

vaut -2

Pour utiliser ou non ce mécanisme les langages à typage statique utilisent des mots clés ; unsigned et signed pour le C par exemple.

À faire... 


correspondance entre mots clés.

  • représentation en complément
  • tableau récapitulatif entre répercussions concrètes de unsigned, double, int, float ... ?

Le système hexadécimal

modifier

Comme on l'a vu dans le tableau représentant les correspondances entre les chiffres décimaux et leur valeur en binaire toutes les combinaisons possibles de 4 bits ne sont pas présentes avec le système décimal (à savoir 1010, 1011, 1100, 1101, 1110 et 1111). C'est pour pallier ce manque que le système hexadécimal a été créé : il regroupe toutes les valeurs que peuvent prendre un quartet (groupe de 4 bits). Ainsi une plage de chiffres binaires découpées en blocs successifs de 4 bits peut devenir « lisible » tout en prenant moins de place à être représentée. Pour désigner les quartets manquants on a choisi arbitrairement les 6 premières lettres de l'alphabet.

Valeur binaire sur 4 bits Valeur décimale Valeur hexadécimale
0000 0 0
0001 1 1
0010 2 2
0011 3 3
0100 4 4
0101 5 5
0110 6 6
0111 7 7
1000 8 8
1001 9 9
1010 10 A
1011 11 B
1100 12 C
1101 13 D
1110 14 E
1111 15 F

Le système hexadécimal couvre donc toutes les combinaisons de 4 bits possible entre 0000 et 1111.

Astuces de conversion entre bases

modifier

Le nombre d'états en fonction du nombre de bits est calculé par la formule 2n.

Le bit le plus à droite est de poids faible. Le bit Le plus à gauche est celui de poids fort.

Nombre binaire 1 1 1 1 1 1 1 1
Poids 27 = 128 26 = 64 25 = 32 24 = 16 23 = 8 22 = 4 21 = 2 20 = 1

Pour convertir un nombre binaire en décimal, il suffit d'additionner chaque poids des bits à 1.

Exemple :

Nombre binaire 1 0 0 1 0 1 0 1
Poids 27 = 128 26 = 64 25 = 32 24 = 16 23 = 8 22 = 4 21 = 2 20 = 1

De la base 2 (binaire) vers la base 10 (décimal) :

10010101 -> 1 * 128 + 0 * 64 + 0 * 32 + 1 * 16 + 0 * 8 + 1 * 4 + 0 * 2 + 1 * 1
         ->   128                     +   16           +   4           +   1
         ->   149

De la base 2 (binaire) vers la base 16 (hexadécimal) :

1001 0101 -> 95

La conversion de la base binaire vers la base hexadécimale est plus facile que vers la base décimale. C'est la raison pour laquelle la base hexadécimale est beaucoup plus utilisée que les autres.

Il est également possible d'utiliser la base 8 (23) c'est à dire la base octale, où les bits sont regroupés par 3 ; ou toute autre base puissance de 2 (base 64 ou 128 pour encoder les fichiers binaires dans un texte, base 32, ...).

Représentation des données

modifier

Cependant les ordinateurs ne sont pas de simples calculatrices : ils peuvent afficher du texte, des images, des animations... autant de types de données qui demandent des codes de conversion entre leur existence binaire et leur restitution à l'écran.

Au contraire des nombres qui peuvent être convertis entres différentes bases de manière équivalente et absolue (du moins en théorie), les informations non numériques demandent l'usage d'un code de communication qui fixe arbitrairement les correspondances entres les informations et leur équivalent numérique. Pour que l'émetteur et le récepteur puissent se comprendre, il est nécessaire que chacun utilise le même code : la nécessité de standardisation est donc primordiale ici. Il y a de nombreux exemples de standards de communication tout au long de l'histoire, du Morse au code Popham, du code Baudot au code Fieldata. Nous ne nous arrêterons que sur ceux qui sont effectivement utilisés dans le cadre de l'informatique, et plus précisément ceux qui sont rencontrés par les programmeurs.

L'esprit humain retient mieux des bouts de textes que des suites de chiffres, si bien que même dans les endroits les plus arides de l'informatique on en a tendance à en mettre partout : dans les codes source des programmes pour les rendre plus lisibles, dans les bulles d'aide, les interfaces... L'ordinateur est également utilisé pour contenir des documents écrits, qu'on a rédigé au moyen d'un clavier ou numérisé avec un scanner et un logiciel ocr. Une fois numérisée il devient possible de modifier le texte, de l'imprimer, de le dupliquer à l'infini...

Pour restituer un texte, la quasi-totalité des système informatiques utilisent le standard ASCII, ou un dérivé de celui-ci. Constitué en 1963 puis complété en 1967 il permet de coder sur 7 bits l'alphabet latin sans les diacritiques, en majuscules et en minuscules, les 10 chiffres du système décimal, des caractères de ponctuation, des symboles mathématiques et financiers ($%&), et des codes de contrôle destinées à superviser la communication.

ISO 646 et ISO 8859

modifier

L'ascii se trouva rapidement limité pour représenter les caractères accentués et autres symboles non américains. L'ISO 646 fut la première tentative pour augmenter le nombre de caractères codables mais elle posa des problèmes d'incompatibilité car le système restait basé sur 7 bits, ne créant pas de nouveaux codes mais réassignant ceux existants, les codes de contrôle servant à définir quel jeu de caractères s'appliquait à tel morceau de texte. Mais ces codes étaient souvent omis, ou bien les traitements de texte n'étaient pas conçus pour les prendre en charge si bien qu'un programmeur non américain était dès lors souvent confronté à :

ä aÄiÜ='Ön'; ü

au lieu de

{ a[i]='\n'; }

L'autre solution adoptée fut d'utiliser un bit supplémentaire afin d'obtenir 128 combinaisons supplémentaires (l'ascii n'utilise que 7 bits). La norme ISO 8859 propose 16 jeux de caractères différents couvrant chacun un ensemble linguistique plus ou moins local : l'ISO 8859-1 pour les langues européennes occidentales, l'ISO 8859-5 pour le cyrillique, l'ISO 8859-11 pour le thaï... l'ISO 8859-15 ajoute le support du symbole Euro (€) et de quelques diacritiques manquantes du français (Œ, œ, et Ÿ).

Cependant devant l'extension mondiale de l'informatique et la limitation d'un système à 8 bits qui ne permet pas d'utiliser par exemple plusieurs alphabets différents dans un même document, l'ISO travaille depuis 1988 à l'élaboration d'un code universel : l'Unicode.

L'Unicode (ISO 10646)

modifier

L'Unicode définit actuellement plus de 120 000 caractères en utilisant jusqu'à 31 bits pour chacun.

L'UTF-8 (Unicode Transformation Format - 8 bits) permet d'encoder les caractères par groupe de 8 bits (un octet). Le nombre de bits employé pour chaque caractère est fonction de son numéro. Il existe 6 plages, la première occupant 1 octet, la dernière en utilisant 6. La première plage se reconnaît à ce que le premier bit de l'octet est positionné à 0, les 7 bits suivants respectent la norme ASCII. Un caractère Unicode de cette plage est donc de la forme 0xxxxxxx et se trouve entièrement compatible avec un système ASCII. Les plages suivantes se reconnaissant à ce que le bit de poids fort de chaque octet est positionné à 1, les bits de poids fort du premier octet permettent de connaître la plage (110xxxxx pour la plage à deux octets, 1110xxxx pour celle à 3, 11110xxx pour 4, 111110xx pour 5 et 1111110x pour 6), et les deux bits de poids fort des octets suivant sont systématiquement positionnés à 10 afin d'indiquer leur appartenance à une suite d'octets Unicode. Un caractère de la deuxième plage est donc de la forme suivante : 110xxxxx 10xxxxxx ; et propose donc 11 bits utiles, ce qui permet   caractères différents.

Les plages unicode
Plage Octets en UTF-8 Nombre de caractères codés
1 0xxxxxxx 128
2 110xxxxx 10xxxxxx  2 048
3 1110xxxx 10xxxxxx 10xxxxxx  65 536
4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx  2 097 152
5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx  67 108 864
6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx  2 147 483 648
À faire... 

rapide topo sur l'incompatibilité iso8859-utf souvent rencontrée par un programmeur

L'image est une ressource beaucoup moins souple que le texte.

À faire... 

matriciel bitmap, matriciel compression sans perte, compression avec perte, vectoriel (sémantique), feuilles de style (décoration), bibliothèques graphiques (gui), bibliothèques 3D (openGL, Direct3D)...

À faire... 

restitution : écran de console (caractères ascii), écran vga (et suivants), prise en charge de la couleur (rvb, tsl, cmjn...), [1], hologrammes ?...

Le son est représenté par un signal analogique. Pour le numériser, on l'échantillonne :

  • Échantillonnage temporel : on prend la mesure du signal à intervalle régulier (fréquence d'échantillonnage),
  • Échantillonnage numérique : la valeur analogique est convertie en valeur numérique sur un nombre limité de bits.

Le signal est enregistré sous forme numérique selon deux principales méthodes :

  • Méthode temporelle : chaque échantillon temporel est enregistré (formats wave, au, ...),
  • Méthode fréquentielle : on décompose le signal par transformée de Fourier (formats MP3, ...).

Certains changements de niveau sonore ne sont pas perceptibles par l'oreille humaine. Les codages µ-Law et A-Law exploitent cette propriété pour encoder les niveaux en utilisant moins de bits.

À faire... 

analogique -> numérique ; types de compression ; ...?

Animation

modifier
À faire... 

compression video (mpeg, ogg theora, ...) fonctionnement par aplats et keyframes...

À faire... 

animation "matérielle" (while(1){...;wait()}) ; animation standardisée (gif, SMIL, ...)

À faire... 

physique newtonienne : havoc, newton...

Sémantique

modifier
À faire... 

html, tex, web sémantique en général [2], [3]...


Paradigmes

modifier

Un paradigme en programmation est la manière dont le programmeur conçoit son ouvrage pour que celui-ci corresponde à ses besoins. Un programme peut être conçu comme une simple suite d'instructions où le but est d'effectuer un traitement sur une ressource donnée en fonction d'un environnement donné. On parle alors de programmation impérative car le programme est une suite d'instructions précises fournies par l'auteur qui manipulent des objets simples comme des chiffres, des images ou des caractères.

Cependant les besoins de l'informatique ont amené la nécessité de pouvoir agir sur des objets plus complexes, comme le pointeur de la souris présente dans l'interface graphique des systèmes d'exploitation tels que Windows, MacOS ou Linux et de pouvoir par exemple agir dessus depuis plusieurs sources dans le cas d'un réseau ou d'agir dessus d'une manière qui dépende davantage de l'environnement crée par l'utilisateur lorsqu'il déplace la souris, appuie sur une touche du clavier… que de la succession d'évènements planifiées par le programmeur.

Ainsi ces différentes manières d'appréhender la programmation influent directement sur la manière dont la discipline est enseignée, et sur la manière dont les programmes sont conçus et fabriqués.

Code source

modifier

Le code source d'un programme est ce que le programmeur rédige avec ses propres moyens ou avec l'assistance d'un éditeur de programme. Il est soit compilé, soit interprété. Pour cette raison, le code doit être rédigé dans un langage qui soit à la fois compatible avec le compilateur ou l'interpréteur (respecter la syntaxe), mais également compréhensible par un être humain (lisibilité, présentation, commentaires), en utilisant les caractères familiers (lettres, chiffres, ponctuation) plutôt que des caractères étendus (caractères de contrôles, caractères spéciaux).

Technologies de langages

modifier

Il existe de très nombreux langages de programmation différents qui obéissent chacun à une syntaxe et à une logique propres. Certains langages sont conçus pour être accessibles et pédagogiques, d'autres pour être efficaces et fiables, d'autres pour être rapides à l'exécution. Selon le programme que l'on souhaite réaliser, le choix du langage peut être un critère décisif.

Langage machine

modifier

Il s'agit du niveau d'abstraction le plus bas que peut appréhender le programmeur, si on excepte les premiers ordinateurs où un groupe de personnes salariées modifiaient elles-mêmes le contexte électronique de l'ordinateur selon les instructions qu'on leur communiquait. Il s'agit d'une suite de bits? que comprend le processeur?. Par exemple l'équivalent binaire de la suite de chiffres telle que 12 003 peut être comprise par le processeur comme la douzième instruction parmi les actions préimplantées par le constructeur que peut effectuer le processeur appliquée à l'élément situé à l'adresse numéro 3 du support visé par le processeur. De fait chaque instruction en langage machine correspond à une et une seule action du processeur et de fait l'augmentation de l'abstraction des langages de programmation correspond à l'augmentation du nombre d'actions du processeur correspondant à une instruction.

Langages assemblés

modifier

Ce langage est une traduction mot à mot du langage machine en une suite d'instructions dont le premier mot est un mot mnémotechnique de l'opération effectuée, suivi des opérandes, c'est à dire des paramètres de l'opération. Ce langage est donc également spécifique à un modèle de processeur.

La traduction est assurée par un programme d'assemblage appelé un assembleur?.

Les langages assembleurs les plus évolués ont des fonctionnalités supplémentaires comme l'utilisation de labels pour les sauts, les adresses de variables, ce qui évite de calculer l'adresse exacte à utiliser ; l'utilisation de pseudo-instructions traduits en une séquence d'instructions équivalente, encore appelées macros? ; ou encore la définition de sections de code, de sections de données, afin d'organiser le programme en blocs spécialisés.

Langages de haut niveau

modifier

Les langages de haut niveau sont soit des langages compilés, soit des langages interprétés. Ils permettent de s'abstraire davantage voire complètement de l'implémentation bas niveau et de programmer sans trop se soucier de l'architecture cible. Le code source produit ne peut être interprété directement par la machine qui a besoin d'un compilateur le traduisant en langage compréhensible par la machine, ou d'un interpréteur exécutant les instructions directement.

Différentes générations de langages haut niveau ont été créées :

  • Les langages impératifs (C, Pascal, Ada, ...)
  • Les langages orientés objet (C++, Java, Delphi, C#.Net, ...)

Technologies d'exécution

modifier

Selon le langage, le code source rédigé par le programmeur peut être exécuté de différentes manières par l'ordinateur.

Langages interprétés

modifier

Le code source d'un langage interprété est traduit en langage machine de manière éphémère lors de son exécution par un programme interpréteur qui lit le code source instruction après instruction et effectue la conversion à la volée. Un langage interprété est donc portable sur divers types de plateformes à condition qu'elles possèdent un interpréteur pour ce langage qui sache convertir le code source en langage machine compatible avec la plateforme.

Certains langages interprétés modernes (Java, C#, et les autres langages .Net) possèdent un semi-compilateur traduisant le programme en un langage plus proche des machines en général. C'est-à-dire un langage pour une machine virtuelle dont l'interprétation par une machine concrète demande moins d'effort que l'interprétation directe.

Langages semi-interprétés

modifier

Également appelés langages semi-compilés, ils se caractérisent par une étape de compilation rapide du code source produisant du bytecode qui est ensuite exécuté par l'interpréteur de manière plus rapide que si il avait à interpréter le code source directement. Ces langages autorisent des possibilités inédites comme la modification du code source à la volée lors de l'exécution du programme et généralement une très grande abstraction des contraintes imputées à la programmation système, en pâtissant de performances moindres en terme de vitesse par rapport aux langages compilés. Ce sont les langages apparus le plus récemment.

Langages compilés

modifier

Un langage compilé définit une syntaxe qui lui est propre et indépendante du processeur. Cette syntaxe peut permettre l'utilisation d'instructions plus complexes, de structures de code (condition, boucle), de structures de données complexes (tableaux, structures, listes, …) et peut fournir des types de données plus évolués (chaînes de caractères, dates, ...).

Un programme dans un tel langage nécessite une phase de compilation pour valider la syntaxe et effectuer la traduction en langage machine. Cette phase est assurée par un compilateur qui traduit le programme pour un ou plusieurs modèles de processeur particuliers.


Commentaires

Un commentaire est un texte ajouté au code source d'un programme servant à décrire le code source, facilitant sa compréhension par les humains. Il est donc séparé du reste du code grâce à une syntaxe particulière, ce qui fait qu'en général, le commentaire est ignoré par le compilateur? ou l'interpréteur? du langage concerné.

Pourquoi ajouter des commentaires ?

modifier

Ajouter des commentaires à un programme permet de décrire ce que fait le code, en utilisant un langage naturel. Il est important d'ajouter des commentaires pour les raisons suivantes :

Expliquer le rôle d'une fonction
Utiliser une fonction est compliqué si on ne sait pas ce qu'elle fait, ce qu'elle retourne. Une explication permet de savoir comment l'utiliser.
Expliquer le fonctionnement d'un algorithme complexe
Le code source des algorithmes les plus complexes ne suffit pas à en comprendre le fonctionnement. Une description synthétique permet de le modifier pour l'adapter à un autre projet, ou pour le corriger en cas de problèmes.
Justifier certains choix techniques
Un code source est souvent repris ultérieurement (correction, réutilisation). Si certains choix ne sont pas justifiés par un commentaire explicatif, ils pourront être remis en cause par le développeur.
Lister les contextes d'appel à une fonction
Un commentaire expliquant quand la fonction est appelée permet de comprendre son rôle et les circonstances de déclenchement de l'appel à la fonction.

 

Selon Martin Fowler, l'ajout de commentaire peut aussi être le symptôme d'un code de mauvaise qualité[1], notamment parce qu'il ne ferait pas appel à des fonctions bien découpées et bien nommées.

Syntaxe

modifier

La syntaxe utilisée dépend du langage de programmation, ou du format de données. Dans les exemples qui suivent, l’élément de syntaxe caractéristique du commentaire est en vert.

Bloc de commentaire

modifier

Un bloc de commentaire commence par une séquence de caractères (en vert ci-dessous), et se termine par une autre séquence. Le commentaire peut donc s'étaler sur plusieurs lignes.

<!-- Un commentaire ici -->
/* Un commentaire ici */
{ Un commentaire ici }
ou
(* Un commentaire ici *)

Ligne de commentaire

modifier

Une ligne de commentaire commence par une séquence de caractères (en vert ci-dessous), et se termine implicitement à la fin de la ligne de code. Si le commentaire s'étale sur plusieurs lignes, il faut répéter la séquence au début de chaque ligne.

// Un commentaire ici
  • Basic, Batch (pour DOS) :
REM Un commentaire ici
  • Shell unix, PHP, Python, fichier de configuration (.ini, .cfg) :
# Un commentaire ici
  • Fichier de configuration (.ini, .cfg) :
; Un commentaire ici
-- Un commentaire ici

Autre utilisation

modifier

Certains langages utilisent une syntaxe particulière de commentaires interprétée par une ligne de commande spéciale pour générer une documentation :

La documentation générée est au format HTML, utilisant la syntaxe suivante :

/**
   Décrire ici la classe ou la méthode
   dont la déclaration suit ce commentaire
   en utilisant la syntaxe HTML
   @tag valeur
*/

La documentation générée est au format XML, utilisant l'une des deux syntaxes suivantes :

/**
   Décrire ici la classe ou la méthode
   dont la déclaration suit ce commentaire
   <tag>valeur</tag>
*/
/// Décrire ici la classe ou la méthode
/// dont la déclaration suit ce commentaire
/// <tag>valeur</tag>

La phpdoc est interprétée pour générer une documentation automatique, par les IDE pour l'autocomplétion, et par les analyseurs de code statique chargés de garantir la qualité du code. Elle se distingue des commentaires de base par l'ajout d'une deuxième étoile au début d'un commentaire de bloc, puis d'un arobase avant le mot clé :

    /** @var int|null */
    private $id;

Références

modifier


Instructions

Une instruction est une opération de base du processeur ou d'un langage de programmation, une opération que le programmeur demande à la machine d'exécuter. Une instruction est une opération élémentaire, c'est à dire l'ordre le plus basique que peut comprendre un ordinateur. Fondamentalement, elle comporte deux éléments : l'action que le processeur va effectuer et les éléments sur laquelle l'action va être effectuée. Par exemple une instruction demandant l'addition des nombres a et b fera intervenir l'opérateur d'addition et les valeurs identifiées par les noms a et b.

Les instructions typiques

modifier

Les sections suivantes présentent les instructions typiques de la plupart des langages de programmation.

Déclaration

modifier

La déclaration permet à un compilateur ou interpréteur de connaitre à quoi correspond un identifiant. En général on déclare :

  • les variables : en général un type précis est associé à l'identifiant. Exemple :
A:ENTIER

EN BASIC : Dim A as String * 5 [qui donnera affecte une zone de mémoire à la variable A pour une chaine de caractère comportant 5 caractères]

  • les fonctions : l'identifiant est associé à une fonction retournant un résultat d'un type spécifié, et prenant comme arguments ceux qui sont spécifiés. Exemple :
FONCTION MAX(A:ENTIER, B:ENTIER) RETOURNE ENTIER
  • les classes : en programmation objet, une classe définit un nouveau type de données auquel peut s'appliquer un certain nombre de fonctions (appelées méthodes). Exemple :
CLASSE VEHICULE
  • d'autres entités qui dépendent du langage de programmation utilisé.

Certains langage n'ont pas besoin de déclarer les variables au préalable. D'autres ne définissent pas le type des variables. Dans ce cas là, le type est celui de la valeur à laquelle on l'affecte.

Affectation

modifier

L'instruction d'affectation permet de stocker le résultat d'une expression ou la valeur d'une constante dans une variable.

Exemples :

A ← 5
A ← A + 2

Expressions

modifier

Une expression contrairement à une instruction peut être affectée. Typiquement int a = <TEST> ? <VALEUR A> : <VALEUR B>; est légal mais int a = if <TEST> <VALEUR A> else <VALEUR B>; n'est pas légal car if est une instruction et non une expression même si les deux construction seraient fondamentalement identiques autrement.

Arithmétique

modifier

Une expression arithmétique fait appel au cœur logique du processeur.

ADD A, B

Comparaison

modifier

Simplification de l'opération de soustraction. si on soustrait deux opérandes, selon que le résultat soit inférieur, égal ou supérieur à zéro, on peut connaitre la différence entre deux opérandes.

CMP A, B

Appel de fonction

modifier
CALL

Bloc d'instruction

modifier

Plusieurs instructions peuvent être regroupées en une seule en les encadrant par des accolades, ou par deux mots-clés du langage de programmation utilisé.

Exemple :

DEBUT
    TMP ← B
    B ← A
    A ← TMP
FIN

Le bloc tout entier est alors considéré comme une seule instruction et peut être utilisé pour définir une fonction, ou l'utiliser avec une instruction de contrôle d'exécution.

Contrôle d'exécution

modifier

Les instructions contrôlant l'ordre d'exécution sont les suivantes :

  • La condition : l'instruction qui suit n'est exécutée que si une condition est remplie. Exemple :
SI A < 0 ALORS A ← 0
On peut ajouter une instruction à exécuter dans le cas contraire :
SINON A ← 1
  • Une boucle permet de répéter un certain nombre de fois une même instruction. Exemple :
POUR I DE 1 À 10 FAIRE
    A ← A + I
FIN_POUR

Ordre d'exécution des instructions

modifier

Sauf instruction contraire, l'ordre d'exécution des instructions est celui de la lecture du code source : de la gauche vers la droite, de haut en bas.

Exemple :

A ← 5 ;    B ← A + 2 ;
A ← 6 ;    B ← A + 4 ;

L'ordre d'exécution des instructions de cet exemple est le suivant :

  1. A ← 5 ; La variable A contient la valeur 5.
  2. B ← A + 2 ; La variable B contient la valeur 7 (5+2).
  3. A ← 6 ; La variable A contient maintenant la valeur 6.
  4. B ← A + 4 ; La variable B contient maintenant la valeur 10 (6+4).

Les instructions qui utilisent un ordre d'exécution différent sont des instructions de contrôle d'exécution.


Variables

À faire... 


  1. Les typages dynamiques
  2. ...


La variable est un concept important en programmation informatique. Intuitivement, il s'agit d'un nom qui se réfère à une chose. Informatiquement, c'est une référence à une adresse mémoire.

Il s'agit d'une entité créée dans l'ordinateur à laquelle on donne un nom et qu'on utilise en évoquant ce nom dans le code source du programme, capable de contenir des informations dont la valeur peut varier au cours du temps selon les manipulations que le programme lui fait subir.

Ces informations peuvent être de types très différents, ainsi lorsqu'une variable contient le nom d'une ville, une autre pourra par exemple contenir un tableau statistique, ou bien simplement le résultat d'un calcul effectué au sein du programme. Pour la définition exacte de la variable, se reporter à la section détaillant les mécanismes des variables au niveau système.

Usage des variables

modifier

Concrètement, lorsqu'on veut par exemple calculer l'aire d'un rectangle à partir de sa longueur et sa largeur, on crée un programme qui demande d'abord la création de deux variables qu'on baptise longueur et largeur en précisant l'espace qu'ils vont occuper dans l'ordinateur au moyen de mots clés universels comme int ou float (voyez le chapitre sur les types de données pour de plus amples détails). Après avoir créé les variables, on leur attribue les valeurs de longueur et largeur souhaitées, puis on lance un calcul effectuant la multiplication entre les deux variables. On peut ensuite stocker le résultat correspondant de fait à l'aire du rectangle dans une des deux premières variables, mais il est plus propre de créer une troisième variable aire dédiée à contenir la valeur de l'opération effectuée par l'ordinateur. Ce n'est que le goût, la nécessité ou la convention de codage du programmeur (ou de l'équipe de développement) qui détermine l'architecture finale du programme.

Niveau système

modifier

Au niveau système , une variable occupe un certain nombre de bits [1] en mémoire. Elle occupe donc une zone dont l'adresse correspond à celui du premier mot stockant la valeur qu'elle contient.

Exemple avec une variable de type entier sur 32 bits (soit 4 octets) :

  • NOMBRE: ENTIER = 12345
  • La valeur correspondante en hexadécimal sur 32 bits est : 00003039h
  • En supposant que la variable occupe les emplacements (adresses) 100, 101, 102 et 103, ceux-ci contenant chacun 1 octet, contiennent les valeurs suivantes :
    • sur une machine dont le processeur stocke d'abord l'octet de poids faible (little endian byte order en anglais) :
Adresse 100 101 102 103
Contenu 39h 30h 00h 00h
  • sur une machine dont le processeur stocke d'abord l'octet de poids fort (big endian byte order en anglais) :
Adresse 100 101 102 103
Contenu 00h 00h 30h 39h

L'emplacement de cette variable est déterminée :

  • À la compilation du programme, en général, relativement au début de la section de données allouée par le système, c'est à dire que le compilateur détermine un décalage (offset) ;
  • À l'exécution de l'application, lorsque le système alloue la section de données correspondante (en lui attribuant une adresse absolue en mémoire).

L'utilisation conjointe de ces deux informations donne l'adresse absolue de la variable en mémoire :

adresse variable = adresse absolue de la zone de données + décalage

Cette adresse est utilisée lors des opérations de lecture et d'écriture.

La machine n'a pas besoin d'enregistrer le type de la variable. Le type n'est utilisé que pour déterminer comment la variable peut être manipulée par les instructions (lecture, écriture, calculs, nombre de bits occupés en mémoire). Cependant certains langages interprétés ou des langages de programmation permettant la réflexion enregistre le type comme information supplémentaire pour d'autres opérations (vérification, duplication, instanciation, ...).

Lors de l'exécution de l'application, la zone de données n'est pas toujours initialisée à zéro. En effet, cet emplacement a pu être allouée antérieurement à une autre application, et contient donc des valeurs utilisées par celle-ci. Cependant, pour des raisons évidentes de sécurité[2], les systèmes modernes initialisent à zéro les zones allouées aux applications.

En langage machine, accéder à une variable correspond à écrire l'adresse de la variable sur le bus d'adresse, et lire ou écrire sur le bus de données la valeur correspondante.

La valeur est toujours binaire à l'intérieur de la machine : stockage, opérations. La conversion en d'autres bases (octal, décimal, hexadécimal) n'est faite que lors de la présentation de la valeur à l'utilisateur, ou lors de sa saisie par l'utilisateur.

Les variables sont utilisées pour :

  • stocker des valeurs, des résultats dans le temps, pour les utiliser ultérieurement,
  • transmettre des valeurs à des fonctions,
  • stocker des résultats intermédiaires dans une séquence de calculs, notamment lorsque ce résultat est utilisé plusieurs fois dans une expression.
  1. Un bit peut valoir 0 ou 1, et correspond à un état électrique (niveau haut / niveau bas, circuit ouvert / circuit fermé). Les bits sont généralement regroupés en mots, on parle d'octets lorsqu'un mot regroupe 8 bits.
  2. De nombreux programmes espions ont utilisé cette fonctionnalité pour récupérer des informations sensibles notamment des mots de passe.


Types

Dans la plupart des langages de programmation il est possible d'attribuer arbitrairement aux variables des types pour – entre autres – déterminer la nature des données qu'elle peut contenir et la manière dont elles sont enregistrées et traitées par le système. Concrètement le type d'un élément influe sur la taille que le compilateur ou l'interpréteur lui allouera en mémoire ; et les opérations qui ne devraient pas être permises si la syntaxe du langage était respectée. Il est par exemple rare qu'un vérificateur d'erreurs ne se manifeste pas lorsqu'on tente de multiplier un « nombre » avec une « lettre ». Si à la base la « lettre » et le « nombre » sont tous deux une « succession de 0 et de 1 », en pratique ce à quoi on fait correspondre ces « successions de 0 et de 1 » rend une telle opération vide de sens.

Selon le degré d'abstraction du langage, il peut être soit indispensable de préciser le type de la variable lors de sa création, ou bien cela peut ne pas être nécessaire, le langage déterminant automatiquement le type de la variable à sa création, et le modifiant de manière dynamique lorsque la valeur contenue par la variable dépasse la quantité de mémoire correspondant au type précédent.

À faire... 

Plan proposé :


Types de données simples

modifier

Un type simple est une simple valeur dont le stockage se fait le plus souvent sur un nombre fixe d'octets. La plupart sont des valeurs numériques. Dans un langage particulier, chaque type peut avoir des variantes qui diffère par la gestion du signe (présentation), les limites autorisées (selon la taille occupé par une valeur de ce type).

L'entier est le type numérique le plus simple : il stocke une valeur entière. Par exemple : 1, 2, 145, 36000720.

Les bornes de valeurs acceptées par ce type dépend de la taille attribué par le langage utilisé, et par la présence d'un signe ou non.

Exemples :

  • Un entier de 8 bits non signé accepte donc   (soit 256) valeurs comprises entre 0 et 255 inclus,
  • Un entier de 32 bits signé accepte   (soit 4294967296) valeurs comprises entre -2147483648 et +2147483647 inclus.

La gestion des nombres signés nécessite de définir comment gérer les nombres négatifs. Plusieurs possibilités ont été utilisées :

Représentation « signe + magnitude »

modifier

Sur le nombre de bits qu'occupe le nombre entier, un bit (généralement le premier ou le dernier, selon l'implémentation) est assigné au signe. Le 0 est utilisé pour un nombre positif, le 1 pour un nombre négatif (ou vice-versa).

Exemples pour des nombres signés sur 8 bits, on peut avoir la représentation suivante :

  • +5 => 0 0000101
  • -5 => 1 0000101

Le zéro n'ayant pas de signe, son bit de signe peut valoir indifféremment 0 ou 1. Il a donc deux représentations possibles :

  • 0 => 0 0000000
  • 0 => 1 0000000

On peut noter que certains langages permettent de distinguer ces deux valeurs.

Représentation en complément à 1

modifier

Le bit de signe est le bit le plus significatif, et les autres bits représentent :

  • la valeur absolue, si le nombre est positif,
  • le complément à 1 de la valeur absolue, si le nombre est négatif (c'est à dire 0=>1 et 1=>0).

Exemples pour des nombres signés sur 8 bits :

  • +5 => 0 0000101
  • -5 => 1 1111010

Le zéro n'étant ni négatif, ni positif, il possède également deux représentations possibles :

  • 0 => 0 0000000
  • 0 => 1 1111111

Représentation en complément à 2

modifier

Cette représentation ressemble à la précédente.

Le bit de signe est le bit le plus significatif, et les autres bits représentent :

  • la valeur absolue, si le nombre est positif,
  • le complément à 2 de la valeur absolue, si le nombre est négatif. C'est à dire qu'il s'agit du complément à 1, auquel on ajoute 1.

Exemples pour des nombres signés sur 8 bits :

  • +5 => 0 0000101
  • -5 => 1 1111011 (1 1111010 + 1)

Le zéro ne possède qu'une seule représentation :

  • 0 => 0 0000000 (soit 1 1111111 + 1, sans la retenue)

Cette représentation est la plus répandue actuellement, car elle facilite le traitement des additions et soustractions.

Exemple : -5 + 7

-5 =>   1 1111011
+7 =>   0 0000111
 =   ------------
     (1)0 0000010
        0 0000010 = +2

Nombre à virgule fixe

modifier

Nombre à virgule flottante

modifier

Caractère

modifier

Il faut ici faire la distinction entre le caractère (par exemple « a latin minuscule ») et sa représentation graphique (le « a » que vous voyez sur votre écran). Un caractère est le plus souvent représenté par une valeur numérique, où chaque valeur est associée à un caractère comme « a latin minuscule », « symbole mathématique de l'addition », « apostrophe ». La gestion des caractères en informatique a une histoire très longue. En effet, il est nécessaire de décider de la liste des caractères qui seront disponibles. Or, cette liste peut être différente suivant les pays (pensez aux langues arabes, asiatiques, au russe...) et, de fait, un grand nombre de codages de caractères ont été créés, avec chacun sa propre liste, et où un même caractère pouvait être associé à une valeur numérique différente suivant le codage (voir l'article Codage de caractères sur Wikipédia).

En pratique, l'encodage ASCII (et ses dérivés) est très courant, et tend à être remplacé très avantageusement par l'Unicode.

Exemple : En ASCII, le caractère espace est le numéro 32, en EBCDIC, il s'agit du caractère numéro 64.

Dans les langages où un caractère est effectivement représenté par un nombre, celui-ci peut être utilisé dans des calculs.

Booléen

modifier

Un booléen ne peut prendre que deux valeurs : vrai ou faux. Ce type est utilisé lorsqu'une expression logique est testée.

Types de données complexes

modifier

Les types de données complexes sont des types composés de plusieurs types plus élémentaires et qui possèdent une architecture spécifique autorisant des traitements dédiés à leur type. Ces traitement autorisés sont propres au langage et il est rare qu'un langage puisse gérer tous les types décrits ci-dessous à la fois.

Les types de données séquentielles comme les listes ou les matrices se caractérisent par leur capacité à contenir des variables rangées dans une suite de "casiers" qui peuvent être accédés par une boucle parcourant tous les indices? de la séquence.

D'autres types complexes permettent de référer à leur contenu non pas par un indice numérique, mais par une clé qui peut être de n'importe quel type. C'est le cas principalement des dictionnaires.

Enumération

modifier

Une énumération définit une liste de noms explicites, limitant les valeurs possibles. Par exemple : oui, non. Certains langages de programmation peuvent également associer une valeur d'un autre type à chaque nom (exemple : non = 0, oui = 1).

Chaine de caractères

modifier

Une chaîne de caractères est une séquence ordonnée de caractères.

Tableau

modifier

Un tableau contient une série d'éléments d'un certain type. Dans la plupart des langages, ce tableau est de taille fixe. Cette taille peut être déclarée en même temps que la variable (allocation statique) ou à l'allocation mémoire, si la variable est un pointeur vers un tableau (allocation dynamique).

Certains langages de programmation n'ont pas de type spécifique pour les chaînes de caractères (le langage C, par exemple) et utilise alors un tableau de caractères.

Une liste contient une série d'éléments d'un certain type. Le nombre d'éléments qu'elle contient est variable.

Une liste simplement chaînée est représenté par un pointeur vers une structure contenant :

  • l'élément de la liste,
  • un pointeur vers la structure suivante.

Ce genre de liste ne possède donc qu'un seul sens de parcours.

Une liste doublement chaînée pointe vers une structure contenant un pointeur supplémentaire vers la structure précédente. Ce genre de liste possède donc deux sens de parcours.

Matrice

modifier

N-uplet

modifier

Dictionnaire

modifier

Expressions

Une expression est un segment de code qui exécute une opération arithmétique puis retourne une valeur correspondant au résultat de l'opération. Par exemple, la ligne suivante est une expression effectuant une addition :

3 + 4

L'expression   retourne la valeur 7 lorsqu'elle est évaluée.

Composition

modifier

L'expression   se compose de deux parties : les opérandes (3 et 4), qui sont les valeurs auxquelles l'opération s'applique, et l'opérateur (+), qui spécifie l'opération à effectuer. Selon le type de notation en vigueur, l'opérateur peut être soit préfixée (+ 3 4) dans le cadre de la notation polonaise? notamment, infixée (3 + 4) comme on a l'habitude de le voir ou post-fixée (3 4 +) comme dans le cadre de la notation polonaise inverse?. Les notations polonaises permettent notamment de s'affranchir des parenthèses mais sont moins accessibles aux débutants.

Exploitation

modifier

Pour exploiter les expressions exécutées par le système, le moyen le plus commode est d'utiliser des variables auxquelles on affecte? les valeurs retournées par les expressions. Pour affecter le résultat d'une expression à une variable, la syntaxe varie selon les langages. Ainsi pour affecter le résultat de l'expression   à une variable a, on peut utiliser la syntaxe a := 3 + 4 en Pascal ou en Ada ; a = 3 + 4 en C et dans tous les langages qui en dérivent ou 3 + 4 → a en Basic Casio par exemple

Expressions avec des opérandes variables

modifier

Il est également possible grace aux variables d'effectuer des calculs à partir d'opérandes qui ne soient pas des valeurs constantes telles que 3 ou 4. La ligne suivante par exemple est une expression effectuant également une addition :

variable1 + variable2

L'expression précédente effectue l'addition entre la valeur stockée par la première variable et celle "contenue" dans la deuxième variable. Ainsi le programme devient non seulement capable d'effectuer une addition entre 3 et 4 si les valeurs des variables avaient respectivement été 3 et 4, mais également toutes les additions possibles et imaginables selon la nature des variables et des valeurs que le programme leur a assignées. Ainsi, le programme devient capable de produire un résultat différent selon l'état des variables utilisées dans le programme, et devient même capable de réagir à l'environnement extérieur à l'ordinateur lorsque les variables sont reliées à un dispositif d'entrée comme le clavier ou la souris.

Influence du typage

modifier

Selon le type des variables qu'on utilise lors de l'exécution d'une opération arithmétique, le résultat peut sensiblement varier, voire produire des incohérences en cas de types incompatibles : il apparait en effet improbable que diviser une variable contenant le mot "arbre" avec la valeur de   produise un résultat probant. De même, diviser deux nombres entraîne souvent le retour d'une valeur décimale, par exemple la division de 3 par 2. Or si on a affecté la valeur de retour de cette expression à une variable Int, cette valeur est tronquée à l'entier immédiatement inférieur, voire arrondie dans les langages plus évoluées au nombre entier le plus proche. Ainsi, il est préférable de typer en float une variable destinée à accueillir le résultat d'une division, plus généralement, de typer les variables impliquées dans des opérations arithmétiques de manière avisée et apte à répondre à tous les contextes auxquels le programme peut les soumettre.

Niveau système

modifier

Le processeur effectue le calcul des expressions, opération par opération. À son niveau, tout est ramené à des nombres, représentés numériquement en binaire (base 2) sur un nombre fixe de bits, chacun valant 0 ou 1. Le circuit du processeur comporte plusieurs bus de transport des données (1 bit par piste, 2 états : soit le courant passe, soit il ne passe pas) pour faire circuler les valeurs numériques entre les registres, les bus externes connectés aux autres circuits (notamment la mémoire) et l'unité arithmétique et logique qui effectue les opérations demandées.

Les transistors composant le processeur sont utilisés pour créer des portes logiques simples.


Pour plus de détails voir : Fonctionnement d'un ordinateur.
À faire... 


  1. décrire les mécanismes internes comme le décalage pour les multiplications et divisions


Addition

modifier

Soustraction

modifier

Multiplication

modifier

Division

modifier

Nombres à virgule flottante

modifier

Gestion de pile

modifier

Comparaisons

Une comparaison est une expression booléenne. C'est à dire qu'elle a pour valeur vrai ou faux.

Exemple : 5>2 a pour valeur vrai.

Les opérateurs de comparaison sont les suivants :

Égal
L'opérateur ne retourne vrai que si la valeur des deux expressions comparées sont égales.
Cet opérateur est souvent représenté par l'un des symboles suivants : = ==
Différent
L'opérateur ne retourne vrai que si la valeur des deux expressions comparées ne sont pas égales.
Cet opérateur est souvent représenté par l'un des symboles suivants : <> !=
Inférieur
L'opérateur ne retourne vrai que si la valeur de la première expression est strictement inférieure à celle de la deuxième.
Cet opérateur est souvent représenté par le symbole suivant : <
Supérieur
L'opérateur ne retourne vrai que si la valeur de la première expression est strictement supérieure à celle de la deuxième.
Cet opérateur est souvent représenté par le symbole suivant : >
Inférieur ou égal
L'opérateur ne retourne vrai que si la valeur de la première expression est inférieure ou égale à celle de la deuxième.
Cet opérateur est souvent représenté par le symbole suivant : <=
Supérieur ou égal
L'opérateur ne retourne vrai que si la valeur de la première expression est supérieure ou égale à celle de la deuxième.
Cet opérateur est souvent représenté par le symbole suivant : >=

Comme dans toute expression, les opérandes peuvent utiliser d'autres expressions, des variables etc...

Exemple :

A : ENTIER = 5
B : ENTIER = -3

Pour cet exemple, l'expression B > A retourne faux.

La comparaison est souvent utilisée dans les structures de contrôle pour assigner une condition à l'exécution (répétitive ou non) d'une série d'instructions :

  • Une instruction conditionnelle :
SI A > B ALORS
    ...
FIN SI
  • Une boucle :
TANT QUE B < 10 FAIRE
    ...
FIN TANT QUE


Contrôles

Généralement, le code source d'un programme décrit l'exécution en une suite d'instructions. Par défaut, ces instructions sont exécutées dans l'ordre séquentiel, suivant l'ordre d'écriture du code source (de gauche à droite, de haut en bas).

Exemple :

A ← 3
B ← A + 1

L'ordre d'exécution est alors le suivant :

  1. A ← 3 On affecte la valeur 3 à la variable A.
  2. B ← A + 1 On affecte la valeur 4 (A+1 = 3+1) à la variable B.

Il peut être nécessaire de changer cet ordre pour diverses raisons :

  • N'exécuter certaines instructions que si une condition est remplie (instructions conditionnelles),
  • Répéter en boucle le même traitement plusieurs fois (boucle).

Le changement d'ordre d'exécution est effectué par les instructions de contrôle d'exécution.

Regroupement d'instructions

modifier

Les sections qui suivent parle d'une instruction, mais il est possible d'utiliser plusieurs instructions en les regroupant dans un bloc. Ce bloc est alors utilisable là où le terme « une instruction » est employé.

Un bloc est délimité par des caractères spéciaux ou des mots réservés du langage.

Beaucoup de langages de programmation utilisent les accolades pour délimiter un bloc (C, C++, Java, C#, Javascript, PHP, ...) :

{
    instruction1
    instruction2
    ...
}

D'autres utilisent des mots réservés :

En Pascal, Delphi et Ada :

BEGIN
    instruction1
    instruction2
    ...
END;

En Visual Basic, les mots utilisés dépendent de l'instruction :

If ...
    instruction1
    instruction2
    ...
EndIf
For ...
    instruction1
    instruction2
    ...
Next

Instruction conditionnelle

modifier

Une instruction conditionnelle n'est exécutée que si une condition est vraie. Elle peut être conditionnée par l'existence d'un fichier, la valeur d'une variable ou expression, l'absence d'erreur retournée par une fonction, ...

Beaucoup de langage de programmation possède une instruction if (mot anglais signifiant si) pour tester une condition. La syntaxe générale est la suivante :

SI condition ALORS
    instruction_si_condition_vraie
FINSI

Une autre syntaxe autorise également l'exécution d'une instruction quand la condition est fausse.

SI condition ALORS
    instruction_si_condition_vraie
SINON
    instruction_si_condition_fausse
FINSI

Chacun des mots est à remplacer par celui utilisé par le langage, utilisant souvent leur équivalent anglais (SI → IF, ALORS → THEN, SINON → ELSE, FINSI → ENDIF). Le mot ALORS peut être absent dans certains langages, car implicite.

En C, C++, Java, C#, Javascript, PHP :
if (condition)
    instruction_si_condition_vraie
else
    instruction_si_condition_fausse
Exemple en Java :
if (a < b)
    System.out.println("A est plus petit que B");
else
    System.out.println("A égale ou est plus grand que B");

En Pascal, Delphi :

IF condition THEN
    instruction_si_condition_vraie
ELSE
    instruction_si_condition_fausse

En Visual Basic :

If condition Then
    instruction_si_condition_vraie
Else
    instruction_si_condition_fausse
EndIf

Une boucle permet de répéter une instruction un nombre de fois déterminé ou non. La boucle générale exécute l'instruction à répéter tant qu'une condition est vraie. La condition peut être évaluée avant l'instruction ou après. Certains langages autorisent aussi une forme de boucle qui se termine quand une condition devient vraie.

Une itération est une exécution particulière de l'instruction dans une boucle. Voir les sections ci-dessous qui détaillent les types de boucle.

Boucle conditionnelle

modifier

La boucle conditionnelle exécute une instruction (ou bloc d'instructions) tant qu'une condition est vraie ou fausse.

Condition testée avant

modifier

La boucle « tant que » exécute instruction tant qu'une condition est vraie, c'est-à-dire jusqu'à ce que la condition soit fausse. Tant que la condition est vraie, une nouvelle itération a lieu.

Elle a en général la forme suivante :

TANT_QUE condition FAIRE
  instruction

La condition est testée avant, ce qui signifie que l'instruction peut ne pas être exécutée si la condition est fausse initialement.

Exemple en Java :

while (a < b)
    a = a + 10;

Avec un bloc d'instruction :

while (a < b)
{
    a = a + 10;
    System.out.println("Nouvelle valeur de A = "+a);
}

Condition testée après

modifier

La boucle peut avoir également cette forme :

FAIRE instruction
TANT_QUE condition

La condition est testée après, ce qui signifie que l'instruction est exécutée au moins une fois même si la condition est fausse initialement.

do
{
    a = a + 10;
}
while (a < b);

Répéter jusqu'à

modifier

Une autre forme de la boucle répète une instruction jusqu'à ce que la condition soit vraie, c'est-à-dire tant que la condition est fausse. Tant que la condition est fausse, une nouvelle itération a lieu.

La forme la plus courante est celle où la condition est testée après l'instruction :

RÉPÉTER instruction
JUSQU_À condition

Il existe aussi une forme où la condition est testée avant l'exécution de l'instruction :

JUSQU_À condition
RÉPÉTER instruction

Boucle d'itération d'un ensemble

modifier

Ce type de boucle effectue une itération pour chacun des éléments d'un ensemble. Une variable associée prend les différentes valeurs successives des éléments de l'ensemble.

Entiers

modifier

On trouve cette forme dans les premiers langages de programmation (Fortran, Basic, Pascal). Les langages de programmation plus récents utilisent en général une autre forme de la boucle.

Cet ensemble peut être celui des entiers en spécifiant les bornes minimales et maximales :

POUR variable DE min À max
FAIRE instruction_qui_peut_utiliser_variable

Le pas par défaut est de un, certains langages permettent de spécifier un autre pas :

POUR variable DE min À max PAS_DE pas
FAIRE instruction_qui_peut_utiliser_variable

Un pas de -1 permettant de parcourir en sens inverse. D'autres langages supporte un sens automatique de parcours inversé quand la borne min est plus grande que max.

Itération par condition explicite

modifier

La plupart des langages supporte cette forme de boucle générale. Elle est composée de trois parties contrôlant l'exécution en plus de l'instruction à exécuter :

  • l'initialisation d'une ou plusieurs variables,
  • l'expression définissant la condition d'itération (testée avant exécution),
  • l'instruction d'incrémentation permettant de passer à l'élément suivant.
POUR initialisation TANT_QUE condition SUIVANT incrémentation
FAIRE instruction

Exemple en Java :

for (int nombre = 1 ; nombre<=10 ; nombre++)
    System.out.println("Le carré de "+nombre+" est "+(nombre * nombre));

Ensemble générique

modifier

D'autres langages (Python, C Sharp, Java) permettent de spécifier un ensemble générique (éléments d'un tableaux, d'une liste...).

POUR variable DANS ensemble_à_parcourir
FAIRE instruction_qui_peut_utiliser_variable

Exemple pour afficher tous les éléments d'un tableau en Java :

String[] mots = { "Une","phrase","comportant","plusieurs","mots" };
for (String mot : mots)
    System.out.println(mot);


Entrées-sorties

Cette page est considérée comme une ébauche à compléter . Si vous possédez quelques connaissances sur le sujet, vous pouvez les partager en éditant dès à présent cette page (en cliquant sur le lien « modifier »).

Ressources suggérées : Aucune (vous pouvez indiquer les ressources que vous suggérez qui pourraient aider d'autres personnes à compléter cette page dans le paramètre « ressources » du modèle? engendrant ce cadre)

Les fonctions d'entrées-sorties sont des fonctions de l'API du langage de programmation permettant de réaliser des entrées (lecture de données) et des sorties (écriture de données) depuis / vers un flux d'entrée-sortie (console, fichier, socket, ...).

Par exemple :

  • lire depuis le clavier, écrire sur l'écran,
  • lire depuis un fichier, écrire dans un fichier,
  • ...

Interactions avec l'utilisateur

modifier

C'est pour faciliter les entrées et les sorties de données que des interfaces sont programmées. Elles doivent être simples et lisibles.

Fichiers

modifier

Communication par réseau

modifier

Manipulation de chaînes

program p (data,output);

   var a,b : integer; data : text;
   begin
   reset(data);b := 0; {on met b a zero}
   while not eof(data) do
   begin readln(data,a);
   if a > 42 then b := b+1 end;
   writeln(a)
   end.


Procédures et fonctions

Cette page est considérée comme une ébauche à compléter . Si vous possédez quelques connaissances sur le sujet, vous pouvez les partager en éditant dès à présent cette page (en cliquant sur le lien « modifier »).

Ressources suggérées : Aucune (vous pouvez indiquer les ressources que vous suggérez qui pourraient aider d'autres personnes à compléter cette page dans le paramètre « ressources » du modèle? engendrant ce cadre)

Les termes procédure et fonction désignent tous deux des sous-programmes. Un sous-programme est constitué, comme un programme, d'une suite d'instructions. Cette suite d'instructions réalise une fonction simple ou complexe, utilisée généralement à divers endroit du code du programme principal.

Programme sans sous-programme

modifier

Pour présenter l'intérêt d'utiliser un sous-programme, voici un exemple de code :

prix : RÉEL
quantité : ENTIER
total_ttc : RÉEL = 0.00
tva : RÉEL = 19.60

-- achat de 3 articles à 10,50€ HT chacun
prix ← 10.50
quantité ← 3
total_ttc ← total_ttc + tva * ( prix * quantité )

-- achat de 2 articles à 21,30€ HT chacun
prix ← 21.30
quantité ← 2
total_ttc ← total_ttc + tva * ( prix * quantité )

-- achat d'1 article à 2,40€ HT
prix ← 2.40
quantité ← 1
total_ttc ← total_ttc + tva * ( prix * quantité )

Pour les 3 achats de l'exemple, le calcul est répété à chaque fois. Ce qui n'est pas pratique pour la maintenance du code : si la formule n'est pas la bonne (une erreur est toujours possible) ou si la formule doit être modifiée (autre mode de calcul), il faudra changer le code en plusieurs endroits pour un même type de calcul.

Règle d'or de la programmation 

Le copier-coller est une très mauvaise façon de programmer.

Une procédure

modifier

Le premier intérêt d'utiliser un sous-programme est de regrouper le code commun et éviter d'avoir plusieurs endroits du code à modifier pour un seul changement d'algorithme, de formule, ...

L'exemple utilisant une procédure devient :

total_ttc : RÉEL = 0.00
tva : RÉEL = 19.60

DÉBUT PROCEDURE acheter(prix: RÉEL , quantité : ENTIER)
    total_ttc ← total_ttc + tva * ( prix * quantité )
FIN

acheter(10.50, 3)  -- achat de 3 articles à 10,50€ HT chacun

acheter(21.30, 2)  -- achat de 2 articles à 21,30€ HT chacun

acheter(2.40, 1)  -- achat d'1 article à 2,40€ HT

Cette deuxième version du code est beaucoup plus claire que la première : les détails du calcul ont été déplacés dans une procédure nommée "acheter" à deux arguments :

  • Le prix de l'article,
  • La quantité achetée.

L'utilisation d'un sous-programme permet donc de clarifier ce que fait le programme, sans s'encombrer des détails de l'algorithme utilisé pour effectuer l'action voulue.

Une fonction

modifier

L'exemple précédent modifie une variable globale nommée total_ttc. Ce qui s'appelle un effet de bord : un effet qui ne dépend pas que des paramètres d'entrée (prix et quantité dans l'exemple).

Règle d'or de la programmation 

Évitez d'utiliser des variables globales pour stocker un résultat temporaire.

Dans un tel cas, il est préférable d'utiliser une fonction. Une fonction permet de retourner une valeur au programme appelant.

Dans le cas présent, la fonction calcule le prix TTC pour l'achat d'une certaine quantité d'articles, et le retourne au programme appelant. Celui-ci utilise le prix TTC retourné pour l'ajouter au total :

tva : RÉEL = 19.60

DÉBUT FONCTION pric_ttc(prix: RÉEL , quantité : ENTIER)
    RETOURNE tva * ( prix * quantité )
FIN

total_ttc : RÉEL = 0.00

total_ttc ← total_ttc + pric_ttc(10.50, 3)  -- achat de 3 articles à 10,50€ HT chacun

total_ttc ← total_ttc + pric_ttc(21.30, 2)  -- achat de 2 articles à 21,30€ HT chacun

total_ttc ← total_ttc + pric_ttc(2.40, 1)  -- achat d'1 article à 2,40€ HT


Paradigmes de programmation

Il existe différentes classes de langage qui fonctionnent à partir de concepts et de schémas de pensées différents. Ainsi, le langage C est assez éloigné du langage Lisp qui lui-même ne partage guère les structures de base du langage SmallTalk.

On parle de paradigme pour désigner un ensemble de concept particulier.

Les langages de programmation impératifs représentent le premier paradigme de programmation utilisé : ce sont les langages qui héritent de l'Algol, dont le C est le meilleur représentant.

Bien qu'inventé en même temps, le paradigme orienté objet a connu le succès avec le C++ et, au début du XXIème siècle grâce aux langages Java et C#.

Les autres paradigmes, comme par exemple la programmation fonctionnelle, sont moins utilisés. Ils comprennent le LISP, le Scheme et le Prolog. Le logo est également un langage respectant le paradigme fonctionnel.

Certains langages sont multi-paradigmes, ainsi le Python offre les trois paradigmes présentés dans cette introduction.


Programmation séquentielle

Cette page est considérée comme une ébauche à compléter . Si vous possédez quelques connaissances sur le sujet, vous pouvez les partager en éditant dès à présent cette page (en cliquant sur le lien « modifier »).

Ressources suggérées : Aucune (vous pouvez indiquer les ressources que vous suggérez qui pourraient aider d'autres personnes à compléter cette page dans le paramètre « ressources » du modèle? engendrant ce cadre)

La programmation séquentielle est un paradigme de programmation dans lequel le déroulement des instructions du programme est toujours le même. Les instructions exécutées peuvent varier en fonction des conditions initiales : embranchements, boucles... Par exemple, un calcul de taux d'imposition relève de la programmation séquentielle car une fois lancé, le traitement exécute toutes ses instructions dans un ordre prédéfini sans avoir à prendre en compte d'événement externe (interruption).

La programmation séquentielle s'oppose à la programmation événementielle dans laquelle la séquence d'instructions exécutée est déterminée ou modifiée en permanence par les différents événements extérieurs ayant une incidence sur le traitement durant son exécution. Par exemple, le traitement prenant en charge l'interface homme-machine (affichage sur écran) sur un micro-ordinateur relève de la programmation événementielle : le traitement prend en compte en permanence les actions de l'utilisateur qui viennent interagir avec la séquence de ses instructions.


Programmation concurrente

Cette page est considérée comme une ébauche à compléter . Si vous possédez quelques connaissances sur le sujet, vous pouvez les partager en éditant dès à présent cette page (en cliquant sur le lien « modifier »).

Ressources suggérées : Aucune (vous pouvez indiquer les ressources que vous suggérez qui pourraient aider d'autres personnes à compléter cette page dans le paramètre « ressources » du modèle? engendrant ce cadre)

Tous les systèmes d'exploitation actuels sont multi-tâches : Ils permettent l'exécution "en parallèle" de plusieurs applications : lancer un traitement de texte tout en écoutant sa musique préférée.

Au sein de la même application (ou programme), plusieurs tâches peuvent également s'effectuer "en parallèle" :

  • Dans un traitement de texte, une tâche récupère ce que l'utilisateur tape tout en vérifiant l'orthographe de ce qui a été tapé précédemment,
  • Le logiciel d'écoute de musique a une tâche de lecture du fichier pour le jouer, une autre pour afficher le temps écoulé, ...

"En parallèle"

modifier

En fait, les tâches ne sont pas exécutées en parallèle, à moins que la machine possède plusieurs processeurs. Le système d'exploitation accorde à chaque tâche lancée un peu de temps de processeur pour s'exécuter. Une fois ce temps écoulé, il donne du temps à une autre tâche, etc. La durée et l'attribution du temps dépend du système d'exploitation et de la priorité attribuée à chaque tâche (priorité pouvant évoluer dans le temps). Si le système dispose de plusieurs processeurs, ceux-ci travaillent en parallèle pour exécuter plus d'une tâche à la fois.

Exemple de tâches :

Tâche 1:                       Tâche 2:
  A ← B + 1                 C ← "Exemple"

Et un exemple d'ordre d'exécution :

Temps          Tâche 1:            Tâche 2:
  t              tmp ← B + 1
 t+1                                 C ← "Exemple"
 t+2             A ← tmp



Programmation impérative

Cette page est considérée comme une ébauche à compléter . Si vous possédez quelques connaissances sur le sujet, vous pouvez les partager en éditant dès à présent cette page (en cliquant sur le lien « modifier »).

Ressources suggérées : Aucune (vous pouvez indiquer les ressources que vous suggérez qui pourraient aider d'autres personnes à compléter cette page dans le paramètre « ressources » du modèle? engendrant ce cadre)

La programmation impérative est un paradigme de programmation où le programmeur dicte explicitement au processeur ce qu'il doit faire (ordres impératifs). Les opérations sont décrites en séquences d'instructions exécutées par l'ordinateur pour modifier l'état du programme. Ce type de programmation est le plus répandu parmi l'ensemble des langages de programmation existants. Il se différencie de la programmation déclarative dont la programmation logique et la programmation fonctionnelle sont des sous-ensembles.


Programmation orientée objet

La programmation orientée objet ou POO existe depuis les années 1960.

Consultez également ces pages dans d’autres projets Wikimedia :

Article encyclopédique sur Wikipédia.
Définition sur Wiktionnaire.



Programmation générique

La généricité (ou programmation générique), consiste à définir des algorithmes identiques opérant sur des données de types différents. L'algorithme est implémenté comme une procédure, fonction ou méthode selon la terminologie adaptée au paradigme du langage de programmation employé.

Techniques

modifier

Différentes techniques permettent la programmation générique selon le paradigme du langage de programmation utilisé :

  • Templates (précurseurs des types et paramètres génériques) : Certains langages impératifs (Ada 83) permettent de manipuler un type qui n'est pas spécifié explicitement.
  • Paramètres génériques : Certains paramètres de l'algorithme ne sont pas spécifiés : constantes, types...
  • Types génériques : Supporté en général par les langages de programmation orientée objets (C++, Java, Eiffel...), le type générique n'est pas déterminé à l'avance, et permet d'appliquer le même algorithme à différents types.
  • Polymorphisme : Supporté par les langages de programmation orientée objets, le polymorphisme permet de manipuler les instances d'une classe mais également celles des classes dérivées.

Types et paramètres génériques

modifier

Principe

modifier

Dans la plupart des langages de programmation, les opérateurs d'expression (opérateurs arithmétiques, logiques, de comparaison...) supportent différents types numériques, entiers et à virgule flottante, sur différentes tailles fixes (16, 32, 64 bits...). Plutôt que de redéfinir le même algorithme (procédure, fonction ou méthode de classe) plusieurs fois pour chaque type numérique, l'algorithme n'est codé qu'une seule fois, en utilisant une syntaxe particulière indiquant qu'il s'agit d'un type générique non défini.

Cela peut s'appliquer aussi aux types non numériques, y compris des structures complexes (objet, chaîne de caractères, tableaux) quand l'algorithme n'utilise aucune particularité du type. C'est le cas par exemple des collections de données (liste, dictionnaire...) qui ne font que stocker les valeurs quel que soit leurs types qu'il s'agisse d'entiers, de chaînes de caractères...

Fonctionnement interne

modifier

À la compilation, certains langages (Java par exemple) remplacent le type générique par un type répondant aux contraintes associées.

D'autres langages ne compilent pas l'algorithme générique (ou partiellement) lors de sa déclaration. Il n'est compilé qu'à son utilisation, lorsque le type à utiliser est déterminé.


Programmation par contrat

Cette page est considérée comme une ébauche à compléter . Si vous possédez quelques connaissances sur le sujet, vous pouvez les partager en éditant dès à présent cette page (en cliquant sur le lien « modifier »).

Ressources suggérées : Aucune (vous pouvez indiquer les ressources que vous suggérez qui pourraient aider d'autres personnes à compléter cette page dans le paramètre « ressources » du modèle? engendrant ce cadre)

La programmation par contrat est un paradigme de programmation dans lequel le déroulement des traitements est garanti par des vérifications sur les données, ce qui permet d'être sûr que les traitements ne vont pas déclencher d'erreur. Il y a trois catégories de vérification :

  • Précondition : L'ensemble des conditions qui doivent être vérifiées avant le lancement d'un traitement donné. Ces conditions permettent de s'assurer que le déroulement du traitement est possible sans déclencher d'erreur.
  • Postcondition : L'ensemble des conditions qui doivent être vérifiées après le déroulement d'un traitement. Ces conditions permettent de s'assurer que le déroulement du traitement n'a pas déclenché d'erreur.
  • Invariant : L'ensemble des conditions qui doivent être vérifiées à tout moment, y compris au sein d'un traitement.

Le seul langage de programmation qui implémente ce paradigme est le langage Eiffel, mais des modules existent pour d'autres langages, comme JContractor pour Programmation Java.


Eclipse

 

Eclipse est un environnement de développement intégré (EDI), générique et extensible (site officiel http://www.eclipse.org). Son système de plugins permet d'ajouter des fonctionnalités diverses.

Initialement prévu pour développer en Java, grâce aux plugins il peut maintenant également gérer des projets développés avec d'autres langages de programmation tels que :

  • Le C et le C++ grâce à l'ensemble de plugins CDT (C Development Toolkit)[1] (compilateur non intégré).
  • Le Python via PyDev[2].
  • Avant l'arrivée d'Android Studio, le développement pour Android se faisait avec Eclipse grâce à l'ensemble de plugins ADT (Android Development Toolkit).

Certains IDE sont basés sur Eclipse, et permettent par exemple le développement de logiciel embarqués pour des systèmes temps réel.

Installation de Eclipse

La page de téléchargement d'Eclipse permet de récupérer une version déjà adaptée au langage ciblé sur http://www.eclipse.org/downloads/. Mais pour installer un plugin manuellement, il faut :

  • Lancer Eclipse, puis dans le menu déroulant :Help>Software Updates>Find and Install...
  • Cocher Search for new features to install, bouton Next. Bouton New Remote Site..., entrer l'adresse de téléchargement :
Name: Nom du plugin
URL: adresse du plugin, ex : http://www.eclipse.org/cdt/downloads.php
  • Bouton Finish, choisir un miroir proche puis continuer l'installation.

Utilisation de Eclipse

L'interface de l'IDE Eclipse est basée sur différentes perspectives. Une seule perspective n'est visible à la fois, et se compose de plusieurs vues. Exemples :

  • La perspective "Java" se compose par défaut de la vue "Package Explorer", de la vue éditeur de code en Java avec un onglet par fichier ouvert, de la vue "Outline" donnant la hiérarchie des éléments composant la classe du fichier ouvert.
  • La perspective "Debug" est ouverte automatiquement au lancement d'une application en mode débogage et se compose par défaut de la vue "Debug" affichant la pile d'appel, de la vue des points d'arrêt nommée "Breakpoints", de la vue éditeur de code en Java avec un onglet par fichier ouvert, de la vue "Outline" donnant la hiérarchie des éléments composant la classe du fichier ouvert.
  • Deux ou plusieurs perspectives peuvent être affichées conjointement.

Chaque vue est une sous-fenêtre qui a un titre et se place dans un cadre particulier de la fenêtre de l'IDE. Les vues peuvent être déplacées à la souris par drag and drop pour changer la disposition de la perspective. Plusieurs vues peuvent partager le même cadre, auquel cas, une barre d'onglets permet de basculer entre les vues. Un double clic sur le titre d'une vue provoque l'affichage du cadre qui la contient en pleine fenêtre, réduisant les autres cadres à une icône sur les côtés. Un second double clic restaure les cadres.

Le menu "Window" permet de changer de perspective, et d'ajouter des vues à la perspective courante. Une vue peut également être retirée de la perspective affichée en utilisant la croix à droite du titre de la vue.

 
Eclipse

Édition de lignes

L'éditeur de code possède des raccourcis clavier pratiques rendant l'édition des lignes de code plus rapide :

Touches Effet
Shift ↵ Enter Ajouter une nouvelle ligne après la ligne courante.
Ctrl / Faire défiler la vue vers le haut/le bas.
CtrlShift / Déplacer le curseur sur le membre précédent/suivant de la classe.
Alt / Déplacer la ligne courante ou les lignes sélectionnées vers le haut/le bas dans le texte.
CtrlAlt / Dupliquer la ligne courante ou les lignes sélectionnées vers le haut/le bas.
CtrlShift : Commenter/Décommenter la ligne courante.

Complétion de code

L'éditeur de code peut compléter automatiquement le code là où se trouve le curseur :

Touches Effet
Ctrl Espace Ouvrir la liste des suggestions de complétion.

Une fois la suggestion choisie, la validation se fait par l'une des touches suivantes :

  • ↵ Enter, n'ajoute rien derrière la suggestion ;
  • Espace ou ., ajoute également le caractère produit derrière la suggestion.

Toute autre touche produit le caractère sans valider (annuler la complétion).

AltShift : Complète avec la seule possibilité, ou produit un bip s'il y a plusieurs possibilités.
  • Dans les codes sources dépassant la hauteur de fenêtre de l'éditeur, placez le pointeur de la souris sur l'accolade fermante d'un bloc pour voir apparaître un résumé du code d'ouverture du bloc en bulle d'aide. Ceci est fort utile pour vérifier quel bloc est fermé par l'accolade sans avoir à faire défiler le code.
  • Placez le pointeur de la souris sur un identifiant de classe, méthode ou variable et enfoncez la touche Ctrl pour faire apparaître un lien cliquable vers la définition.
  • Cliquez sur un identifiant de membre de classe pour faire apparaître toutes les occurrences d'utilisation dans le fichier : à la fois dans le texte et dans la barre de défilement. Les blocs apparaissant dans la barre de défilement sont cliquables pour faire défiler le code à la position de l’occurrence. Il y a deux couleurs distinctes pour les occurrences utilisées en lecture (accès, appel, ...) et celles utilisées en écriture (affectation).
    Il peut arriver que cela ne semble pas fonctionner car l'éditeur peut être dans un mode autre que celui par défaut. Il faut dans ce cas appuyer une ou deux fois la touche Échap pour que cela fonctionne.



NetBeans

 
Logo de Apache NetBeans

Installation de NetBeans

modifier

NetBeans est un environnement de développement intégré (EDI), générique et extensible. Il permet nativement de développer en Java, C, C++, JavaScript, XML, Groovy, PHP et HTML.

De plus, il possède son propre wiki officiel[3] (en anglais). La présente page est donc destinée à le synthétiser au maximum.

Pour démarrer l'installation, le télécharger la version LTS sur https://netbeans.org/downloads/, ou bien la toute dernière sur http://bits.netbeans.org/dev/nightly/latest/.

Configuration

modifier
  • Pour installer les plugins comme PHP ou Python : https://netbeans.org/downloads/index.html.
  • Par défaut le chemin d'accès d'un fichier ouvert apparait en survol de son nom. Pour l'afficher en permanence sous la barre de menu : Tools, Options, Appearance, Show full file path.
  • L'autoformatage est réglable dans Tools, Options, Editor, Formatting.
    • Pour déplacer la barre verticale rouge qui se trouve par défaut à 80 caractères de la gauche : Tools, Options, Editor, Formatting, Right Margin. Par exemple sur GitHub, la taille des écrans est de 120 caractères, il vaut donc mieux ne pas dépasser cette largeur pour éviter lors des relectures de codes, de descendre chercher un des ascenseurs pour remonter lire une fin de ligne.
  • Pour bénéficier des avantages propres à un framework (ex : autocompletion des objets du projet ou ouverture d'une déclaration de méthode avec "CTRL + clic" sur un appel), il convient, après installation dans "Tools\Plugins" de spécifier manuellement son emplacement dans "Tools\Options", puis pour PHP par exemple "Framework & Tools".

Utilisation

modifier
 
NetBeans

NetBeans permet de comparer deux fichiers : Tools, Diff...

Gestion de versions

modifier

Les gestions de version sont regroupées dans le menu Team. NetBeans peut donc tout à fait remplacer des clients Git purs tels que GitHub Desktop ou Smartgit.

Pour éviter de commiter fichier par fichier, ajouter le bouton Commit All - Repository en le faisant glisser depuis View, Toolbars, Customize.

 
 

Principaux raccourcis claviers

modifier

Liste exhaustive en anglais : http://wiki.netbeans.org/KeymapProfileFor60.

  • Alt + Maj + o : ouvre le fichier recherché.
  • Ctrl + o : ouvre le fichier déclarant l’objet sélectionné (recherche de classe).
  • Ctrl + Maj + f : cherche un texte dans les fichiers le dépôt.
  • Ctrl + b : cherche la déclaration d'un élément (dans le même fichier ou pas).
  • Ctrl + espace : propose une liste de complétion (mots-réservés et squelettes de fonctions).
  • Ctrl + Maj + espace : affiche la documentation d'une méthode (Javadoc, PHPDoc...).
  • Ctrl + p : affiche uniquement les arguments possibles d'une méthode.
  • Ctrl + Maj + c : commente les lignes sélectionnées.

Plugins

modifier

Certains plugins peuvent se révéler utiles :

Références

modifier


PhpStorm

IDE en freemium réputé le meilleur pour le langage PHP (compter 10 € par mois pour l'utiliser au-delà d'un mois), PhpStorm permet entre autres des recherches relativement rapides dans le code grâce à son indexation, de l'autocomplétion des langages Web, de nombreuses propositions d'optimisations de code et des plugins (ex : Git, Docker, frameworks PHP...).

Installation

modifier

Le logiciel est multi-plateforme est ses prérequis figure avec les liens de téléchargement sur le site officiel : https://www.jetbrains.com/help/phpstorm/installation-guide.html.

Configuration

modifier

Pour un projet git, il est recommandé d'ajouter le dossier .idea/ créé par PhpStorm dans le fichier .gitignore.

Pour éviter de modifier la totalité des fichiers d'un projet mal formaté, il faut désactiver le reformatage automatique lors du copier-coller sans Settings, Editor, Smart Keys, Reformat on paste : None.

Exclure les fichiers minifiés de l'indexation

modifier

Idéalement l'indexation des fichiers par PhpStorm devrait prendre moins d'une minute, et ses recherches ne devraient renvoyer que du code source lisible par un humain (par les fichiers minifiés).

Pour ce faire, il faut exclure certains dossiers dans File\Settings\Directories.

Par exemple sur un projet Symfony on exclura :

  • public/build (pour les .js optimisés)
  • var (pour les .php optimisés, et les logs)

Fonctionnalités

modifier

Refactorisation

modifier

Par rapport à ses concurrents, il offre de nombreuses options de refactorisation. Par exemple, quand on renomme une variable en passant par le menu "Refactor", il peut le répercuter dans tout le code du projet qui l'appelle, y compris dans les getters et setters. De plus, il peut ajouter ces derniers automatiquement, ainsi que le constructeur d'une classe selon ses attributs (raccourci ALT + Ins), avec un formatage très personnalisable, par exemple pour les retours à la ligne après chaque attributs ou selon une largeur.

À ce propos, afin de respecter la PSR-1 lors de l'insertion de setters, il convient de paramétrer dans Editor\Code Style\PHP\Blank lines, Before return statement = 1.

Autoformatage

modifier

Il fournit aussi de nombreuses options d'autoformatage et son analyse de code permet par exemple de trouver les variables non utilisées. Quand on appelle une méthode avec du type hinting, il apparait sans avoir besoin d'ouvrir le fichier de cette dernière. Depuis la version 2019.3, il affiche les méthodes mortes en couleur plus sombre (en plus des variables mortes qu'il signalait déjà).

Par ailleurs, pour le pretty-print XML ou JSON : Code\Reformat Code.

Terminal

modifier

Par ailleurs, il possède un lien vers un terminal shell intégré dans une fenêtre du footer, et peut aussi exécuter des requêtes SQL sur des bases si on lui ajoute les sources de données. À ce propos, il permet de naviguer dans une base de données nativement avec une interface, comme le fait PhpMyAdmin, Adminer ou MySQL Workbench.

L'interpréteur de commande est modifiable dans Settings\Tools\Terminal. Par exemple pour utiliser du shell Unix depuis Windows, on peut mettre :

C:\Program Files\Git\bin\sh.exe

Gestion de version

modifier

Son système VCS est compatible avec git et permet de voir l'historique des modifications des fichiers en couleur. Par exemple avec un clic droit dans la marge on peut afficher les annotations pour retrouver l'auteur d'un passage, puis réitérer l'opération en affichant les annotations précédentes pour remonter tout l'historique.

De plus, quand on regarde le différentiel des fichiers modifiés depuis le dernier commit (onglet "Version Control" en bas, "resolve", puis "merge..."), en cas de conflit il propose un outil de résolution à trois colonnes très ergonomique.

Enfin, son outil de rebase interactif permet des squash et fixup en masse (dans Log, sélectionner la branche, sélectionner les commits à squasher dans la liste).

Xdebug peut être déclenché depuis une page Web ou une commande shell. S'il est déjà installé sur le serveur PHP, et pour les pages Web dans le navigateur, voici ce qu'il reste à faire pour le faire fonctionner dans PhpStorm :

  • Cliquer sur l'icône en haut à droite Listen for debug connect.
  • Lancer le script à déboguer (afficher la page Web ou entrer la commande shell).

Une fenêtre apparait alors dans PhpStorm Incoming Connection From Xdebug, demandant quel est l'index.php correspondant au signal reçu. Cocher "Import mappings from deployment" si les fichiers sont exécutés sur un serveur distant, et "Manually choose local file or project" s'il est local. Cette deuxième option dresse une liste des index.php trouvés dans le projet, mais pour conserver celui par défaut, choisir leur dossier parent (le nom du projet), et cliquer sur "Accept".

En cas de problème, un outil de diagnostic se trouve dans File, Settings, chercher "Xdebug".

Si le serveur PHP est dans un conteneur Docker, il faut le stipuler à PhpStorm :

  • Ajouter un serveur : dans File, (Languages & Frameworks,) PHP, Servers, ajouter une URL pour le port 80, et une pour le 443. Pour chacun, cocher "Use path mappings" et y mettre le chemin de chaque projet accessible dans le conteneur PHP.
  • Ajouter une configuration de lancement : en haut à droite dans Add Configuration... ou Edit Configurations..., créer une entrée PHP Remote Debug, dans laquelle il faut renseigner le serveur précédemment créé, et la clé de session envoyée par le module de son navigateur.

 

Le php.ini dépend de l'OS hôte[1] :

  • Linux :
 xdebug.remote_host = 172.170.0.1
  • Windows :
 xdebug.remote_host = "docker.for.win.host.internal"
  • Mac :
 xdebug.remote_host = "docker.for.mac.host.internal"

Exemple de Dockerfile :

RUN pecl install -f xdebug \
    && docker-php-ext-enable xdebug

COPY xdebug.ini $PHP_INI_DIR/conf.d
# ou s'il y a peu de lignes à ajouter dans le .ini :
RUN echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

Raccourcis clavier

modifier
Raccourcis clavier indispensables
Maj Maj Rechercher un fichier
Ctrl + Maj + N Ouvrir un fichier (ex : quand on le copie-colle depuis le terminal)
Ctrl + Maj + F Rechercher dans les fichiers
Ctrl + G Aller à la ligne n°X
Ctrl + D Dupliquer la ligne courante
Ctrl + Maj + Alt Sélectionner (en clic, double-clic ou glisser) plusieurs morceaux de codes pour pouvoir les copier.
Ctrl + Maj + Alt + T Renommer en refactorant
Ctrl + B Trouver les utilisations de l'objet courant (équivalent au clic droit, find usages)
Ctrl + E Fichiers récents
Ctrl + K Commiter
Ctrl + L Vider le terminal (utile pour afficher uniquement les derniers logs)
Alt + Insert Générer du code, par exemple le constructeur ou les getters et setters à partir des attributs.
Alt + clic Décupler le curseur pour écrire la même chose à plusieurs endroits.
F2 Se rendre sur l'erreur de compilation du fichier courant

Plugins

modifier

PhpStorm dispose de plusieurs plugins installables dans un deuxième temps, classables par thèmes. Certains sont payants, mais en voici des gratuits utiles :

  • EditorConfig récupère automatiquement la configuration d'IDE par projet (par exemple les conventions de codage)[2] à partir d'un fichier .editorconfig versionné. NB : ce format de fichier fonctionne dans la plupart des autres IDEs[3].
  • SonarLint analyse de code statique en cours de frappe, synchronisable avec SonarQube.
  • Prise en charge de plusieurs frameworks PHP :
    • Symfony donne :
      • Un accès aux fichiers YAML de déclaration de services depuis les classes PHP et vice-versa en un clic[4]
      • Un accès aux fichiers Twig entre eux ou depuis les classes PHP en un clic. Il faut toutefois ajouter au préalable chaque dossier "template" dans Settings, PHP, Symfony, Twig / Template (Namespace = __main__, Type = ADD_PATH).
    • WordPress
    • Drupal
    • Joomla
  • Des frameworks JS :
    • Node.js
    • Angular
    • Next.js
    • Vue.js
  • Docker

Critique

modifier
  • Il est possible que l'application freeze le PC. Pour éviter cela aller dans le menu Help/Change Memory Settings et diminuer la valeur.
  • Début 2019, il considère à tort un fichier accessible par deux liens symboliques Linux comme deux fichiers.
  • Depuis au moins 2020, quand plusieurs projets sont ouverts ensemble, il mélange leurs espaces de nom (namespaces) comme si c'était le même (notamment dans les CTRL + clic).
  • Quand on exclut un dossier de l'indexation, si l'application crée un sous-dossier, il est indexé à tort. Par exemple, dans Symfony var/ est exclu mais var/cache/ apparait dans les recherches si on ne l'exclut pas manuellement après exécution de l'application.

Références

modifier



PyCharm

 

PyCharm est est un environnement de développement intégré utilisé pour programmer en Python.

Installation

Développé par l'entreprise JetBrains, PyCharm est un logiciel multi-plateforme qui fonctionne sous Windows, Mac OS X et Linux.

Il est décliné en édition professionnelle, diffusé sous licence propriétaire, et en édition communautaire diffusée sous licence Apache (donc 100 % gratuite), téléchargeable depuis le site officiel[1].

Configuration

Après installation il faut choisir l'interpréteur Python, dont la version déterminera les conseils fournis par l'IDE. Ils peuvent provenir de quatre environnements :

  • Virtualenv
  • Conda
  • System Interpreter
  • Pipenv

Si le programme doit ensuite tourner sur la machine hôte (sans IDE), le mieux est de prendre "System Interpreter".

Utilisation

PyCharm permet l'analyse de code et contient un débogueur graphique.

Il permet également la gestion des tests unitaires, l'intégration de logiciel de gestion de versions, et supporte le développement web avec Django.

 

Références


SciTE

SciTE (acronyme de Scintilla Text Editor) est un logiciel éditeur de texte graphique, gratuit et open source fonctionnant sous les environnements Linux et Windows. Il est capable d'effectuer la coloration syntaxique, l'auto-complétion et surtout le pliage de code (code folding), c'est à dire le masquage à volonté de différents blocs d'instructions (contenu d'une classe, d'une fonction, d'une boucle, etc.) : cette fonctionnalité se révèle extrêmement pratique lorsque vos scripts commencent à s'allonger... Il intègre également une fenêtre de terminal ainsi qu'un raccourci pour lancement des scripts.

Cet éditeur est disponible pour Windows et pour Linux sur http://www.scintilla.org/SciTE.html.

Scintilla étant une plateforme d'édition de texte qui propose par exemple des outils spécifiques pour corriger du code écrit avec SciTE. Ces deux logiciels sont principalement l'œuvre de leur créateur Neil Hodgson, qui les a placés sous une licence libre peu connue, l'Historical Permission Notice and Disclaimer.

Langages supportés

modifier

Les langages compris par SciTE. Il est actuellement capable d'appliquer une syntaxe de style à ces langages :

Les langages marqués par un astérisque doivent être vérifiés pour fonctionner pour un nombre important de personnes.

Installation sous Linux

modifier

L'éditeur Scintilla fait dorénavant partie des paquetages fournis d'office avec les distributions récentes de Linux. Sinon, téléchargez-le au départ du site web mentionné ci-dessus. Sinon :

  • téléchargez l'archive gscite***.tgz puis l'extraire avec tar ;
  • installez l'exécutable SciTE dans /usr/local/bin ;
  • installez tout le reste (fichiers *.properties) dans /usr/share/scite (et non /usr/share/gscite !).

Installation sous Windows

modifier
  • Téléchargez l'archive wscite***.zip puis l'extraire dans \Program files ;
  • installez une icône de lancement pour l'exécutable SciTe.exe.

Pour les deux versions

modifier

On peut personnaliser beaucoup de choses (polices, etc.) en éditant le fichier des propriétés globales (Menu Options → Open global options file).

Par exemple, pour activer de jolis symboles pour replier/déplier, dans la marge de gauche :

  • fold.symbols = 2 # pour de belles icônes + et - cerclées
  • fold.on.open = 1 # ainsi tout est plié au départ
  • margin.width =0 # pour supprimer la marge inutile

Pour forcer le remplacement automatique des tabulations par des groupes de 4 espaces :

  • tabsize = 4
  • indent.size = 4
  • use.tabs = 0

Traductions

modifier

La traduction doit être téléchargée[1], renommée en "locale.properties" et déplacée dans le même répertoire que les propriétés globales.

Il faut donc passer en root :

sudo nautilus

et aller dans le répertoire par défaut :

/usr/share/scite

Utilisation

modifier
 



Visual Studio Code

 

Visual Studio Code (ou simplement nommé "code") est un logiciel éditeur de texte graphique, gratuit fonctionnant sous Windows. Il est capable de prendre en charge le débogage, d'effectuer la coloration syntaxique, l'auto-complétion et surtout le pliage de code (code folding), c'est à dire le masquage à volonté de différents blocs d'instructions (contenu d'une classe, d'une fonction, d'une boucle, etc.) : cette fonctionnalité se révèle extrêmement pratique lorsque vos scripts commencent à s'allonger... Il intègre également la gestion de version (notamment Git et SVN)[2], une fenêtre de terminal ainsi qu'un raccourci pour lancement des scripts.

Cet éditeur est disponible pour Windows sur https://code.visualstudio.com .

Langages supportés

Visual Studio Code prend immédiatement en charge presque tous les principaux langages informatiques.

Plusieurs d'entre eux sont inclus par défaut, comme HTML et CSS, et aussi JavaScript, TypeScript, Java, PHP, mais d'autres extensions de langage peuvent être trouvées et téléchargées gratuitement à partir de VS Code Marketplace[3].

Utilisation

 

Édition de lignes

L'éditeur de code possède des raccourcis clavier pratiques rendant l'édition des lignes de code plus rapide :

Touches Effet
Ctrl ↵ Enter Ajouter une nouvelle ligne après la ligne courante.
Ctrl / Faire défiler la vue vers le haut/le bas.
Alt / Déplacer la ligne courante ou les lignes sélectionnées vers le haut/le bas dans le texte.
AltShift / Dupliquer la ligne courante ou les lignes sélectionnées vers le haut/le bas.
Ctrl : Commenter/Décommenter la ligne courante.

Références


Structure et style

La structure et le style d'un code source définissent sa présentation. Afin que la maintenance soit facile, il est nécessaire que la présentation du code soit cohérente dans tous les fichiers sources. Des règles de styles sont donc à définir.

Les premiers langages de programmation ne gérant pas les accents (jeu de caractère limité à l'ASCII 7 bits), des habitudes ont été prises pour nommer les variables et écrire les commentaires sans accents. Cela a également aidé la langue anglaise à s'imposer.

Toutefois, cette limite technique n'existe plus dans les langages de programmation modernes, grâce notamment au support du jeu de caractères Unicode. Il est possible de nommer des variables en français avec des accents.

La langue utilisée dans les commentaires et dans la conception est donc d'un choix de développement.

Style du code

modifier

Les caractères blancs (espaces, tabulations, retours à la ligne) sont généralement ignorés par la plupart des langages de programmation, et ne servent qu'à séparer deux mots dans les instructions. Ces caractères permettent donc de présenter le code de façon plus lisible que si les instructions s'enchaînaient sans espaces.

Ceci ne s'applique pas aux langages de programmation où l'indentation a une signification, comme le langage Python par exemple.

Exemple en C : Sans coloration syntaxique, quel code est le plus lisible ?

int main(void){printf("Bonjour monde !");return 0;}

ou

int main ( void )
{
    printf( "Bonjour monde !" );
    return 0;
}

?

Il est possible de définir ses propres règles de style, ou d'utiliser des règles de styles standard afin que la cohérence de présentation dépasse le cadre de son projet personnel.

L'indentation

modifier

L'indentation définit l'espace blanc situé au début de chaque ligne de code. Les lignes de code sont rassemblées en blocs (fonctions, résultat d'un test, ...) et sont ordonnées de manière hiérarchique (bloc conditionnel dans une fonction, fonction dans une classe, classe dans un espace de nom, ...).

À chaque nouveau niveau hiérarchique plus profond, l'indentation augmente.

Exemple (dans un pseudo-langage) :

namespace mynamespace {    // <- début espace de nom
    function myfunction {  // <- début fonction
        if (condition) {   // <- début if
            instruction;   // <- instruction conditionnelle
        }                  // <- fin if
    }                      // <- fin fonction
}                          // <- fin espace de nom

L'exemple précédent utilise 4 caractères espaces supplémentaire à chaque nouveau début de bloc hiérarchique. Le nombre de caractère espaces peut varier selon le style, il est même possible d'utiliser des caractères tabulations au lieu des espaces.

Utiliser des caractères tabulation au lieu des espaces présente certains avantages :

  • Beaucoup de logiciels d'édition ou présentation permettent de définir le nombre d'espace à afficher pour chaque tabulation, ce qui permet à chacun d'adapter la présentation du code.
  • Un caractère de tabulation occupant moins de place qu'une série de caractères espaces, le fichier source est plus petit. Cet avantage était particulièrement important pour les moyens de stockage limités (disquettes par exemple).

et certains inconvénients :

  • Beaucoup de logiciels ne permettent pas de définir le nombre d'espace à afficher pour chaque tabulation qui est fixé (souvent 8, voire 4).

Les caractères de tabulation sont donc souvent à proscrire. Il est préférable d'utiliser le bon nombre de caractères espace à chaque nouvelle indentation :

  • 1 ou 2 est souvent insuffisant pour distinguer les différents niveaux,
  • 4 est généralement correct,
  • 8 est largement trop grand, spécialement quand on limite la longueur des lignes de code (souvent 79 caractères maximum), la limite diminue alors rapidement à chaque nouveau niveau.

Cependant l'utilisation d'espaces a aussi des inconvénients :

  • Certaines lignes peuvent être indentées avec un nombre invalide d'espaces. Par exemple (indentation de 4 espaces) des lignes indentées de 3 ou 5 espaces au lieu de 4, de 7 ou 9 au lieu de 8, ... La différence d'indentation n'est pas visible. Tandis qu'une différence d'un caractère de tabulation est très visible.
  • L'indentation est fixe et imposée à tous. Un développeur reprenant un code existant ne pourra pas adapter facilement l'indentation du code si elle ne lui convient pas. Par exemple, le développeur originel utilisant un écran 4K utilise une indentation de 8 espaces, ce qui est trop grand pour un autre développeur utilisant un écran à faible résolution.

La règle d'or est de toujours utiliser le même style d'indentation (cohérence de présentation) et de ne surtout par mélanger espaces et tabulations.

Il faut aussi veiller à ne pas avoir besoin de plus de 5 indentations dans le code. Dans le cas contraire, il faut envisager de revoir la structure du code.

Le style K&R

modifier

Le style K&R est nommé d'après Kernighan et Ritchie qui ont utilisé ce style dans leur livre Le langage de programmation C (The C Programming Language en version originale).

Ce style définit les règles suivantes :

  • Chaque nouvelle accolade s'ouvre sur la même ligne que l'instruction de contrôle,
  • L'indentation du contenu du bloc est augmenté,
  • L'accolade fermante se situe au même niveau que l'instruction de l'accolade ouvrante.

Exemple:

int main(void) {
    printf( "Bonjour monde !" );
    return 0;
}

Cependant, si la fonction utilise des arguments dont les types sont définis après, l'accolade ouvrante est sur une ligne à part :

int main(argc, argv)
int argc;
char**argv;
{
    printf( "Bonjour monde !" );
    return 0;
}

Le style Allman

modifier

Nommé d'après son auteur Eric Allman, ce style est essentiellement le même que K&R, excepté que chaque accolade ouvrante est située sur une ligne séparée.

Exemple:

int main(void)
{
    printf( "Bonjour monde !" );
    return 0;
}

La déclaration de la fonction, l'accolade ouvrante et l'accolade fermante sont 3 lignes séparées et possèdent le même niveau d'indentation.

Ce style est également utilisé dans les langages de programmation n'utilisant pas les accolades pour les blocs mais des mots-clés. Par exemple, en Pascal les blocs sont définis entre les mots-clés begin et end.

procedure BonjourMonde
begin
    Writeln("Bonjour monde !");
end;

Le style Whitesmiths

modifier

Moins commun que les précédents, ce style indente les accolades au même niveau que le bloc qu'il contient.

Exemple:

int main(void)
    {
    printf( "Bonjour monde !" );
    return 0;
    }

Le style GNU

modifier

Ce style est intermédiaire entre le style Allman et le style Whitesmiths : les accolades sont semi-indentées.

Exemple:

int 
main (void)
  {
    printf ( "Bonjour monde !" );
    return 0;
  }


Règles de programmation

Qu'est-ce qu'une règle de programmation ?

modifier

Une règle de programmation informatique est la description de contraintes à respecter quand on écrit un logiciel. Il existe plusieurs types de règles de programmation :

  • les règles de nommage : elles définissent la façon de nommer les identificateurs utilisés dans une application de façon à faciliter la lecture du code et à aider à détecter des erreurs.
    Exemple : les noms des constantes doivent être en lettres capitales. Les variables, fonctions et classes en CamelCase ou snake case.
  • les règles permettant de faciliter le portage informatique des applications : elles identifient des constructions du langage de programmation qui peuvent avoir un comportement différent selon le système d'exploitation ou le microprocesseur.
    Exemple : deux nombres flottants ne doivent pas être comparés pour une stricte égalité (mais arrondis).
  • les règles protégeant des pièges d'un langage
    Exemple en C : utiliser la condition Yoda pour ne pas confondre le "=" d'affectation et le "==" de comparaison. Cela consiste à toujours placer l'opérande variable à droite (ex : if 1 == x).
  • les règles de présentation pour faciliter la relecture du code
    Exemple : mettre une seule instruction par ligne.
  • les règles facilitant la maintenance des applications
    Exemple : en C, C++ et Java, mettre les blocs if et then d'un test entre accolades.
  • les règles limitant la complexité du code
    Exemple : limiter la complexité des expressions à 4 opérateurs.
  • les règles permettant d'améliorer la structuration du code
    Exemple : déclarer les variables partagées dans un fichier header.

Vérification des règles de programmation

modifier

La vérification d'un ensemble de règles de programmation est généralement faite lors d'un audit de code. Elle peut être réalisée soit manuellement par lecture du code, soit automatisée par un outil qui localise les violations des règles.


Outils de vérification automatique de règles de programmation

modifier
  • AdaControl : cet outil permet de vérifier des règles de programmation pour Ada.
  • CodeCheck : cet outil permet de vérifier des règles de programmation pour C et C++.
  • Logiscope Rulechecker : cet outil permet de vérifier des règles de programmation pour les langages C, C++, Ada et Java.

Règles de programmation standardisées

modifier
  • MISRA C : ensemble de règles initialement réalisées pour l'automobile et maintenant largement utilisées.
  • MISRA C++ : version de MISRA C adaptée au langage C++.
  • JSR pour Java.
  • PSR pour PHP.


Langages de programmation

On distingue six générations de langages de programmation. Les langages des générations 1 et 2 sont appelés langages de bas niveau (orienté machine) alors que les langages des générations 3 à 6 sont appelés langages de haut niveau (orienté problème). Les langages de haut niveau sont indépendants du processeur ce qui n’est pas le cas des langages de bas niveau.

Bas niveau

modifier

Génération 1

modifier
  • Langage machine dépendant du processeur
  • Suite d’instructions binaires directement introduites (programmation directe) dans la mémoire du processeur
  • Les instructions du processeur sont appelées code opérationnel

Code opérationnel- Intel pentium- Motorola 6800

Exemple pour un processeur 8086 :

BD 41 00
BE 65 41
01 D8
38 47 03

La programmation de la machine par un humain à ce niveau nécessite d'avoir le manuel du processeur. Les erreurs de frappe arrivent facilement.

Génération 2

modifier
  • Même jeu d’instructions que le langage machine, mais sous forme symbolique (mnémoniques) plus compréhensible pour l’homme
  • Les instructions sont converties (programmation indirecte) en langage machine par un programme (assembleur)

Exemple pour un processeur 8086 :

MOV BP,41h
MOV SI,4165h
ADD AX,BX
CMP [BX+3],AL

Les langages assembleurs plus évolués permettent d'utiliser des commentaires et possèdent des fonctionnalités facilitant la vie du développeur, lui évitant des calculs manuels et des erreurs potentielles. Par exemple, il est possible de définir un symbole/nom/label représentant l'adresse où se trouve la déclaration puis l'utiliser directement comme opérande (adresse de saut ou adresse de l'emplacement d'une donnée) dans les instructions à la place d'une adresse calculée manuellement.

Haut niveau

modifier

Génération 3

modifier
  • Langages indépendants du processeur
  • Proches des langues parlées (anglais)
  • Langages procéduraux, descriptions des opérations à effectuer pour résoudre un problème.

Les premiers langages de programmation étaient écrits sur des cartes perforées. Celles-ci ne permettaient pas de coder les lettres en minuscules, ce qui explique que les mots-clés des premiers langages de programmation soient en capitales (Fortran, COBOL, Basic, Pascal).

Langages : C, Pascal, Fortran (Formula Translation), Cobol (Common Business Oriented Language), Basic, Wlangage

Génération 4

modifier
  • Langages descriptifs
  • Description de ce que l’on désire faire mais pas de la manière de le faire
  • Très fortement lié à un domaine (base de données, tables de calcul)

Langages : Uniface, Informix, Oracle, Lotus

Génération 5

modifier
  • Langages descriptifs pour la programmation de systèmes experts

Langages : Prolog

Génération 6

modifier
  • Orienté objet
  • Toutes les informations nécessaires à la résolution d’un problème sont réunies dans un objet

Langages : Ada, C++, C#, Delphi, Eiffel, Java, Object Pascal, PHP, Python, Smalltalk

Références

modifier
  GFDL Vous avez la permission de copier, distribuer et/ou modifier ce document selon les termes de la licence de documentation libre GNU, version 1.2 ou plus récente publiée par la Free Software Foundation ; sans sections inaltérables, sans texte de première page de couverture et sans texte de dernière page de couverture.