Lexique


Bienvenue sur le lexique ITExpert, une page fourre-tout où j'ai défini un paquet de concepts que j'utilise fréquemment dans mes articles.

Comme tous les métiers techniques, le développement logiciel pullule de termes complexes ou ultra-spécifiques, qui ne sont pas forcément familiers à tout le monde, et qui changent de définition selon les personnes…

Cet article a pour but de leur donner un sens afin que vous, chers lecteurs, puissiez être à l'aise avec eux lorsque vous les croisez dans mes autres articles.

Avant de commencer, quelques avertissements :

  • Cet article se place strictement dans un contexte de développement logiciel. Certains de ces termes existent dans des contextes différents avec une autre définition, mais je n'en parlerais pas ici.
  • Certains de ces termes sont si flous que j'ai dû bricoler une définition maison, attendez-vous donc à un peu de subjectivité (les termes en question seront mis en rouge). Je ne prétends pas leur donner un sens définitif, et si vous n'êtes pas d'accord avec un d'entre eux, on peut en discuter tout en bas.

Incontournables

Logiciel

Alias : programme, software

Ensemble logique d'instruction permettant d'exploiter la force de travail d'un ordinateur.

Le terme est très générique puisqu'il inclut à peu près tout ce qui découle d'une codebase (et de ses dépendances). En vrac :

Le terme programme est généralement utilisé pour les petits logiciels comme les scripts. Mais la frontière entre les deux est si floue que c'est difficile de dire qu'est-ce qui est quoi (paradoxe sorites). Donc dans le doute, je préfère les mettre au même niveau.


Système d'exploitation

Alias : operating system, OS

Logiciel ou ensemble de logiciels qui s'interfacent entre le matériel de l'ordinateur (processeur, mémoire vive…), et le reste des logiciels installés (dont les nôtres).

C'est la clef de voute qui contrôle absolument tout, et qu'il faut prendre en compte lors du développement logiciel pour le choix des technologies à utiliser, mais aussi pour l'étude du marché.

Quelques exemples :


Application

Alias : logiciel applicatif, appli, app

Type de logiciel destiné à être directement utilisé par un humain via une interface graphique ou une invite de commande (CLI).


Développement logiciel

Alias : programmation, software development, software engineering

Conception et réalisation de logiciels.


Codebase

Alias : code source

Ensemble du code maitrisé par les développeurs lors de la réalisation d'un logiciel. Le code source des bibliothèques, frameworks et autres dépendances externes n'en fait pas partie.


Système de fichiers

Alias : file système

Arborescence de fichiers sur un média de stockage.

En général, on insinue qu'il possède une racine et qu'on ne parle pas de ce qu'il y a au-dessus.

Par exemple : quand on parle du système de fichier d'une codebase, on se place dans le répertoire qui contient tout le code en ignorant le reste.


Client (logiciel)

Lorsqu'un logiciel dépend d'un autre, on dit qu'il est son client.

Le terme est utilisable dans une tonne de contextes :

Ambiguïté : le terme est parfois utilisé au niveau des éléments de code (exemple : classe cliente d'une autre classe).

Sur ce schéma, le navigateur est le client du serveur web, et le serveur web est le client du serveur de base de données.

Serveur (logiciel)

Logiciel dont le but est de distribuer des données ou recevoir des requêtes. Son but est littéralement de servir ses clients.

Par exemple : un serveur web reçoit des requêtes HTTP et émet des réponses HTTP. Tout le reste se fait en interne.

À ne pas confondre avec un serveur matériel, qui est simplement un ordinateur ayant pour but d'héberger des serveurs logiciels (entre autres).

Logiciels

Environnement

Contexte informatique dans lequel un logiciel s'exécute, et dont il dépend forcément. Les principaux acteurs sont :

  • Le système d'exploitation
  • L'architecture du processeur (x64, x86, ARM…)

Application de bureau

Type d'application destinée à un environnement de bureau (PC fixes, PC portables et autres écrans larges). Elle peut interagir directement avec l'OS (application native), ou passer par une interface (comme une machine virtuelle).

Les OS principaux sur PC sont Windows (Microsoft), macOS (Apple) et Linux (libre).


Application mobile

Type d'application destiné à un environnement mobile (smartphones et tablettes). Le principe est le même que pour les applications de bureau, les seules différences sont :

  • La taille de l'écran (plus de contraintes sur mobile)
  • Les systèmes d'exploitation

Les OS principaux sur mobile sont Android (Google) et iOS (Apple).


Application web

Type d'application distribuée par un serveur web sous forme de pages lisibles par un navigateur. Elles n'ont pas besoin de s'adapter à un OS, mais doivent suivre un ensemble de normes pour fonctionner de la même manière avec tous les navigateurs.


CLI

Alias : Command Line Interface, interface en lignes de commande

Type d'application qui ne possède pas d'interface graphique, et dont les fonctionnalités s'utilisent directement depuis une invite de commandes.

Ces applications sont destinées principalement aux développeurs ou aux administrateurs systèmes et réseaux, et possèdent une documentation riche (j'espère).

Quelques exemples :


Application embarquée

Type d'application optimisée pour un type de matériel aux fonctionnalités réduites, tel que des microcontrôleurs. Elles servent surtout à créer des automates, comme des robots, machines industrielles, systèmes de domotique…


Microcontrôleur

Ordinateur miniature fixé sur un circuit imprimé. Il permet de résoudre des tâches très spécifiques relevant de la programmation d'applications embarquées.


Script

Type de petit logiciel qui s'exécute manuellement ou sur appel d'un évènement, comme :

  • Connexion à une session
  • Tous les jours à minuit
  • Quand un capteur détecte une présence…

Il s'exécute pendant une durée limitée, et s'arrête dès qu'il a terminé son travail.

Il tourne généralement en arrière-plan, mais peut parfois demander de l'interaction à l'utilisateur (mais c'est à éviter le plus possible)


Service (type de logiciel)

Type de logiciel qui s'exécute en tâche de fond, sans aucune interaction avec l'utilisateur. Ils interagissent énormément avec l'OS.


Bibliothèque

Alias : library

Type de logiciel dont le but est de servir de dépendance directe à un autre logiciel, typiquement, pour faciliter sa création en apportant des fonctionnalités génériques que les développeurs n'auront pas besoin de refaire.

Une codebase qui dépend de 3 bibliothèques : une pour la sérialisation/désérialisation en JSON, une pour les requêtes HTTP et une pour la connexion à une base de données MySQL.

Framework

Alias : cadriciel

Type de logiciel qui sert de modèle architectural à un autre logiciel. Il va apporter son lot de fonctionnalités, mais aussi créer un cadre de travail pour inciter les développements à coder proprement.

Exemples connus :


API REST

Type de logiciel ayant pour but de distribuer des données et recevoir des requêtes en respectant la norme REpresentational State Transfert (REST), qui apporte les contraintes suivantes :

  • Client-serveur : les données doivent être transmises par un serveur centralisé et ont pour but d'être consommées par un client.
  • Sans état : les données doivent transiter par un protocole sans état, où toutes les requêtes, même identiques, sont indépendantes les unes des autres.
  • Avec mise en cache : les clients peuvent mettre en cache les réponses, afin d'optimiser les performances si une requête retourne toujours la même chose.
  • En couche : les données sont indépendantes du serveur, ce qui fait que le client ne peut pas savoir si le serveur les a générées lui-même ou simplement relayées.
  • Interface uniforme : les données sont structurées de manière à pouvoir être consommées simplement par le client, via des spécifications telles que HTML, JSON, XML

Généralement, les API REST s'exécutent sur des serveurs web recevant des requêtes HTTP, et sont donc directement utilisables depuis un navigateur.

Une API REST documentée avec Swagger. Comme vous pouvez le voir, c'est juste des fonctions accessibles depuis HTTP, et qui retournent un résultat en JSON.

Client lourd

Catégorie d'application qui nécessite d'être installée sur le matériel de l'utilisateur pour fonctionner.

Elles permettent d'avoir moins de contraintes de bande passante, car une fois installées, la grande majorité s'exécute en local, mais elles sont plus difficiles à déployer, car pour publier une nouvelle version, il faut mettre à jour toutes les applications sur tous les postes.

Elle s'oppose au client léger.


Client léger

Catégorie d'application installée sur un serveur, et dont les utilisateurs récupèrent les parties au fur et à mesure qu'ils en ont besoin.

Une application web est forcément en client léger, car un utilisateur ne charge pas toutes les pages d'un coup, mais uniquement celles auxquelles il accède.

Elles sont beaucoup plus simples à déployer, car il suffit de mettre à jour l'application sur le serveur pour publier une nouvelle version, mais elles demandent beaucoup plus d'échanges entre le serveur et le client, ce qui peut poser des problèmes de performances, notamment pour les petites connexions internet.

Elle s'oppose au client lourd.


Client hybride

Catégorie d'application dont une partie est installée sur un serveur et l'autre sur le matériel de l'utilisateur, dans des proportions qui peuvent varier.


Paquet

Alias : package

Catégorie de logiciel diffusée dans un seul fichier d'archive, et qui est ensuite décompressé et consommé par un autre logiciel. Quand on parle de paquet, on fait généralement référence à des bibliothèques.

La plupart des paquets sont référencés sur des sites web appelés dépôts qui en contiennent des centaines de milliers, tel que :

Rien que ça…

Multiplateforme

Alias : cross-plateform.

Catégorie de logiciel pouvant s'exécuter sur plusieurs OS avec une même codebase.

Il y a plusieurs méthodes pour que cela fonctionne :

  • Avoir un environnement d'exécution entre l'OS et le logiciel. C'est la stratégie la plus simple, mais pas la plus performante. Les exemples les plus connus sont :
  • Traduire le code du logiciel en code natif à l'OS. C'est la solution la plus performante, mais aussi la plus difficile à mettre en place.

Application native

Application adaptée au système d'exploitation de la machine et qui n'a pas besoin de logiciel intermédiaire pour s'exécuter. Elle bénéficie d'une meilleure intégration à l'environnement et de meilleures performances, mais est plus difficile à porter vers d'autres plateformes.


Serveur web

Logiciel permettant de distribuer des ressources grâce au protocole HTTP. Il peut s'agir de texte, images, vidéos, pages web

Quelques exemples :


Serveur de base de données

Alias : système de gestion de bases de données, SGBD, DBSM

Logiciel permettant d'héberger une base de données et d'interagir avec via un système de requêtes/réponses.

Une base de données découle forcément d'un serveur de base de données, et pas l'inverse.

Quelques exemples :

Aucun protocole entre la base de données et le serveur, car elle fait partie intégrante de celui-ci.

Alias : web browser

Application permettant de récupérer et de lire des ressources sur le web grâce au protocole HTTP, notamment des pages web.

En réalité, les navigateurs modernes font beaucoup plus que ça, ils peuvent lire des images, des fichiers audio, vidéo, PDF ou parcourir un système de fichiers

Quelques exemples :


Page web

Alias : page HTML

Fichier en HTML qui contient une interface graphique codée en HTML pouvant être retranscrite par un navigateur web.

Sur quasiment tous les navigateurs, son code peut être lu en appuyant sur F12.

Une page web à gauche et le code qui la représente à droite. Notez que ce code n'est pas nécessairement le code source de la page, mais c'est celui que le navigateur reçoit et interprète.

Machine virtuelle

Logiciel qui sert d'interface entre un logiciel et l'OS qui va l'exécuter. C'est la stratégie la plus rependue pour faire du multiplateforme.

Quelques exemples :

En d'autres termes, une machine virtuelle fonctionne comme un adaptateur. L'inconvénient est qu'il faut l'installer sur sa machine pour exécuter les programmes, comme Java pour jouer à Minecraft (le vrai).


Sources de données

Source de données

Endroit où un logiciel va venir récupérer des données persistantes pour les consommer ou les distribuer. Elles peuvent être :

Un disque dur n'est pas considéré comme étant une source de donnée étant donné qu'à peu près n'importe quelle source est installée sur un disque dur.


Persistance des données

Fait d'enregistrer des données dans une source pour pouvoir les réutiliser plus tard ou pour les archiver.



Base de données

Alias : BDD, database, DB, base (ambiguë)

Système de fichier particulier entièrement géré par un serveur de base de données, qui permet de stocker, d'organiser et de récupérer des données de manière flexible et performante.

En développement logiciel, c'est le système de persistance de données le plus incontournable.


Base de données relationnelle

Type de base de données dans laquelle les données sont organisées en tables interconnectées.

Elles mettent l'accent sur :

  • La cohérence des données en uniformisant leur structure.
  • Les relations entre elles afin de dresser une connexion entre toutes les tables de la base.
  • La limitation des redondances pour une maintenance plus facile et une BDD très légère.

RDBSM

Serveur de base de données relationnelle


SQL

Alias : Structured Query Language

Langage normé par l'ISO permettant de coder des requêtes à destination d'une base de données relationnelle.

Dû aux limitations techniques du langage, tous les serveurs de base de données relationnelles possèdent leur propre implémentation de SQL, mais le cœur est (quasiment) le même partout.

Par abus de langage, quand on parle de SQL, on parle en réalité de n'importe quelle implémentation, et non pas de l'origine du langage, bien que leurs spécifications soient un peu différentes.


Base de données NoSQL

Base de données non relationnelle, et qui n'est donc pas adaptée au langage SQL. On en retrouve 4 grands types :


Programmation

Langage de programmation

Dialecte issu d'une spécification permettant de programmer des logiciels et de les rendre exécutables via de la compilation ou de l'interprétation.

Quand on parle de langage, on l'associe toujours à son compilateur ou interpréteur de référence, car un langage seul n'a rien de concret, c'est juste une syntaxe.

Par exemple, quand on dit que Rust est un langage très performant, on parle en réalité de son compilateur, car il est tout à fait possible de créer un compilateur Rust tout pourri.


Compilation

Stratégie d'exécution d'un programme consistant à transformer une codebase en un logiciel dit compilé, pouvant être lu par le client qui l'exécute.

Il peut s'agir de :

Le logiciel servant à compiler des programmes s'appelle le compilateur.


Transpilation

Alias : compilation source à source

Compilation du code d'un langage en un autre lisible par l'être humain.

C'est une pratique très fréquente dans le monde JavaScript avec des langages comme TypeScript ou CoffeeScript transpilés en pur JavaScript. Cela permet d'avoir un langage avec des fonctionnalités modernes dans la codebase, mais de le rendre compatible avec tous les navigateurs.

Le logiciel servant à transpiler des programmes s'appelle le transpileur, transcompilateur ou encore compilateur source à source.


Interprétation

Stratégie d'exécution d'un programme consistant à avoir un logiciel qui lit et traduit le code au fur et à mesure en code machine ou intermédiaire.

À la différence de la compilation, tout le programme n'est pas traduit d'un coup, mais au fur et à mesure. Il n'y a pas de version compilée, tout se passe dans le code source et dans la mémoire vive.

Le logiciel servant à interpréter des programmes s'appelle l'interpréteur.


État

Alias : state

Ensemble des informations persistantes dans un système, y compris celles qui se réinitialisent quand le programme est redémarré. Par exemple :

Si l'une de ces données est altérée durant l'exécution, on dit qu'il y a eu un changement d'état.


Effet de bord

Alias : effet secondaire, side effect

Changement d'état d'un programme provoqué par une de ses instructions, volontairement ou non.


Immuabilité

Alias : imutability

Fait d'avoir une variable dont on ne peut jamais changer la valeur.

C'est une bonne pratique, car ça protège davantage le programme. On s'assure que si la variable était dans un état stable au début, elle y reste.


État stable

État dans lequel le programme peut s'exécuter sans rencontrer de problème.

Garantir un état stable est un des objectifs principaux de l'architecture logicielle, qui s'atteint en :


Paradigme de programmation

Grand principe de programmation implémenté par un langage. Un paradigme peut contenir plusieurs sous-paradigmes, et un langage peut en implémenter plusieurs.


Programmation impérative

Paradigme désignant un logiciel construit en totale isolation de son environnement afin d'éviter tout changement d'état.

Par souci de praticité, la plupart des langages dits impératifs laissent la possibilité d'altérer l'état du programme via des instructions spéciales, mais leur utilisation est fortement découragée.


Programmation déclarative

Paradigme désignant un logiciel ayant la possibilité de modifier son état au cours de son exécution.


Programmation fonctionnelle

Alias : PF, FP

Paradigme de programmation impérative désignant des logiciels construits à base d'enchainement et d'imbrication de fonctions prenant des paramètres d'entrée et sortant un résultat, le tout sans aucun effet de bord (idéalement).

L'objectif est essentiellement de construire des logiciels fiables en se basant sur des règles extrêmement simples (issues du monde mathématique), et prédictibles en limitant, voir en éliminant les changements d'état.


Programmation générique

Paradigme désignant un programme où l'on peut passer des types à des fonctions ou à d'autres types.

Cela permet de créer des éléments de code qui peuvent fonctionner de la même manière avec à peu près n'importe quel type et ainsi limiter la duplication de code.

Cependant, elle ne fonctionne que si l'objet générique n'est que très peu utilisé. En effet, étant donné qu'il a un type indéfini, il est impossible de lire sa valeur ou d'accéder à ses propriétés.

Cas d'utilisation : imaginons que l'on veut créer un nouveau type de collection. L'idée est de lui donner un type générique de sorte qu'on puisse la remplir avec n'importe quoi (primitives, objets, autres collections…). Cela fonctionne, car une collection ne fait que stocker des données sans nécessairement avoir besoin de savoir quoi que ce soit sur ce qu'elle stocke.

class Stack<T>
{
    private readonly List<T> Items;

    public Stack()
    {
        Items = new List<T>();
    }

    public void Push(T item)
    {
        Items.Add(item);
    } 

    public T Pop()
    {
        if(Items.Count == 0)
        {
            return default;
        }
        else
        {
            var res = Items[^1];
            Items.RemoveAt(Items.Count - 1);
            return res;
        }
    }

    public T Top()
    {
        if(Items.Count == 0)
            return default;
        else
            return Items[^1];
    }
}

var intStack = new Stack<int>();
var stringStack = new Stack<string>();
var pointStack = new Stack<Point>();
var dishStack = new Stack<Dish>();

Évènement

Signal envoyé par un logiciel permettant de lancer une fonction ou un script.

Par exemple : l'utilisateur clique sur le bouton Démarrer.

On entend parfois dire que les évènements sont les fonctions qui se lancent sur un signal, mais c'est un abus de langage. Pour les distinguer des fonctions « classiques », je préfère les appeler procédures sur évènement.


API

Alias : Application Programming Interface, interface de programmation, interface (ambiguë), interface publique

Ensemble des procédures mises à disposition par un logiciel pour être utilisées depuis l'extérieur.

Typiquement :

  • Une API REST met à disposition un ensemble de procédures exécutables avec HTTP.
  • Une bibliothèque apporte un tas de nouvelles fonctions à une codebase.
  • Un système d'exploitation met à disposition des procédures qui permettent aux logiciels d'interagir avec le matériel…

Ambiguïté : beaucoup utilisent ce terme au sein d'une codebase pour désigner les procédures publiques d'un composant ou d'un élément de code.

Abus de langage : beaucoup utilisent le terme pour désigner une API REST, qui n'est qu'un type particulier d'API.


Composant

Élément de code chargé d'encapsuler une partie du programme et qui sert de dépendance directe à une codebase.

En fonction des langages, la notion de composant ne sera pas la même :

  • En C# ou en Java, les composants ont la forme de fichiers compilés (DLL ou JAR).
  • En PHP ou en JS, les composants sont simplement d'autres fichiers sources.

Un composant peut faire partie de la codebase (composant interne) ou non (composant externe). Dans le second cas, ses fonctionnalités seront généralement moins spécifiques. Les bibliothèques sont des exemples de composants externes.

À ne pas confondre avec composant graphique ni avec module.


Élément de code

Terme générique désignant n'importe quel élément de code réutilisable au sein d'une codebase, donnée ou procédure. En vrac :


Donnée

Élément contenant une ou plusieurs informations à même d'être exploitée par le programme. Exemples :


Procédure

Élément contenant une suite d'instructions à même d'être exécutée par le programme. Selon les contextes, elles peuvent prendre des paramètres d'entrée, sortir un résultat, et effectuer ou non des effets de bord. Exemples :


Comportement

Alias : behavior

Ensemble des procédures d'un élément de code.


Programmation Bas Niveau

Niveau d'abstraction (langage de programmation)

Gradient sur lequel on situe des langages de programmation pour dire s'ils représentent fidèlement le comportement de l'ordinateur à l'exécution, ou pas.

Par exemple :

  • L'assembleur est un langage de bas niveau, car il représente fidèlement les instructions envoyées au processeur, mais de manière textuelle au lieu de binaire.
  • Java est un langage de haut niveau, car il se concentre davantage sur des concepts servant à aider les développeurs à réaliser le programme. Par exemple, le typage statique ou la programmation orientée objet qui n'ont aucune signification pour le processeur.
  • C se trouve entre l'assembleur et Java, car même s'il utilise déjà pas mal de concepts de haut niveau, il permet aux développeurs de garder une certaine maitrise du matériel et la mémoire vive.

Aucun niveau d'abstraction n'est mieux que l'autre, c'est simplement un critère à prendre en compte lorsqu'on choisit un langage.

Dans une immense majorité des cas, un langage de haut niveau ferra l'affaire, car ils sont généralement moins prise de tête. Les langages de bas niveau sont surtout réservés à la programmation système ou au développement de logiciels à très hautes performances.


Instruction

Ordre indivisible donné au processeur. C'est la plus petite action qu'un logiciel puisse faire, et il peut en exécuter des millions à la seconde.

Généralement, on adapte la définition au langage de programmation que l'on utilise, car dans les langages modernes, le moindre truc simple est transcrit en un tas d'instructions.

Par exemple, on aura tendance à dire que « a = b » est une instruction même si dans la pratique, ce n'est pas tout à fait vrai.

De la même manière, un appel de fonction est généralement considéré comme étant une seule instruction malgré la complexité qui se cache derrière.


Code machine

Code directement exécutable par un ordinateur sans passer par un intermédiaire.

Dans la pratique, ce n'est que du binaire, mais on peut le représenter différemment en groupant les bits. La forme hexadécimale étant la plus fréquente.

10111000    00100001 00001010 00000000 00000000
10100011    00001100 00010000 00000000 00000110
10111000    01101111 01110010 01101100 01100100
10100011    00001000 00010000 00000000 00000110
10111000    01101111 00101100 00100000 01010111
10100011    00000100 00010000 00000000 00000110
10111000    01001000 01100101 01101100 01101100
10100011    00000000 00010000 00000000 00000110 
10111001    00000000 00010000 00000000 00000110
10111010    00010000 00000000 00000000 00000000
10111011    00000001 00000000 00000000 00000000
10111000    00000100
00000000    00000000 00000000 11001101 10000000
10111000    00000001 00000000 00000000 00000000
11001101    10000000
Binaire - base 2 (un nombre = 1 bit).
b8    21 0a 00 00
a3    0c 10 00 06
b8    6f 72 6c 64
a3    08 10 00 06
b8    6f 2c 20 57
a3    04 10 00 06
b8    48 65 6c 6c
a3    00 10 00 06
b9    00 10 00 06
ba    10 00 00 00
bb    01 00 00 00
b8    04 00 00 00
cd    80
b8    01 00 00 00
cd    80
Hexadécimale - base 16 (un nombre = 4 bits).
¸    ! LF NUL NUL
£    FF DLE NUL ACK
¸    o r l d
£    BS DLE NUL ACK
¸    o , SP W
£    EOT DLE NUL ACK
¸    H e l l
£    NUL DLE NUL ACK
¹    NUL DLE NUL ACK
º    DLE NUL NUL NUL
»    SOH NUL NUL NUL
¸    EOT NUL NUL NUL
Í    P
¸    SOH NUL NUL NUL
Í    P
Extended ASCII - base 256 (un caractère = 8 bits = 1 octet). Certains caractères (tous ceux qui ont 2 lettres ou plus) sont invisibles, comme des espaces (SP) ou des sauts de page (FF). Je les ai remplacés par leurs abréviations communes.

Plus d'informations sur ce code ici.

Attention : beaucoup utilisent le terme pour désigner l'assembleur. Ce n'est pas la même chose, car l'assembleur est un langage intermédiaire qui s'assemble en machine code.


Code intermédiaire

Alias : bytecode

Code qui se trouve à l'intermédiaire entre le code source et le code machine.

Son but est principalement d'être pris en charge par un autre programme qui va à son tour le compiler/interpréter/assembler en code machine, ou bien en un autre code intermédiaire.

Le langage intermédiaire de référence est l'assembleur.

.method private hidebysig static void  Main(string[] args) cil managed
{
    .entrypoint
    .maxstack  2
    .locals init (int32 V_0, bool V_1)
    IL_0000:  nop
    
    IL_0001:  ldc.i4.0
    IL_0002:  stloc.0
    IL_0003:  br.s       IL_000b
    IL_0005:  nop
    
    IL_0006:  ldloc.0
    IL_0007:  ldc.i4.1
    IL_0008:  add
    IL_0009:  stloc.0
    IL_000a:  nop

    IL_000b:  ldloc.0
    IL_000c:  ldc.i4.s   10
    IL_000e:  clt
    IL_0010:  stloc.1
    IL_0011:  ldloc.1
    IL_0012:  brtrue.s   IL_0005

    IL_0014:  ret
}
Un exemple de MSIL, le langage intermédiaire de .NET. C'est dans ce langage que les programmes en C#, VB.NET ou F# compilent, et ce code est ensuite interprété par le .NET Runtime.
static void Main(string[] args)
{
    int i = 0;
    while(i < 10)
    {
        i++;
    }
}
Code source

Assembleur

Alias : assembly, ASM

Langage de programmation représentant fidèlement les instructions faites au processeur lors de l'exécution d'un programme. Il est le langage le plus bas niveau destiné à un être humain.

Dans la réalité, l'assembleur n'est pas vraiment un langage, mais une manière de structurer un langage. Chaque architecture de processeur possède sa version d'assembleur, tout comme chaque serveur de base de données possède sa version de SQL. Mais par abus de langage, quand on parle d'assembleur, on parle de toutes ses implémentations confondues.

Il est certainement le langage intermédiaire le plus utilisé. Rares sont les développeurs qui le maitrise, mais nombreuses sont les codebases qui passent d'abord par l'assembleur avant le code machine lors de la compilation.

square:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     eax, DWORD PTR [rbp-4]
        imul    eax, eax
        pop     rbp
        ret
Compilation d'une fonction C en assembleur x86-64, via godbolt.org (compilateur GCC 11.1).
int square(int num) {
    return num * num;
}
Code source

Assemblage

Compilation du code d'un langage en code machine, directement exécutable par l'ordinateur.

Dans la pratique, c'est extrêmement compliqué, car les langages de programmation modernes ne s'apparentent pas du tout à la manière dont l'ordinateur fonctionne, ils simplifient le fonctionnement réel afin de les rendre plus lisibles par nous.

Des concepts aussi simples que les conditions ou les boucles n'existent même pas pour un ordinateur.

L'assemblage est surtout destiné aux langages de très bas niveau, notamment l'assembleur qui représente assez fidèlement la manière dont les instructions sont exécutées.

C'est pour cela que beaucoup de langages compilent d'abord en assembleur, et celui-ci est ensuite assemblé pour rendre le logiciel exécutable par la machine.

Le logiciel servant à assembler des programmes s'appelle l'assembleur, à ne pas confondre avec le langage du même nom.


Type valeur

Donnée représentée par une valeur stockée dans la pile d'exécution. Elle est récupérable directement par le programme.

Les variables locales, notamment les primitives et les collections avec un nombre d'éléments déterminé sont souvent de type valeur, mais il y a des exceptions.


Type référence

Type de donnée représenté par des adresses mémoires dans la pile d'exécution, pointant vers leurs réelles valeurs dans la heap. Récupérer ces valeurs nécessite de passer par des pointeurs.

Les objets, collections avec un nombre d'éléments indéterminé et variables globales sont souvent de type référence, mais il y a des exceptions.


Pile d'exécution

Alias : pile mémoire, pile d'appel, pile (ambiguë), stack (ambiguë), call stack, memory stack

Portion de la mémoire vive de taille définie, allouée pour un seul thread et accessible par celui-ci sans pointeurs. Si le programme est exécuté par plusieurs threads, chacun possède sa pile d'exécution.

Elle est implémentée sous la forme d'une pile (collection) et bénéficie d'une meilleure gestion de l'allocation et la désallocation des variables dans la mémoire vive afin d'éviter les fuites mémoires.

On y retrouve généralement des variables locales (types valeur) ainsi que des pointeurs vers la heap (type référence).


Thread

Alias : fil d'exécution, tâche

Microprocessus chargé d'exécuter les instructions d'un programme. Quand vous lancez un logiciel, vous avez forcément un thread qui tourne pour le faire fonctionner.

Plusieurs threads peuvent parcourir un seul programme, c'est le cas par exemple pour les serveurs web où à chaque fois qu'ils reçoivent une requête, ils créent un thread pour s'en occuper, et une fois la réponse envoyée, le thread disparait. Ça permet de traiter instantanément toutes les requêtes au lieu d'avoir une file d'attente.

Tous les threads ont leur propre pile d'exécution, mais partagent la même heap. Autrement dit, ils peuvent se partager les données de types référence, mais pas de type valeur.


Pile

Alias : stack

Type de collection fonctionnant sur le principe LIFO (Last In First Out = dernier arrivé premier sorti) de la manière suivante :

  • On ajoute des données qu'en haut de la pile (push).
  • On retire des données qu'en haut de la pile (pop).
  • On peut lire la valeur en haut de la pile sans la modifier (top).

Pour prendre une analogie, sur une pile d'assiettes, on ne peut récupérer que celle qui est au-dessus, et si l’on en veut une en particulier, il faut vider la pile jusqu’à l'atteindre. Idem pour ajouter une assiette à la pile.

Ambiguïté : le terme est parfois utilisé pour désigner la pile d'exécution, qui n'est qu'un exemple concret de pile.


Heap (mémoire vive)

Alias : mémoire dynamique

Portion de la mémoire vive de taille indéfinie, partagée par tous les threads exécutant le programme. Pour y accéder, il faut passer par des pointeurs stockés dans la pile d'exécution.

Elle ne bénéficie pas d'encadrement pour l'allocation et la désallocation des variables ce qui oblige soit :

  • De le faire à la main, comme en C ou C++.
  • D'utiliser un garbage collector, un programme rattaché à l'environnement d'exécution qui est chargé de nettoyer la heap au fur et à mesure, comme en Java ou .NET.

On y retrouve généralement les variables globales, les objets et les collections, en particulier celles dont leur taille n'est pas définie à l'avance.

Chaque thread accède aux valeurs dans la heap grâce à des pointeurs stockés dans leur pile d'exécution.

Ambiguïté : le terme heap désigne aussi un type de collection. Mais contrairement à la pile d'exécution (mémoire vive) qui est effectivement implémentée par une pile (collection), la heap (mémoire vive) n'est pas implémentée par une heap (collection).


Pointeur

Variable stockée dans la pile d'exécution qui contient une adresse mémoire pointant vers une donnée stockée dans la heap.

Selon les langages, cette notion peut être prise en charge manuellement par le développeur (C, C++…) ou automatiquement par le langage (Java, .NET…).


Fuite mémoire

Alias : memory leak

Dans la mémoire vive, phénomène quand des données ne sont pas désallouées même quand le programme a fini de l'utiliser.

Le problème étant que ça pollue la mémoire vive, et dans le pire des cas, ça peut la surcharger et la corrompre.

La pile d'exécution est relativement bien protégée des fuites mémoires, la majorité a lieu dans la heap.

int foo()
{
  char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
  bool b = true; // Allocated on the stack.
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];

    //Create 500 bytes on the heap
    pBuffer = new char[500];

   }//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;
Code de Brian R. Bondy sur stackoverflow.com

Programmation Procédurale

Programmation procédurale

Alias : PP

Paradigme de programmation déclarative désignant un logiciel construit à base d'appels de procédures pouvant être imbriquées les unes dans les autres.

C'est un paradigme si simple qu'il est implémenté par la quasi-totalité des langages déclaratifs, y compris ceux dits orientés objet qui sont généralement procéduraux avant tout.


Composition

Quand un type A contient un autre type B non primitif, on dit que A est composé de B.

class Point
{
    public int X;
    public int Y;
}

class Line 
{
    public Point A;
    public Point B;
}
Une ligne composée de deux points.

Type

Élément servant de modèle à la création d'objets en définissant sa structure.

class Point
{
    public int X;
    public int Y;

    public bool Equals(Point other)
        => X == other.X && Y == other.Y;

    public string ToString()
        => $"({X},{Y})";
}

Primitive

Donnée indivisible, qui n'en contient aucune autre. Par exemple :

  • Nombre entier
  • Nombre décimal
  • Caractère
  • Chaine de caractères…

Constante

Primitive qui ne change jamais. Elle peut être nommée ou non (constante magique).

Bien qu'elle s'apparente à une variable, elle n'est pas considérée comme telle à la compilation, mais simplement comme une donnée codée en dur. Son nom ne sert qu'à la rendre lisible par les développeurs.

const int monthsInYear = 12;
// monthsInYear = 13 // <= Impossible

Variable

Conteneur d'une donnée susceptible de changer au cours de l'exécution du programme. Il peut s'agir :

double salary = 3200;
salary *= 0.05; // 3360

Collection

Alias : tableau (ambiguë), liste (ambiguë), array (ambiguë)

Variable qui peut en contenir plusieurs autres du même type.

Par exemple, une collection de nombres entiers peut en contenir plusieurs (1, 3, 4…) alors qu'une primitive ne peut en contenir qu'un seul.

string[] fruits = new string[] { "Orange", "Apple", "Pear" }

Objet

Alias : instance

Variable qui contient une structure de données pouvant contenir plusieurs primitives, collections ou autres objets.

En programmation orientée objet, ils peuvent aussi contenir des méthodes.

Employee employee = new Employee
{
    Firstname = "Thomas",
    Lastname = "Edison",
    Age = 84,
};

Champ

Alias : field

Variable qui se trouve à l'intérieur d'un objet.

class Employee
{
    public string Firstname;
    public string Lastname;
    public int Age;
}
Firstname, Lastname et Age sont des champs de Employee.

Procédure

Alias : fonction, routine, sous-routine, sous-programme, méthode

Élément contenant une suite d'instructions exécutable par le programme sur appelle. Selon les contextes, elles peuvent prendre des paramètres d'entrée, sortir un résultat, et effectuer ou non des effets de bord.

En fonction des contextes, le terme peut différer. Par exemple :

int Square(int value) 
    => value * value;

int result = Square(2); // 4
Une fonction qui prend un paramètre (int) et qui retourne un résultat (int).

Paramètre de fonction

Variable locale à une fonction, définie dans sa déclaration et assignée à son appel, avant même qu'elle commence à s'exécuter.

int Square(int value) 
    => value * value;

int result = Square(2); // 4
Le paramètre value est local à Square, il s'initialise avec la valeur qu'on lui donne pendant l'appel (2), et à la fin de la fonction, il n'existe plus.

Structure de données

Alias : composite

Type pouvant contenir plusieurs données, contrairement à un type primitif.

En programmation orientée objet, le terme sert à désigner les classes sans méthodes.

class Point
{
    public int X;
    public int Y;
}
Une structure contenant 2 champs.

Ambiguïté : dans le langage C++, une structure est une classe dont les éléments sont publics par défaut. C'est une confusion introduite par le langage.

Ambiguïté : dans le langage C#, une structure est une classe de type valeur, là où une classe normale est de type référence. C'est une confusion introduite par le langage.


Déclaration (fonction)

Création d'un élément de code dans la mémoire vive en déclarant au programme ce qu'il aura besoin de savoir quand il l'utilisera, c’est-à-dire :

public int Square(int number);
Déclaration d'une fonction avec sa visibilité (public), son type de retour (Employee), son nom (Get) et ses paramètres (int id).

Implémentation (fonction)

Code qui va s'exécuter à l'appel d'une fonction.

Le code qui appelle la fonction se fiche complètement de l'implémentation, il a juste besoin de connaitre les types de paramètres d'entrées et le type de la valeur de retour. De ce fait, les fonctions éliminent naturellement le couplage entre leur implémentation et le reste du programme.

C'est une des raisons pour laquelle le polymorphisme fonctionne.

public int Square(int number)   // Declaration
    => number * number;         // Implementation

Signature de fonction

Élément qui permet de distinguer une fonction d'une autre. Généralement, la signature prend en compte :

public int Square(int number); // Signature : Square(int)

Surcharge

Fait d'avoir plusieurs fonctions avec les mêmes noms, mais pas les mêmes implémentations. Elles restent cependant différentiables par leur signature.

class Math
{
    public static int Square(int number) // Signature : Square(int)
        => number * number;

    public static long Square(long number) // Signature : Square(long)
        => number * number;

    public static double Square(double number) // Signature : Square(double)
        => number * number;
}

Programmation Orientée Objet

Programmation orientée objet

Alias : POO, OOP

Paradigme de programmation déclarative désignant un logiciel construit à base de relations entre différents objets ayant chacun une responsabilité au sein du programme.

L'objectif est de représenter la manière dont fonctionne le monde réel, ou chaque objet (livre, meuble, personne, document, processus, n'importe quoi en fait…) est caractérisé par des données et un comportement spécifique.


Classe

En programmation orientée objet, type pouvant contenir à la fois des données et des méthodes.

class Point
{
    public int X;
    public int Y;

    public bool Equals(Point other)
        => X == other.X && Y == other.Y;

    public string ToString()
        => $"({X},{Y})";
}

Méthode

En programmation orientée objet, fonction contenue dans un objet.

class Point
{
    public int X;
    public int Y;

    public bool Equals(Point other)
        => X == other.X && Y == other.Y;

    public string ToString()
        => $"({X},{Y})";
}
Equals(Point) et ToString() sont des méthodes du type Point, inutilisables sans instances de celui-ci.

Visibilité

En programmation orientée objet, caractéristique permettant de définir si un champ ou une méthode est utilisable à l'extérieur d'une classe ou non.

On retrouve généralement 3 niveaux :

  • Publique : l'élément est utilisable à l'extérieur.
  • Protected : l'élément est utilisable uniquement dans les dérivées de la classe.
  • Private : l'élément n'est utilisable que dans la classe en question.

Elle permet de garantir l'encapsulation.

class Person
{
    public string Firstname;
    public string Lastname;

    public int Age 
        => DateTime.Now.Year - BirthDate.Year;

    protected string DebugName;

    private DateTime BirthDate;
}
Firstname et Lastname sont public. DebugName est protégé, car il ne sert qu'à faciliter le débuggage de l'objet et de ses enfants. BirthDate et privé car il ne sert qu'à calculer Age qui, lui, est public.

Note : certains langages tels que C# proposent aussi une visibilité sur les types pour définir s'ils sont utilisables à l'extérieur de leur composant d'origine ou non.


Encapsulation

Bonne pratique visant à exposer le moins de données et de procédures possible.

Le but principal est d'encadrer les développeurs afin de limiter les erreurs humaines et leur impact.

Par exemple : en encapsulant un champ dans une classe, on facilite le débogage, car on sait que s'il rencontre un problème, cela vient forcément de l'intérieur de la classe.

L'encapsulation est respectée en :

Les autres objets ne font qu'utiliser l'interface publique du sujet sans rentrer dans sa complexité. Cette interface publique doit être la plus fine possible.

Accesseur

En programmation orientée objet, méthode dont le but est de récupérer la valeur d'un champ privé.

Le but est de :

  • Pouvoir exécuter une procédure particulière lors de la récupération d'une valeur. Par exemple, la convertir d'un type à un autre.
  • Faire de la lecture seule en ayant un accesseur, mais aucun mutateur.
class Point
{
    private int X;
    private int Y;

    public int GetX()
        => X;
    
    public int GetY()
        => Y;
}
Des accesseurs sans mutateurs, ce qui permet de faire de la lecture seule.

Mutateur

En programmation orientée objet, méthode dont le but est de modifier la valeur d'un champ privé.

Le but est de :

  • Pouvoir exécuter une procédure particulière lors de la modification de la valeur. Par exemple, emmètre un signal (comme pour un évènement).
  • Faire de l'immuabilité pour qu'une variable ne puisse jamais changer de valeur.
class Point
{
    private int X;
    private int Y;

    public int GetX()
        => X;

    public void SetX(int x)
    {
        Y = (x/X);
        X = x;
    }
    
    public int GetY()
        => Y;

    public void SetY(int y)
    {
        X = (y/Y);
        Y = y;
    }
}
Ces mutateurs me permettent de changer la position du point, mais de manière à ce qu'il reste toujours sur la même droite (entre lui et l'origine).

Héritage

En programmation orientée objet, fais qu'un type A contienne tous les champs et méthodes d'un type B. Dans ce cas, on dit que :

  1. B est le parent (ou mère) de A
  2. A est l'enfant (ou fille) de B
  3. A a hérité de B

Contrairement aux idées reçues, l'intérêt n'est pas vraiment de limiter la duplication de code, mais de faire du polymorphisme.

class Person
{
    public string Firstname;
    public string Lastname;
}

class Employee : Person
{
    public string Service;
    public double NetSalary;
}

// Création d'un objet
Employee employee = new Employee
{
    Firstname = "Marc",
    Lastname = "Veron",
    Service = "Informatique",
    NetSalary = 2800,
};

Person person = new Person
{
    Firstname = "François",
    Lastname = "Levalet",
    // Service = "R&D",     => Erreur
    // NetSalary = 2900,    => Erreur
};
Employee hérite de Person.

Polymorphisme

En programmation orientée objet, fait qu'un type enfant puisse se faire passer pour son type parent sans que le programme ne le sache.

L'intérêt est de pouvoir traiter un ensemble d'objets de types différents sans faire de cas par cas. Par exemple : en ayant qu'une fonction au lieu d’une par type.

En revanche, quand on fait du polymorphisme, on est limité aux champs et aux méthodes présentes dans la classe parente.

class Dish { }

class Potato : Dish { }

class Carrot : Dish { }

class Cook
{
    public Dish Cut(Dish dish)
        => //...

    public Dish Fry(Dish dish);
        => //...
}

static class Cuisine
{
    public static Dish CutAndFry(Cook cook, Dish dish)
    {
        dish = cook.Cut(dish);
        dish = cook.Fry(dish);

        return dish;
    }
}
La fonction CutAndFry(Cook, Dish) peut prendre en paramètres des objets de type Dish, mais aussi Potato et Carrot puisqu'ils héritent de Dish.

Interface

En programmation orientée objet, type particulier qui ne contient que des déclarations de méthodes publiques. Aucun champ, aucune implémentation, aucune méthode privée.

Leur objectif est principalement d'être héritées par d'autres classes pour pouvoir faire du polymorphisme.

interface ICook
{
    Dish Cut(Dish dish);
    Dish Fry(Dish dish);
}

class Chef : ICook
{
    public Dish Cut(Dish dish)
        => // Chef implementation...

    public Dish Fry(Dish dish);
        => // Chef implementation...
}

class CookRobot : ICook
{
    public Dish Cut(Dish dish)
        => // CookRobot implementation...

    public Dish Fry(Dish dish);
        => // CookRobot implementation...
}

static class Cuisine
{
    public static Dish MakeFrenchFries(ICook cook)
    {
        Potato potatoes = new Potato();

        potatoes = cook.Cut(potatoes);
        potatoes = cook.Fry(potatoes);

        return potatoes;
    } 
}
Sans interface, il aurait fallu en faire une fonction MakeFrenchFries(Chef) et une MakeFrenchFries(CookRobot) avec quasiment le même code pour prendre en charge les deux possibilités. Ici, on peut faire les deux avec MakeFrenchFries(ICook).

Champ statique

Alias : variable de classe

En programmation orientée objet, champ dont la valeur est partagée par tous les objets de la classe susnommée.

class Process
{
    private static int ActiveProcessesNumber;
    
    public Process()
    {
        ActiveProcessesNumber++;
    }

    ~Process()
    {
        ActiveProcessesNumber--;
    }

    public static int GetActiveProcessesNumber()
        => ActiveProcessesNumber;
}
Le champ ActiveProcessesNumber permet de traquer le nombre d'instance de Process crées dans le programme. À chaque création d'un objet, il s'incrémente, et dès qu'un objet est libéré en mémoire, il se décrémente.

Méthode statique

Alias : méthode de classe

En programmation orientée objet, méthode qui n'a pas besoin d'instance de sa classe pour être exécutée.

Étant donné qu'elle ne peut pas accéder aux méthodes et aux champs normaux, elle se contente souvent d'exécuter des opérations très simples.

class Math
{
    public static int Double(int number) 
        => number * 2;

    public static int Square(int number)
        => number * number;
}

Réseau

Protocole de communication

Spécification technique servant d'interface entre 2 ou plusieurs logiciels afin qu'ils puissent s'échanger des données.

Chaque protocole possède des fonctionnalités bien à lui, mais concernant le transport des données, ils se basent tous sur TCP ou sur UDP.

Les protocoles de communication sont toujours associés à un port (qui n'est pas forcément le même d'une machine à l'autre).


Port

Point d'accès d'un protocole de communication, caractérisé par un nombre allant de 1 à 65535.

La notion de port existe, car une même machine peut faire tourner plusieurs protocoles en même temps. Le numéro de port sert à préciser le protocole avec lequel on veut interagir.

Par exemple : pour lire cette page, votre navigateur a dû envoyer une requête à l'adresse itexpert.fr:443, car c'est ici que mon serveur intercepte les requêtes HTTPS. Mais si vous voulez vous connecter dessus pour accéder à tous ses fichiers, le port sera différent, car ça nécessite un autre protocole.

Les protocoles ont généralement un port par défaut conventionnel, mais rien n'empêche de le changer.


TCP

Alias : Transmission Control Protocol

Protocole de transmission de données, fortement accès sur la fiabilité et l'intégrité de celles-ci.

Ses principales fonctionnalités sont :

  • L'établissement d'une connexion entre l'envoyeur et le receveur pour vérifier s'il existe et s'il est capable de répondre.
  • Des accusés de réception pour savoir si le receveur a bien reçu les données.
  • Un contrôle de l'intégrité des données pour savoir si elles sont toujours intactes à l'arrivée.
  • Un contrôle d'ordre d'arrivée des données, pour ne pas qu'elles se mélangent.
  • Un plan de reprise sur erreur si la transmission a rencontré un problème…

Exemples de protocoles connus utilisant TCP :

  • HTTP (80)
  • SMTP (25)
  • FTP (21)
  • SSH (22)…

UDP

Alias : User Datagram Protocol

Protocole de transmission de données, fortement accès sur la vitesse de transfert.

Il n'implémente quasiment aucune fonctionnalité permettant de garantir l'intégrité des données ce qui en fait un protocole ultra-rapide (car il ne perd pas de temps sur la qualité), mais moins rigoureux que son cousin TCP :

  • Aucune connexion entre l'envoyeur et le receveur, il ne sait même pas si le receveur existe.
  • Pas d'accusés de réception.
  • Aucun contrôle d'intégrité et d'ordre des données.
  • Aucun plan de reprises en cas d'erreur.

Exemples de protocoles connus utilisant UDP :

  • DNS (53)
  • DHCP (67)
  • SNMP (161) (le tueur)
  • VoIP (5060)…

HTTP

Alias : HyperText Transfert Protocol

Protocole de référence pour communiquer avec un serveur web.

Les requêtes sont facilement lisibles par un être humain, et se structurent toujours de la manière suivante.

  • La première ligne qui contient :
    • La méthode HTTP pour que le serveur sache à quel type de requête il a affaire.
    • L'adresse de la ressource à interroger sur le serveur web.
    • La version du protocole.
  • Les entêtes pour configurer le comportement du serveur web. Elles se basent sur des conventions.
  • Le corps qui contient les données à envoyer au serveur web. Il est souvent structuré dans un format standard, comme JSON ou XML.

Les réponses se structurent globalement de la même manière.

Par abus de langage, quand on parle de HTTP, on inclut aussi HTTPS, car pour un développeur, ils se gèrent exactement de la même manière.


HTTPS

Alias : HyperText Transfert Protocol Secure

Protocole HTTP avec chiffrement des requêtes et des réponses par le protocole TLS.


TLS

Alias : Transport Layer Security, SSL/TLS, SSL (ambiguë)

Protocole de chiffrement de données afin de garantir leur transport. Son but est de faire en sorte que si quelqu'un intercepte les données pendant leur transit, il ne puisse pas les lire. Seul le receveur le peut.

Il est principalement utilisé pour chiffrer les requêtes et les réponses HTTP au travers du web (HTTPS), mais aussi pour le transfert de fichiers, mails, messageries instantanées, et parfois les communications vocales et vidéo.

Il est le successeur d'un autre protocole de chiffrement des données nommé SSL, dont on ne parle plus parce qu'il est déprécié, et surtout bien merdique. Comme le protocole est simplement une version améliorée de SSL, il est souvent nommé SSL/TLS.


Architecture logicielle

Architecture logicielle

Alias : conception, design (ambiguë)

Agencement des différents éléments d'une codebase.

Tout comme l'on place les fondations d'un bâtiment de manière stratégique pour faciliter sa construction, l'architecture logicielle organise les éléments d'une codebase pour que sa maintenance évolutive et corrective se déroule rapidement et dans de bonnes conditions.

Une bonne architecture permet d'encadrer les développeurs afin de limiter la dette technique.

L'architecture logicielle peut se faire sur tous les niveaux d'abstraction :

  • Très haut niveau : agencement des modules de l'application et des moyens dont ils communiquent.
  • Très bas niveau : agencement des éléments pour implémenter une fonctionnalité.

Spécification technique

Schématisation de la manière dont un logiciel doit être construit. Elle a pour but d'instaurer un standard strict, afin que le développement ne parte pas dans tous les sens.

Par exemple, un langage de programmation est une spécification qui permet de guider le développement de compilateurs et d'interpréteurs.

Exemple de la spécification du langage C#.

Ambiguïté : le terme spécification est parfois utilisé pour désigner une exigence.


Dépendance

Logiciel qui permet à un autre de fonctionner, dont celui-ci dépend. Elle peut être :

  • Directe, c’est-à-dire strictement liée à la codebase, auquel cas elles doivent être codées dans le même langage (ou compilé de la même manière). C'est le cas des bibliothèques et les frameworks.
  • Indirectes, c'est-à-dire très faiblement liées à la codebase. Elles communiquent généralement avec leur client au travers de protocoles. C'est le cas des API REST (protocole HTTP) et des bases de données (protocole TCP/IP).

Ambiguïté : le terme est parfois utilisé au niveau des éléments de code (exemple : injection de dépendances).


Niveau d'abstraction (analyse)

Position de notre niveau d'analyse sur un gradient allant d'abstrait à concret.

Par exemple :

  • Un diagramme d'architecture modulaire se situe sur un haut niveau d'abstraction, car on ne parle pas du tout de l'implémentation. Tout est ultra-abstrait et simplifié, car le but est de donner une vue d'ensemble du logiciel.
  • Un diagramme d'implémentation se situe sur un bas niveau d'abstraction, car il implique de modéliser la manière dont les éléments de code fonctionnent, allant parfois jusqu’à modéliser les instructions.

Ambiguïté : la définition peut changer en fonction du contexte. Je parle ici du contexte de la conception d'un logiciel.


Frontend

Code source de la partie du logiciel avec laquelle l'utilisateur va interagir directement. Il contient généralement :

À ne pas confondre avec front-office.


Backend

Code source de la partie du logiciel qui s'exécute sur un serveur centralisé et qui prend en charge les requêtes envoyées par le client depuis le frontend.

Elle contient généralement :

  • L'API permettant de recevoir et distribuer des données
  • Les règles métier
  • La communication avec la base de données

À ne pas confondre avec back-office.


Architecture n tiers

Type d'architecture qui met en relations plusieurs logiciels à la chaine, qui se passent des informations de l'un à l'autre, n étant le nombre de logiciels de la chaine

Le modèle le plus connu est l'architecture 3 tiers qui comporte :

Un exemple d'architecture 3 tiers pour une application web.

Flux de contrôle

Imbrication des unités de code dans une codebase.

  • Tout en haut, on retrouve le point d'entrée (fonction main), c'est-à-dire la procédure dans laquelle est contenu tout le programme.
  • Tout en bas, on retrouve les dépendances, où la codebase s'arrête et que tout est délégué à des composants génériques.
Un flux de contrôle inspiré du livre PoEAA. Il s'arrête à la connexion avec la base de données, puisque tout le reste est géré par des bibliothèques (la BDD ne fait pas partie du flux de contrôle).

Module

Partie d'un logiciel prenant en charge une responsabilité bien définie. Par exemple :


Inversion des contrôles

Alias : IoC

Principe architectural visant à inverser le flux de contrôle.

Dans un programme classique, les développeurs réalisent tout le code qui se trouve en haut du flux et laissent le bas du flux à des dépendances qui prennent en charge des fonctionnalités génériques (algorithmes, communication avec une base de données…).

En inversion des contrôles, le haut du flux est géré par un framework, et les développeurs créent des éléments de code en bas du flux que ce framework va utiliser.

Dans la pratique, les développeurs ne s'occupent pas vraiment du tréfonds du flux non plus, il est toujours géré par des dépendances. La grosse différence, c'est qu'ils ne s'occupent plus du haut, ils se contentent du milieu.

Les frameworks web MVC utilisent à fond ce principe. Les développeurs créent des fonctions en suivant la convention du framework, et à l'exécution, celui-ci les utilise afin de générer des API REST.

Un flux de contrôle inspiré du livre PoEAA. L'IoC est reconnaissable au fait que la codebase ressemble souvent à un ensemble d'éléments éparpillées à droite à gauche, mais en réalité, c'est le framework qui recolle tous les morceaux en arrière-plan.

MVC

Alias : modèle-vue-contrôleur, Model-View-Controller

Principe architectural visant à diviser une codebase en 3 modules :

  • Le modèle, qui contient le modèle de domaine, les règles métier et l'accès aux données. C'est le cœur du programme.
  • Les vues, qui contiennent les interfaces graphiques et leurs évènements.
  • Les contrôleurs, qui traitent les requêtes de l'utilisateur en allant piocher dans le modèle, et en lui renvoyant les bonnes vues.
Notez que le client n'interagit JAMAIS directement avec le modèle.

Attention : la plupart des schémas illustrent le modèle MVC de cette manière (voir pire), où la vue se base directement sur le modèle. C'est une horrible pratique puisque cela implique que la vue soit couplée au modèle, et donc plus exposée aux régressions. Je recommande plutôt mon diagramme, celui-ci ou encore celui-là (👌) pour une représentation plus propre et exacte de MVC.


Programmation modulaire

Principe architectural visant à séparer, isoler et distinguer les modules d'un logiciel. Elle permet de rendre une codebase plus compréhensible et de limiter les régressions.

Un diagramme d'architecture modulaire. Il permet de visualiser la manière dont le programme fonctionne, mais aussi à guider le développement en séparant correctement les fonctionnalités.

À ne pas confondre avec programmation orientée composant, la programmation modulaire ne parle pas de code se concentre uniquement sur l'aspect fonctionnel.


Programmation orientée composant

Principe architectural visant à diviser une codebase en composants interconnectés afin d'avoir plus de flexibilité sur la manière de les agencer.

Un diagramme d'architecture orientée composant (non-UML). Les flèches simples représentent les dépendances directes, la flèche HTTP représente la dépendance indirecte entre le client et le serveur.

Monolithe

Type d'architecture où tous les modules sont regroupés dans une seule codebase, sans dépendances indirectes.

Ils sont généralement plus simples à déployer, mais succombent plus facilement aux régressions.


Microservices

Types d'architecture où les modules sont éclatés dans des codebases différentes qui communiquent entre eux via des protocoles.

Ils sont plus isolés ce qui diminue le risque de régressions, mais ils sont plus difficiles à déployer, car ils sont interconnectés, mais pas attachés.


Bonnes pratiques

Bonne pratique

Principe reconnu qui améliore la qualité d'une codebase quand il est appliqué. Les bénéfices peuvent être visibles sous différentes formes, tel que :


Code propre

Alias : clean code

Désigne un morceau de code ou une codebase où les bonnes pratiques de bases ont été appliquées, ce qui le rend facilement lisible et compréhensible.

Il est caractérisé par :

Le code propre est rarement caractérisé par ses bonnes pratiques architecturales, il s'agit plus d'un sentiment quand on lit du code intuitif, que l'on comprend tout de suite même sans aucun contexte.


Nommage

Fait d'attribuer un nom à un élément de code.

Les bonnes pratiques disent que nommage doit être le plus expressif possible de sorte qu'un développeur n'ait pas à regarder son type (pour les données) ou son implémentation (pour les procédures) pour le comprendre.

string GetEmployeeLastname(int employeeId)
{
    //...
}
Exemple de nommage expressif.
// Le nom de qui ? Prenom ou nom de famille ? ID de quoi ?
string GetName(int id)
{
    //...
}
Exemple de nommage ambigu.

Commentaire de code

Code qui n'est pas lu par le compilateur/interpréteur et qui ne sert qu'à donner des informations aux programmeurs.

Les bonnes pratiques disent que les commentaires doivent être les plus clairs et concis possibles, et utiliser qu'au cas où le nommage et le code léger ne suffisent pas à faire parler le code de lui-même.

Parfois, ces commentaires peuvent être lus par des programmes externes, tels que des générateurs de documentation.

// Compose le numéro de série d'un appareil XP22
// Se référer au chapitre 2.2 du guide produit
string GetXP22SerialNumber(int employeeId)
{
    //...
}
Les commentaires sont particulièrement efficaces sur les éléments de code qui relèvent du domaine métier, car ils peuvent porter à confusion pour les non-connaisseurs, et sont difficiles à vulgariser.

Code léger

Alias : light code

Bonnes pratiques visant à rendre le code le plus court et aéré possible. Cela peut se faire en :

  • Ayant un nombre maximum de lignes acceptable par fonction.
  • Séparant les lignes d'un espace quand elles font des choses différentes.
  • Stockant un maximum de données dans des variables pour mieux les réutiliser après…

Cohérence de code

Alias : code consistancy, uniformisation du code

Bonne pratique visant à avoir du code dont le style est similaire ou identique partout dans la codebase grâce à des standards de code.


Standard de code

Manière de coder partagée par tous les membres d'une équipe afin de rendre le code cohérent.

Les standards sont généralement très rattachés au langage de programmation, et documentés dans une charte de développeurs, voire automatisés pour que tous les développeurs les suivent.


Charte de développeur

Document qui contient tous les standards de code sur lesquels une équipe s'est accordée.


Séparation des responsabilités

Fait d'attribuer une seule responsabilité bien définie à un élément de code. Une seconde responsabilité implique de créer un second élément.

C'est une bonne pratique qui permet de rendre le code plus lisible, de retracer les problèmes plus facilement et d'éviter les régressions.

const string employeeSqlQuery = "SELECT Id, Firstname, Lastname FROM Employees WHERE Id = {Id};";
const string activeEmployeesSqlQuery = "SELECT Id, Firstname, Lastname FROM Employees WHERE Status = 'Active';";

Db.Execute(employeeSqlQuery, new { Id = id });
Db.Execute(activeEmployeesSqlQuery);
Bonne séparation des responsabilités, où chaque requête se trouve dans son propre élément.
string sql = "SELECT Id, Firstname, Lastname FROM Employees WHERE Id = {Id};";

Db.Execute(sql, new { Id = id });

sql = "SELECT Id, Firstname, Lastname FROM Employees WHERE Status = 'Active';";

Db.Execute(sql);
Mauvaise séparation des responsabilités, car on a une variable SQL qui s'occupe de deux choses à la fois.

Duplication de code

Fait d'avoir plusieurs éléments de code qui pourraient être factorisés en un seul.

C'est généralement considéré comme étant une mauvaise pratique, car cela rend la maintenance plus difficile. Mais il y a des exceptions.


Couplage

Lorsqu'un type A est composé d'un autre type B, on dit que A et B sont couplés, car A dépend directement de B. Ainsi, si B change, A sera irrémédiablement impacté.

Ce n'est pas toujours un problème, mais dans certains cas, il est nécessaire de découpler A et B de sorte à limiter les régressions.

La meilleure manière de faire c'est d'utiliser le principe d'inversion des dépendances, qui tire avantage du polymorphisme pour faire en sorte que A ne dépende pas directement de B, mais d'un de ses parents.


Constante magique

Constante non nommée. C'est généralement considéré comme une mauvaise pratique, car ça peut porter à confusion, et générer de la duplication de code.

double yearlySalary = salary * 13; // Pourquoi 13 ?

Régression

Fait de provoquer une erreur dans une partie d'un logiciel en changeant quelque chose dans une autre partie.

Un des objectifs fondamentaux d'une bonne architecture est de limiter les régressions.


Design

Design

Conception et modélisation de l'interface graphique d'une application.

La réalisation ne fait pas partie du design, mais plutôt du développement, car ce n'est que du code, donc pas le travail d'un designer.


Interface graphique

Alias : interface utilisateur, UI, GUI

Ce que voit l'utilisateur lorsqu'il utilise l'application.


Expérience utilisateur

Alias : ergonomie, UX

Ce que ressent l'utilisateur quand il utilise l'application (frustration, confusion…).

Le terme est souvent réduit à simplicité d'utilisation, mais il est en réalité beaucoup plus large que ça, et plonge dans les profondeurs de la nature humaine. Mais comme je suis loin d'être un expert, je vais m'arrêter ici 😛


Front-office

Partie d'une application accessible par les utilisateurs non modérateurs et non administrateur, tel que :

  • Les pages de présentation (accueil, à propos…)
  • Le compte client…

À ne pas confondre avec frontend.


Back-office

Partie d'une application accessible uniquement par des modérateurs ou administrateurs, tel que :

  • La page de création de contenu
  • La page de gestion des utilisateurs…

À ne pas confondre avec backend.


Divers

Conception (développement)

Alias : architecture, design (ambiguë)

Fait de construire une architecture logicielle en imaginant et en modélisant la manière dont les éléments vont s'agencer.

Dans la pratique, ça implique surtout beaucoup de diagrammes, de prototypes et de documentation.


Implémentation (pratique)

Alias : codage, réalisation

Programmation des fonctionnalités du logiciel, les spécifications et les exigences du client.


Programmation système

Développement de logiciels proches, ou faisant partie intégrante de l'OS.


Langage de balisage

Alias : markup langage

Spécification permettant de structurer des données, documents ou interfaces graphiques au format texte, sous la forme d'une hiérarchie de balises.

Dans sa forme la plus simple, une balise est un mot clef placé entre deux chevrons, et est composée en 3 parties :

  • L'ouverture (<title>)
  • Le contenu, c'est-à-dire tout ce qui se trouve dans cette balise. Ça peut être du texte, mais aussi d'autres balises (Ceasar salad).
  • La fermeture, qui clôture le contenu (</title>)

Exemples connus :

  • SGML, le papa de tous les autres qui a formalisé la manière dont on écrit les balises.
  • HTML, spécifique aux pages web.
  • XML, principalement pour la structure de données (mais pas que !)
<recipe>
    <name>Ceasar salad</name>

    <isHealthy>true</name>

    <ingredients>
        <ingredient>Lettuce</ingredient>
        <ingredient>Croutons</ingredient>
        <ingredient>Olive oil</ingredient>
        <ingredient>Egg</ingredient>
    </ingredients>
</recipe>

HTML

Langage de balisage permettant de structurer des pages web.

<h3 id="programmation-imp-rative">Programmation impérative</h3>

<p><u><a href="#paradigme-de-programmation">Paradigme</a></u> désignant un logiciel construit en totale isolation de son <u><a href="#environnement">environnement</a></u> afin d'éviter tout <u><a href="#-tat">changement d'état</a></u>.</p>

<p>Par souci de praticité, la plupart des <u><a href="#langage-de-programmation">langages</a></u> dits <em>impératifs</em> laissent la possibilité d'altérer l'état du programme via des instructions spéciales, mais leur utilisation est fortement découragée.</p>

<p>Grand principe de programmation implémenté par un <u><a href="#langage-de-programmation">langage</a></u>. Un paradigme peut contenir plusieurs sous-paradigmes, et un langage peut en implémenter plusieurs.</p>
Un code HTML tiré d'un de mes articles.

XML

Alias : eXtensible Markup Langage

Langage de balisage ayant la particularité de n'avoir quasiment aucune règle hormis le style, ce qui le rend très extensible.

La plupart du temps, il est utilisé pour structurer des données au même titre que JSON, mais il peut aussi être utilisé pour structurer des documents ou créer des interfaces graphiques.

Les extensions les plus connues sont :

  • XHTML qui permet de formaliser l'écriture du HTML.
  • RSS qui permet de diffuser des mises à jour de contenu d'un site internet en temps réel.
  • KML qui permet de représenter une position de manière standard sur un site de carte interactive, style Google Map…
<recipe>
    <name>Ceasar salad</name>

    <isHealthy>true</name>

    <ingredients>
        <ingredient>Lettuce</ingredient>
        <ingredient>Croutons</ingredient>
        <ingredient>Olive oil</ingredient>
        <ingredient>Egg</ingredient>
    </ingredients>
</recipe>

JSON

Alias : JavaScript Object Notation

Spécification de structure de données extrêmement simple qui ne possède que 5 types :

Elle est issue du monde JavaScript, mais s'est démocratisée pour devenir la structure la plus utilisée aujourd'hui.

{
    "name": "Ceasar salad",
    "isHealthy": true,
    "ingredients": [
        "Lettuce",
        "Croutons",
        "Olive oil",
        "Egg"
    ]
}

Composant graphique

Élément de code qui contient une partie de l'interface graphique, design et comportement. Il peut être lui-même formé d'autres composants graphiques.

On retrouve principalement cette notion dans les frameworks web frontend, tel que :

Des composants Material pour Angular.