Pourquoi tout le monde devrait apprendre à coder ?

Le codage : passé et futur
Dans l’histoire des inventions, il en est une à l’origine de la première machine programmable, et qui est probablement précurseur à l’ordinateur tel que nous le connaissons de nos jours, même si elle était mécanique à l’époque et non électronique.
C’est un français Joseph Marie Jacquard qui l’imagina.
Ce lyonnais mit au point en 1801 le premier métier à tisser mécanique programmable avec des cartes perforées, et cela en combinant plusieurs techniques qu’il emprunte à d’autres inventeurs : les techniques des aiguilles à Basile Bouchon, les cartes perforées à Falcon et le cylindre à Vaucanson.
Le système de lecture de cartes perforées est comparable a un language binaire : un trou laisse passer un signal (ici une aiguille) comparable à 1, et l’absence de trou bloque le signal (ici une aiguille) comparable à 0.

Dans cette machine on distingue déjà la partie purement mécanique qu’est la technologie brute (ou « hardware » en Anglais) du métier à tisser fait de rouages et autres pièces en différentes matières, et la partie interactive qu’est l’action de rentrer des instructions par un utilisateur dans la machine par le biais des cartes perforées (ou « software » en Anglais).
Ce premier système de lecture séquentielle, c’est-à-dire de lecture par séquences délimitées sur chacune des cartes, sera repris plus tard par un inventeur et mathématicien anglais. Dans le courant de l’année 1834, Charles Babbage eut l’idée, en plein développement de sa « Machine à différences », d’y ajouter ce principe de lecture séquentielle binaire. Il ne put la terminer de son vivant, cependant c’est un de ses fils qui acheva son oeuvre et en fit la démonstration en 1908. Cette machine analytique a été conçu spécifiquement pour le calcul et l’impression de tables mathématiques. Ce qui en fait le véritable ancêtre de « l’ordinateur » pour « machine à ordonner » (ou « computer », en Anglais pour « machine à compiler ») des calculs.

Bien qu’il fut un pionnier, c’est une femme qui est à l’origine de l’idée même de l’ordinateur personnel ou du PC (« personnal computer » en Anglais) tel que nous le connaissons aujourd’hui. En effet, Ada Byron Lovelace naturellement douée et passionnée de mathématique, propose à Sir Babbage d’abord une traduction du mode d’emploi de sa machine analytique en français, pour finalement rédiger à sa demande un véritable mémoire présentant cette dernière. Dans ce mémoire en plus d’y ajouter de très nombreuses notes sur les potentialités de la machine comme celle de composer de la musique ou d’écrire des livres, elle y présente un véritable algorithme détaillé pour calculer les nombres de Bernoulli (suite de nombres rationnels). Cette suite d’instructions comporte notamment la première boucle conditionnelle (du type : « SI…ALORS » ou « IF…THEN » en Anglais). Ce concept typiquement informatique, contrairement à celui des séquences inscrites sur les cartes du métier à tisser, a valu à Ada d’être considérée comme ayant inventé le tout premier code de programmation !
Les algorithmes sont comme l’illustre l’histoire de la machine analytique, une mise en forme d’un nombre certain de données précises (mathématiques ou autres) servant à simplifier des problèmes complexes au premier abord. Même si étymologiquement le sens du mot grec arithmos est « calcul », un algorithme décompose en sous-parties plus faciles à comprendre une « question à résoudre » (ou problema en latin), et s’applique à plusieurs domaines même dans la vie quotidienne comme par exemple en cuisine.
Une recette peut ainsi être réduite par un algorithme :
- en éléments constitutifs avec des entrées, dits « variables » (ingrédients, matériel, nombre de personnes à nourrir…) ;
- avec des instructions élémentaires simples, dits « séquences (souvent) itératives » (les étapes de préparation du plat) comprennant :
— — — des tâches, dits « fonctions et procédures » (découper, trancher, blanchir, mélanger, réserver…),
— — — à exécuter dans un ordre précis, dits « conditions » (par quoi commencer, le temps de cuisson…) ;
- et qui amènent en sortie au résultat voulu (le plat final).
Le premier algorithme est donc une suite binaire de 2 variables tout comme l’est le morse, inventé à la même période par l’américain Samuel Morse. Ce langage qui est une suite d’impulsions courtes et longues, circule à travers un réseau de câbles avec à chaque extrémité, un transmetteur capable de traduire les pressions du doigts de l’opérateur sur un télégraphe en impulsions électriques, et un récepteur capable de traduire ce code binaire en sons convertissables par un autre opérateur en un texte compréhensible.
Le morse est l’ancêtre de toutes les communications numériques : comme le signal radio, télécom et protocole internet…
Peu de temps après, en 1838 dans ce siècle des Lumières où les inventions s’enchaînent, le premier télégraphe électrique fonctionnel est construit par Charles Wheatstone et le code binaire mécanique devient à partir de là, un code binaire digital (ou numérique, car « digit » signifie chiffre en anglais)avec les digits 0 et 1. Son unité de mesure est le « bit » (une compilation de « binary digital » en Anglais). Au vu du nombre de bits nécessaire pour coder une seule instruction, il a fallut normaliser les règles de ce nouveau langage très complexe car au potentiels multiples et qui a commencé a réellement se développer au XXe siècle.

Vous avez-dit bit ou byte ?
Pour mesurer la quantité d’information numérisé il existe les octets; 1 octet est égal à 8 bits ou 1 byte (soit 1 byte = 8 bits) . Pour comprendre ce choix de nom, il faut regarder son étymologie, octet est constitué du préfixe « oct- » signifiant huit et du suffixe « -et » signifiant petit en latin.
Comme le code est binaire, donc composé de 2 variables, cela équivaut à une possibilité de codage de 28 nombres, soit 256 valeurs et donc caractères différentes, ce qui est largement suffisant pour coder l’alphabet latin.
Allons dans le détail : chaque bit est un multiple de 2 du bit précédant : soit 1 puis 2 puis 4 puis 8 puis 16 puis 32 puis 64 puis 128 fois 2 variables. Cela signifie qu’avec 1 octet de 8 bits ou 1 byte, nous avons 2 fois 128 = 256 nombres possibles de codage !
Pour donner une idée de la puissance d’autant de combinaisons de chiffres il faut retenir que seulement 16 bits ou 2 bytes, représentent 65 536 nombres et 32 bits ou 4 bytes augmentent ce chiffre à déjà 4 294 967 296 !
Voyons la signification d’un code de 8 bits ou 1 byte en détail :
0000 0000 = 0 0000 0100 = 4
0000 0001 = 1 0000 0101 = 5
0000 0010 = 2 0010 0110 = 6
0000 0011 = 3 0000 0111 = 7
Voyons maintenant un exemple de texte avec le mot « ange » grâce à une suite binaire de nombres définit par le code ASCII (Code Américain Standardisé pour l’Inter-échange d’Information, standardisé à 7 bits au Etats-Unis, mais augmenté à 8 en Europe pour pouvoir coder les caractères accentués) :
Lettres :
A — N — G — E
Chiffres correspondants :
65 — 78 —71 — 69
Suite binaire correspondante :
1000 0001 — 1000 1110 — 1000 1111 — 1000 0101
Quelques exemples de valeur de bits pour :
- Une photo de smartphone 4/3 à 8 000 000 pixels ou 8 mégapixels, équivaut à un espace de 19,5 ko ou kilo-octets, soit 19 500 octets ou 103 octets dans la mémoire de l’appareil.
- Une vidéo 16:9 en HD ( 1280 par 720 pixels) d’une minute fait 3,1 méga-octets, soit 3 100 000 octets ou 106 octets. Et un film entier fait en moyenne 3 giga-octets, soit 3 000 000 000 octets ou 1010 octets !
Les contenus médias prennent beaucoup de place, mais heureusement la technologie permet actuellement d’avoir des mémoires avec des capacités de plusieurs téraoctets soit 1012 octets.
Le langage binaire informatique sert à programmer des instructions afin que la machine les exécute; ceci équivaut à transmettre une série de charges électriques (ou impulsions) et de non-charges correspondant à 1 ou à 0, et qui feront fonctionner ou non un composant électronique dans l’ordinateur, qui à son tour exécutera une fonction ou non. Evidemment, il y a des milliers de composants et plusieurs millions d’impulsions à la seconde dans les circuits d’un PC !

Ceci implique que les premiers programmes informatiques qui étaient des suites de code binaire laborieusement écrits à la main ne fonctionnait pas à grande échelle. Rentrer des milliards de chiffres manuellement, aurait été un travail titanesque de plusieurs siècles même si toute la population des états-unis s’y collait ! Alors les premiers ingénieurs-informaticiens ont très vite optimisé et simplifié le codage en inventant le principe des portes logiques ou « logic gates » en Anglais, qui comprend la fameuse boucle conditionnelle d’Ada Lovelace. Ces portes sont programmées dans un logiciel ou software rudimentaire nommé « assembleur de texte » qui permet d’entrer des textes dans un langage informatique intermédiaire dans la machine, qui les traduit ensuite en code binaire à l’aide d’algorithmes.
Les premiers langages étaient encore loin d’un langage facile à maîtriser pour un non ingénieur-informatique, de plus presque chaque ordinateur avait son propre langage. Ce langage d’assemblage est dit « du plus bas niveau » car c’est du langage machine de base sous forme lisible par un codeur avéré. Le premier programme assembleur nommé SOAP pour « protocole simple d’accès à des objets » (ou Simple Object Acess Protocol en Anglais) a été écrit par Nathaniel Rochester pour l’IBM 701 de 8 192 octets (le premier ordinateur commercialisé par IBM) en 1954. Ce langage est représenté par des symboles mnémoniques (faciles à mémoriser), des valeurs décimales en binaires et des libéllés d’emplacements d’adresses qui permettront de créer par exemple un fichier objet ou exécutable.
Dans les années 60, sont testés des langages de programmation orienté objet et utilisant les premiers compilateurs qui deviendrons standards par la suite en donnant leur nom commercial aux « computers » . Un compilateur permet de transformer un code source texte en code objet machine (et est dépendant du système d’exploitation). Dès 1963 les laboratoires universitaires de Cambridge et de Londres travaillent sur un langage de programmation combiné : le CPL ou (Combined Programming Language en Anglais). Censé être bon à la fois pour la programmation scientifique (à la manière du langage ALGOL ou Algorithmic Oriented Language en Anglais) et également pour la programmation commerciale (comme le COBOL ou Common Business Oriented Langage en Anglais), le CPL fut un échec, car il était lourd, complexe et restait trop abstrait. Il donnera cependant naissance à des langages bien connus ; d’abord il y eut fin des années 60 le Basic CPL ou originairement le Bootstrap CPL, qui sera la transition vers le langage plutôt orienté enseignement qu’est le Pascal permettant de se concentrer sur les algorithmes et les structures de données, et le fameux langage C très orienté langage machine. Le langage Pascal n’est pas un langage compilé mais interprété, il tombera cependant dans le déclin jusque dans les années 1990.
Le langage C crée par Dennis Ritchie dans les laboratoires Bell est « de bas niveau » et dit « impératif », c’est-à-dire une logique de programmation basé sur des opérations en séquences d’instructions élémentaires, à savoir:
- des instructions d’assignation de valeur en résultat, des instructions conditionnelles de type « if…then »,
- des instructions de bouclage pour les itérations de type « for…do…while »,
- et les branchements sans condition permettant à la séquence d’être transféré ou de sauter en mode aller-à (« go to » en Anglais) à un autre endroit du programme dans d’une boucle.
Toutes ces instructions sont codées sous forme de «codes-opérationnels » (ou « opcodes » pour « operation codes » en Anglais) et exécutées par l’ordinateur équipé de processeur de nature impérative. Le langage C a été conçu pour le développement du système Unix, car il permettait un accès complet aux primitives du système, rendant l’ensemble puissant et facile à utiliser pour les initiés.
De ces premiers langages ont découlés les langages dits « de haut niveau » qui se sont éloignés du langage machine pour se rapprocher du langage courant facilement compréhensible par l’humain, ceux-ci se sont vraiment développés dans les années 70. D’une part les machines bénéficiaient d’une belle avancée technologique avec la réduction de la taille et du coût de fabrication des composants électroniques qui a permit l’amélioration de la performance et de la vitesse des processeurs, mais aussi la taille de la mémoire de la machine.
Les compilateurs évoluent rapidement et les langages de concert, car la plupart des compilateurs permettent d’optimiser le code, c’est-à-dire qu’ils vont chercher à améliorer la vitesse d’exécution, ou réduire l’occupation mémoire du programme.
En général, le langage source est « de plus haut niveau » que le langage cible, c’est-à-dire qu’il présente un niveau d’abstraction supérieur. En informatique, le concept d’abstraction identifie et rassemble les caractéristiques et les traitements communs au langage pour en optimiser l’utilisation.

Un compilateur fonctionne par analyse-synthèse : il commence d’abord par analyser le texte source pour en construire une représentation intermédiaire qu’il traduit à son tour en langage cible pour la machine. Le code source du programme est donc généralement réparti dans plusieurs fichiers.
Ainsi, le compilateur est séparé en au moins deux parties :
- une partie avant (ou frontale), parfois appelée « souche », qui lit le texte source par exemple en langage C, et produit la représentation intermédiaire, soit un code d’assemblage ;
- et une partie arrière (ou finale), qui parcourt cette représentation pour produire le code cible, soit le langage machine.
Ces étapes sont :
Pour la partie Frontale
- le prétraitement, nécessaire pour certains langages comme C, qui prend en charge la substitution de macro (remplacement d’un texte par un identificateur) et de la compilation conditionnelle ;
- l’analyse ou le scan lexical, qui découpe le code source texte en petits morceaux appelés « jetons » (ou «tokens» en Anglais), par exemple un mot-clé, un identifiant ou un symbole ;
- l’analyse syntaxique, qui implique l’analyse de la séquence jeton pour identifier la structure syntaxique du programme. Cette phase remplace la séquence linéaire des jetons par une structure en arbre construite selon la grammaire formelle qui définit la syntaxe du langage ;
- l’analyse sémantique, qui est la phase durant laquelle le compilateur ajoute des informations sémantiques à l’arbre d’analyse et construit la table des symboles. Cette phase vérifie le type (vérification des erreurs de type), ou l’objet de liaison (associant variables et références de fonction avec leurs définitions), ou une tâche définie (toutes les variables locales doivent être initialisées avant utilisation), peut émettre des avertissements, ou rejeter des programmes incorrects ;
- la transformation du code source en code intermédiaire ;
- l’application de techniques d’optimisation sur le code intermédiaire : c’est-à-dire rendre le programme « meilleur » selon son usage ;
Pour la partie Finale
- la génération de code avec l’allocation de registre et la traduction du code intermédiaire en code objet, avec éventuellement l’insertion de données de débogage (ou debugging en anglais) et d’analyse de l’exécution ;
- et finalement l’édition des liens de fichiers exécutables ou de bibliothèques dynamiques et statiques.
Mais retournons d’abord dans le passé, car c’est à cette époque en 1970 que dans les bureaux de Xerox aux Etats-Unis, qu’un certain Alan Key développe le premier GUI ou interface graphique d’utilisateur (Graphical User Interface en Anglais) qui permet au commun des mortels d’interagir directement avec la machine sans devoir connaitre des lignes de code ! Ce fut une révolution qui propulsa les ordinateurs personnels dans la sphère privée des foyers, et permit à l’informatique de se démocratiser mondialement en l’espace de 30 ans à peine.

Tous les langages des années 70 et 80, comme le C++ ou l’ Objective C, sont issus des premiers que j’ai abordés, mais dans les années 90, le regain des langages interprétés voient la création de nouveau langages basés sur Pascal, comme Ruby, Perl et Python.
Un interpréteur permet d’analyser, de traduire et d’exécuter des programmes informatiques par des opérations qui sont réalisées à chaque exécution et au fur et à mesure de leur lecture pour interprétation, plutôt qu’une seule fois par à un compilateur.
L’interprétation repose sur l’exécution dynamique du programme par un autre programme (l’interprète), plutôt que sur sa conversion en un autre langage (comme le langage machine); elle évite la séparation du temps de conversion et du temps d’exécution, qui sont simultanés.
On va parler ici de « script » au lieu de « compilé », et ce script est directement exécuté à partir du fichier source via l’interpréter de la manière suivante :
- Il lit et analyse une instruction (ou une expression de valeurs) ;
- Si l’instruction est syntaxiquement correcte, il l’exécute (ou évalue l’expression) ;
- Il passer à l’instruction suivante.
La où les langages interprétés perdent du temps à cause de l’absence de la phase de traduction, leur intérêt réside principalement dans la facilité de programmation et dans la portabilité. Les langages interprétés facilitent énormément la mise au point des programmes car ils évitent la phase de compilation, souvent longue, et limitent les possibilités de bogues. La portabilité permet d’écrire un programme unique, pouvant être exécuté sur diverses plates-formes sans changements, pourvu qu’il existe un interprète spécifique à chacune de ces plates-formes matérielles.
Aujourd’hui les langages sont souvent un savant mélange des deux outils compilateur et interpréteur utilisant des langages intermédiaires , comme avec les « cadriciels » (ou « frameworks » en Aglais) Java ou .NET qui pré-compilent le code en un bytecode intermédiaire ensuite interprété ou exécuté par une machine virtuelle.
Si la notion de machine virtuelle date de 1936, avec la machine de Turing universelle purement théorique, le premier système de virtualisation informatique a été créée dans les années 70 par IBM et servait au partage de temps processeur d’une même machine. Puis Windows a repris le concept pour simuler l’exécution de son système d’exploitation MS-DOS en 1989, et en 1995, Sun Microsystems a propulsé sa machine virtuelle nommé Java qui pouvait exécuter directement sur n’importe quel type de machine, peut importe ses caractéristiques techniques, des logiciels téléchargés depuis un serveur web. Cette dernière est devenu le standard, même si des améliorations ont étés apportés comme l’hyperviseur intégré ou l’exécution simultané de plusieurs systèmes d’exploitation sur une seule machine. La définion actuelle d’une machine virtuelle est la suivante : une illusion d’un appareil informatique créée par un logiciel d’émulation simulant les ressources matérielles afin de tester des prototypes d’applications rapidement.

Le codage du futur
Dans la vision de notre futur, le véritable monde virtuel crée par le code informatique devrait se généraliser à tous les domaines de notre vie, et s’accélerer de plus en plus à l’aide de l’IA ou « Intelligence Artificielle ».
Il devient alors essentiel dans ces conditions, de sensibiliser tout les utilisateurs dès leur plus jeune âge aux notions de la programmation informatique, car il est évident que nous devons connaître, comprendre et garder les commandes de cet autre dimension de notre réalité actuelle, même si elle est virtuelle.
Depuis quelques décennies, un tout autre langage se construit jour après jour ; celui-ci est basé uniquement sur des algorithmes crées par l’ordinateur lui-même lors de sessions dits d’ « apprentissage machine » (ou « Machine Learning » en Anglais) et surtout l’« apprentissage approfondi » (ou « Deep Learning » en Anglais). Les deux comprennent un ensemble de méthodes d’apprentissage automatique supervisé et/ou non supervisé (par un humain ou un autre ordinateur) ou des techniques d’extraction hierarchique de caractéristiques (classés dans ses propres bibliothèques créées par la machine), et visant à modéliser avec un haut niveau d’abstraction (se rapprochant du langage humain) des données avec une bonne capacité d’analyse automatique des différenciations (pour permettre une reconnaissance visuelle, vocale, auditive, etc.).
L’apprentissage comprend des entrées ou (« inputs » en Anglais) et des sorties (ou « outputs » en Anglais) de données diverses (ou « data » en Anglais), comme des images associées à un ou plusieurs éléments sémantiques ; par exemple le mot « chat ». La méthode consiste à soumettre à la machine des milliers voir des millions d’images de chats de plusieurs races et dans différentes situations, afin que la machine puisse créer son propre modèle algorithmique ou code, lui permettant de reconnaitre un chat dans n’importe quelle image qui lui sera présenté par la suite. Un peu comme lorsqu’un enfant créée ses premières connexions neuronales à travers son processus d’apprentissage débuté dès sa naissance.
Bien sûr, tout ce processus est très lent et demande des quantités pharamineuses d’informations, mais en réalité les entreprises qui développent ces IA ont accès à des milliards de données qui sont postées à chaque seconde sur le web, par nous les internautes et accros des réseaux sociaux, et de ce fait il s’avère que les Intelligences Artificielles « grandissent » très vite !
Je pense sincèrement qu’il ne faut pas laisser les machines tout faire par elles-même. Nous devenons de véritables humains assistés, de moins en moins capables de réfléchir par nous-mêmes, et nous risquons de perdre les clefs de la connaissance du fonctionnement des machines que nous avons créées. Derrière chaque machine et chaque programme il y a un être humain, mais attention car c’est de moins en vrai !
Apprenons tous à coder, d’autant plus qu’en 2019, il n’y a seulement que 2% de la population mondiale capable de le comprendre et de le manipuler. C’est surprenant, car c’est un peu l’avenir de l’humanité quand même!
L’éthique du codeur
D’après mes sources et ma propre expérience, un bon code se doit d’être élégant, efficace, sans répétitions tout en étant puissant.
Et lorsque le codage est enseigné il est important de bien transmettre la notion de responsabilité du développer vis à vis des décisions capitales qu’il devra prendre quand à ce que son code doit contenir. Comme comment il est écrit et pourquoi, car il y aura toujours le risque de l’oubli d’une circonstance non envisagée ou d’une erreur de jugement, d’une mauvaise priorité ou d’une nouvelle condition non anticipée.
C’est pourquoi chaque développeur doit toujours bien réfléchir à toutes les différentes possibilités et à comment être exhaustif sans se voir freiné par la quantité de situations à considérer lorsqu’il code. Sur ce à bon entendeur… Salut !
Sources:
Netflix, la série série Bref « coder, pourquoi ? » 26 minutes, du 24 octobre 2019 > https://www.netflix.com/browse?jbv=80216752&jbp=0&jbr=1
FUN MOOC — « Données et algorithmes » de l’Université de Cergy, Paris Seine. > https://www.fun-mooc.fr/courses/course-v1:u-cergy+156003+session01/about
Wikipedia > https://fr.wikipedia.org/wiki
