Les bibliothèques logicielles
La structuration du code, en utilisant les bibliothèques logicielles ou les bibliothèques de code (également appelé library), est l'une des plus anciennes méthodes de fondations de la structure de code. Ainsi, elles sont apparues dans les 1950. Elles sont basées sur un principe linéaire où on retrouve un ensemble de procédures et de fonctions et font diverses tâches spécialisées. Elles sont souvent incluses de base dans les anciens langages de programmation, lorsqu'elles sont incluses dans le langage de programmation, ont les appels les bibliothèques standard. Toutefois, la plupart des langages de programmation offrent la possibilité d'ajouter des bibliothèques externes à leur bibliothèque standard.
Les bibliothèques logicielles ont évolué avec les années, et sont maintenant soit dépendant d'un langage de programmation, d'un système d'exploitation ou d'un réseau. Elles ont cependant tout le même objectif, c'est à dire de permettre l'ajout de fonctionnalité à un programme.
Voici la liste des différentes techniques de bibliothèques logicielles :
Technique | Nom anglais | Description |
---|---|---|
Bibliothèque statique | Static libraries | Cette technique permet d'indiquer une bibliothèque destinée à être copiée, sans modification, dans les programmes l'utilisant lorsque compilation d'un programme. |
Bibliothèque partagée | Shared libraries | Cette technique permet d'indiquer une bibliothèque partageant ses fonctionnalités et ses données entre différents programmes. Cette bibliothèque n'est pas incluse dans le code du programme lui-même, il s'agit généralement d'un fichier séparé. |
Bibliothèque de liaison dynamique | Dynamic-link library | Cette technique permet de lier le programme est en cours de chargement ou à son exécution plutôt que lorsque le fichier exécutable est créé. Les formes les plus connues de cette technique sont les DLL des systèmes d'exploitation Windows et OS/2 ou les DSO du système d'exploitation de style Unix. Cette technique provient à l'origine du système d'exploitation Multics développé en 1964 au MTS (Michigan Terminal System). |
Bibliothèque à distance | Remote libraries | Cette technique permet d'indiquer une bibliothèque de code à distance, c'est-à-dire une bibliothèque présente sur un réseau, mais sur la même machine. Elle utilise généralement un RPC (Remote Procedure Call). |
Bibliothèque de composantes | Component Library | Cette technique permet d'inclure des composantes d'environnement graphique et des ressources dans une bibliothèque. Les exemples les plus connus sont le VCL (Visual Component Library), LCL (Lazarus Component Library) et le CLX (Component Library X). |
Éditeur de liens | Linkers | Cette technique permet de combiner différents fichiers de code objet avec des bibliothèques afin de produire un programme exécutable. |
Table de symboles | Symbol table | Cette technique permet de structurer les données des différents éléments de programmes (fonction, procédure, routine, variable, constante,..) et ou bibliothèque (fonction, procédure, routine, variable, constante,..) afin d'avoir une forme de cartographie permettant de déterminer les emplacements de chacun. |
Bibliothèque statique
Une bibliothèque statique est un ensemble de fonctions compilées étant directement intégrées dans l'exécutable final lors du processus de compilation. Les fichiers objets, étant le résultat de la compilation du code source, sont combinés avec le programme principal pour créer un binaire autonome. Une fois que la bibliothèque statique est liée au programme, elle fait partie intégrante du fichier exécutable, ce qui signifie que le programme n'a plus besoin de la bibliothèque originale lors de l'exécution. Ce processus augmente généralement la taille de l'exécutable, mais garantit que toutes les dépendances sont résolues et qu'aucun fichier externe n'est nécessaire pour le bon fonctionnement de l'application.
L'un des avantages des bibliothèques statiques est la portabilité. Comme tout le code requis pour exécuter le programme est inclus dans l'exécutable, il peut être transféré et exécuté sur d'autres systèmes sans avoir à se soucier des versions de bibliothèque ou de la configuration du système hôte. Cela simplifie le déploiement et évite les problèmes liés à l'incompatibilité de versions. Cependant, cela a un coût : le fichier exécutable peut devenir volumineux, et toute modification apportée à la bibliothèque nécessite une recompilation complète du programme, ce qui peut être peu pratique dans des environnements où les mises à jour fréquentes sont nécessaires.
En outre, la duplication des bibliothèques statiques peut entraîner une utilisation inefficace de la mémoire si plusieurs programmes utilisent la même bibliothèque. Chaque programme aura sa propre copie de la bibliothèque en mémoire, ce qui peut rapidement consommer des ressources sur des systèmes avec des contraintes de mémoire. C'est pourquoi, dans des environnements où les bibliothèques doivent être partagées entre plusieurs applications, les bibliothèques partagées ou dynamiques sont souvent préférées.
Bibliothèque partagée
Les bibliothèques partagées, également appelées bibliothèques dynamiques, permettent de réduire la taille des fichiers exécutables en ne les liant pas directement aux programmes lors de la compilation, mais en les chargeant uniquement à l'exécution. Cela permet à plusieurs programmes de partager la même bibliothèque en mémoire, améliorant ainsi l'efficacité de l'utilisation des ressources. Sur les systèmes Linux, ces bibliothèques sont souvent identifiées par l'extension .so (shared object), tandis que sous Windows, elles sont généralement appelées .dll (Dynamic Link Library). Le chargement dynamique permet également des mises à jour des bibliothèques sans avoir besoin de recompiler les programmes qui les utilisent.
L'utilisation de bibliothèques partagées offre une grande flexibilité, car un programme peut charger des bibliothèques spécifiques selon ses besoins. Les systèmes d'exploitation fournissent souvent des mécanismes de gestion de version pour les bibliothèques partagées, afin que différents programmes puissent utiliser différentes versions d'une même bibliothèque, réduisant ainsi les conflits de version. En outre, cela permet de maintenir un seul exemplaire de la bibliothèque sur le système, économisant ainsi de l'espace disque et de la mémoire, car plusieurs programmes peuvent partager une copie unique de la bibliothèque en mémoire.
Cependant, cette approche présente également des inconvénients. Si une bibliothèque partagée est modifiée ou supprimée, cela peut entraîner des erreurs pour les programmes en dépendant, un phénomène parfois appelé "hell of dependencies" (enfer des dépendances). De plus, les performances peuvent être légèrement affectées, car le système d'exploitation doit gérer le chargement et la résolution des symboles des bibliothèques dynamiques à l'exécution, ce qui peut ajouter un temps d'initialisation pour les programmes.
Bibliothèque de liaison dynamique
Les bibliothèques de liaison dynamique (DLL sous Windows, ou shared objects sous Linux) permettent de lier des fonctions ou du code externe à un programme de manière dynamique, c'est-à-dire au moment de l'exécution plutôt qu'à la compilation. Contrairement aux bibliothèques statiques, les DLL ne sont pas intégrées au binaire final. Au lieu de cela, elles sont stockées séparément et peuvent être mises à jour indépendamment du programme. Lorsque le programme s'exécute, il appelle la DLL pour accéder aux fonctionnalités ou au code qu'elle contient, ce qui permet une certaine flexibilité dans la gestion des dépendances logicielles.
Cette méthode présente plusieurs avantages, notamment la réduction de la taille des fichiers exécutables et la possibilité de partager les DLL entre plusieurs programmes exécutés sur le même système. En effet, une seule copie de la bibliothèque est chargée en mémoire, économisant ainsi des ressources. Cela permet également de mettre à jour les DLL indépendamment des applications qui les utilisent, ce qui peut être bénéfique dans des environnements où des correctifs ou des mises à jour sont fréquents. Tant que les interfaces de la bibliothèque restent inchangées, le programme peut continuer à fonctionner sans nécessiter de recompilation.
Cependant, les bibliothèques de liaison dynamique présentent également certains défis. Si une DLL est corrompue ou supprimée, les programmes qui en dépendent peuvent échouer à se lancer, provoquant des erreurs d'exécution. De plus, les systèmes doivent gérer la résolution des symboles au moment de l'exécution, ce qui peut introduire un léger surcoût en termes de performance et un risque de conflit de version lorsque plusieurs applications nécessitent des versions différentes de la même DLL.
Bibliothèque à distance
Les bibliothèques à distance permettent à un programme d'accéder à des fonctions ou des services situés sur un autre système via un réseau. Cela est particulièrement utile dans les environnements distribués où la logique ou les ressources d'une application doivent être externalisées sur un serveur ou dans l'infonuagique. Des technologies comme RPC (Remote Procedure Call) ou SOAP permettent de créer des appels vers des fonctions hébergées à distance, comme si elles étaient locales, tout en masquant les détails de la communication réseau.
Ces bibliothèques sont souvent utilisées dans les architectures orientées services (SOA) ou les microservices, où des fonctionnalités spécifiques sont déléguées à des serveurs dédiés. Cela permet d'améliorer l'évolutivité des applications, en déplaçant des charges de calcul lourdes ou des services spécialisés vers des serveurs plus puissants. Par exemple, une application peut utiliser une bibliothèque à distance pour effectuer des calculs intensifs ou pour accéder à des bases de données complexes hébergées sur des serveurs à distances.
Toutefois, l'utilisation de bibliothèques à distance comporte des défis, notamment la gestion de la latence et la fiabilité des réseaux. Les performances peuvent être affectées si le réseau est lent ou instable, et des mécanismes de gestion des erreurs doivent être mis en place pour traiter les interruptions de communication. De plus, la sécurité est un enjeu majeur, car les données échangées entre les systèmes peuvent être sensibles et nécessiter des protocoles d'authentification et de chiffrement robustes.
Bibliothèque de composantes
Les bibliothèques de composantes regroupent des composantes logiciels modulaires pouvant être assemblés pour créer des applications plus complexes. Chaque composant est indépendant et représente une unité fonctionnelle autonome, ce qui permet de les réutiliser dans différentes applications sans avoir à redévelopper de code. Un exemple bien connu de bibliothèque de composantes est le modèle (COM (Component Object Model) de Microsoft, où les composantes peuvent interagir entre eux au sein d'un environnement Windows tout en restant indépendants.
Ce type de bibliothèque permet de créer des architectures logicielles flexibles et modulaires. Les développeurs peuvent assembler des composantes pour créer des applications sur mesure, en remplaçant ou en mettant à jour des parties spécifiques sans affecter l'ensemble du programme. Les bibliothèques de composantes sont également souvent utilisées dans des environnements distribués, où différents composants peuvent être déployés sur des serveurs distincts et communiquent via des interfaces bien définies, favorisant ainsi la mise à l'échelle et la maintenance.
Un autre avantage des bibliothèques de composantes réside dans leur capacité à s'adapter à des environnements hétérogènes. Par exemple, dans le cadre de CORBA (Common Object Request Broker Architecture), des composantes écrits dans des langages de programmation différents peuvent interagir les uns avec les autres, facilitant ainsi l'intégration d'anciens systèmes avec de nouvelles technologies. Cependant, la gestion de la compatibilité et la complexité de l'intégration peuvent représenter un défi dans les systèmes très interconnectés.
Éditeur de liens
L'éditeur de liens, également connu sous le nom de linker, est un outil crucial dans le processus de compilation des programmes informatiques. Sa fonction principale est de combiner plusieurs fichiers objets générés par le compilateur en un seul fichier exécutable ou une bibliothèque. Cela inclut la résolution des références entre les différents fichiers, l'ajout des adresses mémoire appropriées pour chaque symbole et la création d'une structure de programme cohérente. L'éditeur de liens prend en compte les symboles définis et référencés dans les fichiers objets pour s'assurer que toutes les fonctions et variables sont correctement liées entre elles.
L'éditeur de liens travaille sur les fichiers objets contenant le code machine ainsi que des tables de symboles. Lorsqu'il assemble ces fichiers, il vérifie les symboles pour détecter d'éventuels conflits et résout les dépendances. Cela signifie que si un fichier objet fait référence à une fonction définie dans un autre fichier, l'éditeur de liens s'assure que cette fonction est correctement intégrée dans le fichier exécutable final. En plus de l'assemblage des fichiers, l'éditeur de liens peut également effectuer des optimisations, comme la suppression de code inutilisé ou la fusion de sections similaires, afin de réduire la taille du binaire final et d'améliorer les performances d'exécution.
Il existe deux types principaux d'éditeurs de liens : les éditeurs de liens statiques et les éditeurs de liens dynamiques. Un éditeur de liens statiques combine les fichiers objets au moment de la compilation, créant un exécutable autonome. En revanche, un éditeur de liens dynamiques résout les références aux bibliothèques partagées au moment de l'exécution, ce qui permet de réduire la taille des exécutables et de faciliter les mises à jour des bibliothèques sans recompilation des programmes les utilisant. Cette flexibilité est particulièrement importante dans les applications modernes, où plusieurs programmes peuvent partager les mêmes bibliothèques, contribuant ainsi à une gestion plus efficace des ressources et à une meilleure modularité du code.
Table de symboles
La table de symboles est une structure de données essentielle utilisée dans la compilation et l'édition des liens des programmes informatiques. Elle est principalement utilisée pour stocker des informations sur les identificateurs (ou symboles) présents dans le code source, tels que les variables, les fonctions, les classes et les objets. Chaque entrée de la table de symboles contient des détails pertinents sur un symbole, y compris son nom, son type, son emplacement en mémoire, sa portée et éventuellement d'autres métadonnées. Cela permet aux compilateurs de suivre les symboles déclarés et utilisés dans le code, facilitant ainsi le processus de compilation et d'édition des liens.
Lors de la compilation, le compilateur construit progressivement la table de symboles en analysant le code source. Chaque fois qu'un nouveau symbole est rencontré, il ajoute une entrée dans la table avec les informations nécessaires. Lorsque le compilateur rencontre une référence à un symbole, il consulte la table pour s'assurer que le symbole a été correctement défini et pour récupérer des informations sur son type et sa portée. Cela aide à détecter les erreurs de compilation, telles que les références à des symboles non déclarés ou les conflits de type, garantissant ainsi que le code source est valide avant la génération du code machine.
L'éditeur de liens utilise également la table de symboles pour résoudre les références entre les différents fichiers objets lors de la création de l'exécutable final. Il recherche dans la table les symboles externes nécessaires à l'assemblage du programme, en liant correctement les symboles à leur définition correspondante. Cela est particulièrement important dans les projets de grande envergure qui impliquent de multiples fichiers objets et bibliothèques. Cependant, la gestion des tables de symboles peut devenir complexe, notamment en raison des conflits de noms et des dépendances entre différents modules. Pour éviter ces problèmes, il est essentiel d'utiliser des conventions de nommage appropriées et de structurer le code de manière à minimiser les collisions de symboles.