Nous, les informaticiens, utilisons sans arrêt des acronymes sans se soucier des individus qui ont peu de connaissances en informatique. Une personne perplexe m'a demandé un jour «Qu'est-ce donc qu'un Framework et l'OOD ?» Le pauvre gars ne se savait pas ce qu'il demandait, ou à qui il le demandait. Puisque la question est justifiée et que plusieurs autres personnes se posent peut-être la question, j'ai écrit cet article.
L'ordinateur exécute des instructions simples (très simples), très rapidement. Ces instructions sont faites de 0 (zéro) et de 1. Sous cette forme, ces instructions s'appellent du code machine, puisque seule une machine accepte volontiers de les utiliser.
Ces 1 et 0 ne sont que des signaux électriques à l'intérieur de l'ordinateur. Ce signal à deux états est appelé «binaire» et sa valeur s'appelle le «bit». Bit est le raccourci de Binary digit, chiffre binaire.
Les premiers ordinateurs, dans les années 40 et 50, n'étaient même pas programmés, ils étaient littéralement connectés par des fils électriques sur un grand panneau, les connexions représentaient un «1» alors que l'absence de connexion représentait un «0». Brancher tous ces fils électriques étaient un processus lent et difficile à faire, les erreurs étaient quasi introuvables. Si quelque chose n'allait pas, il fallait suivre chacun des fils électriques du panneau et localiser le fautif, des dizaines de milliers de ces fils étaient connectés. Pour créer un nouveau programme, les concepteurs retournaient au panneau électrique et rebranchaient le nouveau programme.
Une rumeur veut que le terme «bogue» (bug en anglais, qui désigne un insecte) vient de cette époque, alors que des insectes se faufilaient dans les ordinateurs et que leurs carcasses grillées causaient des courts-circuits. Ces «bogues» provoquaient un mauvais fonctionnement des programmes. Il est indéniable que cela ce soit produit, mais que le terme provient de cette époque est un mythe. Le terme «bogue» est antérieur aux années 40 et décrivait un mauvais fonctionnement dans les machineries, 100 ans avant les ordinateurs. Des insectes tombaient dans les machineries (plus particulièrement dans les mécanismes délicats d'horlogerie et de boîte musicale) et bloquaient les engrenages!
Plus tard, les ordinateurs ne furent plus connectées par des fils électriques, mais plutôt par des valeurs situées dans une «mémoire» (aux alentours des années 50 et 60). C'était mieux et permettait d'effectuer des changements rapidement, mais les humains faisaient encore beaucoup d'erreurs en utilisant les «0» et les «1». Alors les gens ont commencé à utiliser des mnémoniques (ou abréviations) qui substituaient des noms faciles à retenir à la places des séries de «1» et «0» (qui étaient des instructions pour les ordinateurs).
Les mnémoniques sont des descriptions humaines des séries de bits. Ces mots étaient convertis de leur forme humaine (leurs noms) en leur forme numérique (séries de «1» et «0») par un programme appelé «un assembleur». Ces représentations mnémoniques s'appellent le langage d'assemblage, parce c'est un assembleur qui effectue la conversion.
Le code machine et l'assembleur sont très détaillés. Chaque instruction fait un tout petit travail. Ces instructions ne modifient que quelques états qui n'ont qu'un sens électrique, pas un sens permettant aux humains de modéliser un problème ou une solution, les programmeurs ne sont pas très productifs avec le langage d'assemblage.
Le langage d'assemblage est tellement détaillé qu'au lieu de demander à quelqu'un de «manger», ce serait comme demander: «Avec votre main droite saisissez l'ustensile à plusieurs pointes en utilisant les doigts de votre main droite. Prenez des aliments avec la fourchette en piquant la nourriture avec la dite fourchette. Ouvrez votre bouche et pliez votre bras droit, déplacez la fourchette vers votre bouche. Continuez jusqu'à ce que la nourriture soit dans votre bouche et cessez le déplacement de la fourchette. Fermez la bouche autour de la fourchette (pas trop fort) et retirez la fourchette. Répétez le processus jusqu'à ce qu'il ne reste plus de nourriture dans l'assiette.» Ce n'est pas encore assez détaillé, mais vous avez sûrement compris.
Le langage d'assemblage est un langage de bas niveau car les programmeurs parlent aux ordinateurs à un niveau très bas (vous parlez le langage des ordinateurs). Pour augmenter la productivité des programmeurs, les langages de haut niveau ont été créés (1960 - 1970).
FORTRAN (qui signifie en anglais formula translator) est un des premiers langages de haut niveau. Le langage de haut niveau permet au programmeur d'utiliser des instructions moins détaillées pour faire plus avec chaque instruction (de même que «manger» signifie la même chose que toutes les instructions détaillées énoncées plus haut dans l'article). Ce progrès a permis aux programmeurs d'être plus productifs et d'écrire de plus gros et plus complexes programmes qui faisaient beaucoup plus de choses. Mais le code est organisé selon le bon vouloir du programmeur et plusieurs programmeurs ne sont pas très organisés (la programmation était un nouvel art et il y avait peu de formation), certains résultats étaient élégants, d'autres étaient épouvantables à regarder.
Le résultat cauchemardesque d'un programmeur est appelé «code spaghetti», parce que lorsqu'on y regardait plus tard et qu'on essayait de suivre le programme pas à pas, s'était comme suivre une nouille dans un plat de spaghetti, ca va n'importe où, n'importe comment. Le code, dans les langages de haut niveau, pouvait être plus gros et plus complexe qu'auparavant (comparativement aux langages de bas niveau), mais il s'effondrait éventuellement sous sa propre complexité. Ce qui signifie que le programme était tellement gros et complexe qu'il en était devenu irréparable et impossible à maintenir, ce qui coûtait beaucoup d'argent.
Une partie du problème des langages de haut niveau était leur incapacité à traiter des types de données complexes. Les programmeurs utilisaient des types de données de base pour construire à peu près n'importe quoi. Ainsi ils utilisaient des vecteurs de base pour en décrire de beaucoup plus complexes, puisqu'il n'y avait pas de représentation «naturelle» de ce qu'ils désiraient et ils ne pouvaient pas les créer facilement. Les programmeurs devaient décoder et recoder ces vecteurs à plusieurs endroits dans le code et une seule erreur pouvait alors s'avérer catastrophique. Les programmeurs utilisaient également une instruction appelée goto qui permettait de se brancher à n'importe quel endroit dans le code. Cela a contribué au code spaghetti et avait besoin d'être amélioré.
Il devait exister une meilleure manière de programmer.
Le code procédural et les structures de données étaient destinés à résoudre le problème de la programmation spaghetti. Cela s'est révélé faux. Le problème de la programmation spaghetti était causé à 90% par le programmeur et les langages améliorés n'ont aidé que le 10% restant. Les nouveaux langages ont cependant aidé un peu. Ce que ces langages offraient étaient appelés «Structures de données» et «Conception procédurale» (appelé ensemble programmation procédurale). Les langages procéduraux sont devenus populaires dans les années 70 et 80 avec des langages comme le Pascal et le C.
Avant la programmation procédurale, les programmes n'étaient qu'une longue suite de code. Les programmeurs sautaient d'un endroit à l'autre dans le code, il n'y avait aucune frontière entre la fin d'une tâche et le début de l'autre (pensez aux anciens manuscrits écrits sur des rouleaux de papier). Lorsqu'un programmeur désirait aller d'une place à l'autre, c'était toujours compliqué de trouver où les choses étaient. Les procédures étaient la manière de diviser le code en plusieurs parties (pensez aux livres modernes avec des pages séparées et des chapitres). Le programmeur n'avait plus à faire face à une suite de pensées aléatoires sur un rouleau de papier, il existait maintenant une manière d'organiser les choses en groupes de chapitres, et renvoyer les gens à une page particulière. Beaucoup mieux.
Les structures de données permettaient aux programmeurs de grouper des ensembles complexes de données en groupes ou structures. Les programmeurs n'avaient plus à décoder un vecteur de données de base à des centaines d'endroits dans le code (avec des erreurs causant des résultats fâcheux), le programmeur bâtit une structure utilisant plusieurs types de données, et il en propage la référence dans son code.
Il y avait une blague qui disait que les programmeurs de FORTRAN pouvaient programmer en FORTRAN dans n'importe quel langage. En d'autres mots, le seul fait qu'un langage change ne signifie pas que la façon de l'utiliser change également. Le résultat fut que les mauvais programmeurs étaient toujours capables d'écrire du code spaghetti. Les programmes étaient maintenant répartis en plusieurs chapitres mal écrits, au lieu d'être une suite de code mal écrit.
Pour être équitable il faut ajouter que les bons programmeurs pouvaient faire plus de choses avec chacune des nouvelles générations de langage, et écrire des programmes mieux faits et plus clairs. Cependant le ratio de bons programmeurs versus les mauvais programmeurs est toujours demeuré constant. Les bons programmeurs pouvaient écrire des programmes très lisibles avec les vieux langages. (Pouvez-vous deviner dans lequel de ces camps de programmeurs se considère l'auteur de cet article ?). Les progrès dans les langages ont été bénéfiques, mais pas autant qu'espéré.
Tout au long de l'histoire de l'informatique la taille des programmes a considérablement augmenté. Les programmes des années 50 ne contenaient que des douzaines, peut-être des centaines d'instructions (lignes de code), mais dans les années 70 et le début des années 80 les programmes atteignaient les 100,000 lignes de code, et dans les années 90 ce sont des millions de lignes, tout en se rappelant que chaque ligne de code est de plus en plus puissante. Rappelez-vous également qu'une seule petite erreur peut faire planter le programme ou même l'ordinateur.
Avec le code procédural les programmeurs ont appris à regrouper leur code en procédures. Chaque procédure fait un petit travail, mais le fait bien (à condition d'être écrite par un bon programmeur). Les programmeurs ont appris également comment regrouper plusieurs fonctions en librairies. Plusieurs de ces librairies étaient constituées d'un grand ensemble de fonctions déjà écrites. D'autres programmeurs pouvaient acheter ces librairies plutôt que de les écrire eux-mêmes, et ainsi augmenter leur productivité en utilisant du code déjà écrit, c'est en gros ce qu'est un système d'exploitation.
Les premiers ordinateurs n'avaient pas de systèmes d'exploitation, chaque programme devait, en plus de son propre travail, contrôler tout le matériel de l'ordinateur. Un système d'exploitation n'est qu'un paquet de code déjà écrit (une librairie) permettant aux programmeurs de contrôler le matériel (et faire autre chose) sans avoir à écrire tout le code eux-mêmes. La partie du code du système d'exploitation qui est dans l'ordinateur et qui n'a pas besoin d'être chargée en mémoire est appelée le BIOS (Basic Input Ouput System). Le système d'exploitation ne représente pas seulement le point de vue du programmeur sur l'ordinateur mais également celui de l'utilisateur, ainsi une partie du système d'exploitation est un programme qui est livré avec l'ordinateur et qui permet à l'utilisateur de le contrôler.
Cette dualité dans le fonctionnement confond les utilisateurs, il y a la partie programmation du système d'exploitation et la partie visible par les usagers. Au fil des années les systèmes d'exploitation font toujours de plus en plus de travail alors que les programmeurs ont besoin d'en faire de moins en moins. Les premiers systèmes d'exploitation ne contrôlaient que le matériel de l'ordinateur. Plus tard les systèmes d'exploitation ont commencé à contrôler des choses comme l'affichage graphique, les copies de fichiers, l'affichage de séquences vidéo, le son et l'impression. Maintenant un système d'exploitation est considéré comme étant «tous les programmes et librairies livrés avec votre ordinateur.»
Certains programmes ont des noms spéciaux. Si le programme ne contrôle qu'une pièce du matériel, il est souvent appelé un «pilote» (driver). C'est la partie du code qui est en charge du matériel et tous les programmeurs doivent demander au pilote de faire les choses pour eux. Si le code est une librairie du système d'exploitation destinée aux créateurs d'application pour leur faciliter la tâche, alors ce code est appelé un API (Application Programming Interface). Les programmeurs d'application devaient écrire beaucoup de code, alors pour les rendre plus productifs, les concepteurs de systèmes d'exploitation ont commencé à livrer des API avec leur système. Cela diffère des autres librairies du système d'exploitation que les manufacturiers de matériel ou les programmeurs de bas niveau ont besoin et que les créateurs d'application ignorent. Des couches de fonctionnalités sont apparues destinées à des groupes de programmeurs différents. Il fut un temps où il existait une différence entre les API et les autres librairies du système d'exploitation, les couches supérieures étaient appelées des API. Cette distinction s'est malheureusement perdue il y a de cela quelques années déjà. Aujourd'hui presque toutes les librairies livrées avec un système d'exploitation sont appelées API.
Les concepteurs de langage ont essayé, une fois de plus, d'améliorer la productivité des programmeurs. La nouvelle solution est beaucoup plus importante que les autres, elle impose un nouveau paradigme, une nouvelle façon de créer les programmes. Plutôt que de concevoir les programmes en une séquence d'instructions regroupées en procédures, un tout nouveau concept doit être utilisé. Ce nouveau procédé utilise ce qu'on appelle la conception orientée-objets le OOD (Object Oriented Design) par l'entremise des langages de programmation orientés-objets OOP (Object Oriented Programming) comme le Pascal objet (ObjectPascal), le C++ ou le Java.
Cela signifie que le code est non seulement composé de groupes de procédures, mais que ces groupes de procédures sont appelés des «objets». Les données utilisées par ces objets sont conservées à l'intérieur de ces objets. Tout est concentré dans des objets et ce concept est appelé «l'encapsulation» et permet de clarifier le code.
La possibilité d'aller d'un endroit à l'autre dans le code et de modifier des données ça et là est rendue impossible puisque tout le code et les données sont encapsulés dans des objets. Les objets ne peuvent modifier que leurs propres données et pas celles des autres et ont tout le loisir d'aller n'importe où dans leur code, mais pas dans le code des autres. Les objets peuvent communiquer ensembles en utilisant des messages. Tout cela est une «protection» et permet de localiser les problèmes plus facilement. Si un objet fonctionne mal, vous savez que vous n'avez à examiner que le code de cet objet plutôt que chercher dans tout le code de l'application ou dans tout le système. Cela permet d'économiser beaucoup d'argent.
Avant l'apparition de l'OOP et l'OOD, c'était chose courante d'utiliser le code écrit par d'autres personnes. Les programmeurs utilisaient le système d'exploitation et parfois quelques librairies, mais la plupart du temps les programmes étaient uniques pour chaque application. C'était beaucoup de gaspillage car des parties du code d'un programme ressemblaient bien souvent à celles d'autres programmes. Les objets et le OOD ont apporté des «composantes» standards à la programmation; on peut faire le parallèle avec les lignes d'assemblage de la révolution industrielle. Le regroupement de fonctionnalités à l'intérieur d'objets permettait de les réutiliser dans d'autres applications. Une réutilisation de code signifie des coûts plus bas et une augmentation dans la productivité. Mieux encore, l'héritage permet à un objet d'hériter plusieurs des caractéristiques (code et données) d'un autre objet, le programmeur n'a qu'à écrire le code qui ajoute la différence au nouvel objet. Encore plus de réutilisation.
Alors comment s'appelle un regroupement d'objets ? Le terme magique est «Framework». Un Framework d'objets est une super librairie, les concepts d'encapsulation et d'héritage ajoutent à l'efficacité de ceux-ci. Des parties d'un système d'exploitation peuvent être livrées en Framework. Souvent le squelette d'une application est déjà écrit, ainsi les programmeurs débutent avec une application complètement fonctionnelle, et tout ce qu'ils ont à faire c'est d'y ajouter leur propre code. C'est ce qu'on appelle un Framework d'application (squelette d'application). Il y a également plusieurs autres types de Framework qui rendent les programmeurs encore plus productifs.
Plus il y a de code écrit par d'autres programmeurs et plus ce code est bien écrit, moins les programmeurs ont à écrire. Un programmeur peut faire un même travail en beaucoup moins de temps; ou dans un même temps faire beaucoup plus de travail (et créer de plus grosses applications). C'est ce que permet l'OOD et l'OOP et c'est pourquoi les Frameworks sont si attrayants pour les programmeurs.