Les bibliothèques C++ POCO (POCO signifie « Portable Components ») forment une collection de bibliothèques de classes C++ open source qui simplifient et accélèrent le développement d'applications portables orientées réseau en C++. Ces bibliothèques offrent une foule de fonctionnalités, allant des clients et serveurs HTTP et HTTPS à l'analyse XML, au chiffrement des données, à la prise en charge des threads, et bien plus encore.
Nous nous appuyons sur la bibliothèque POCO depuis plus de quinze ans pour vérifier que CppDepend évalue correctement les projets bien implémentés. Cette appréciation ne découle donc pas d'une rencontre passagère avec la bibliothèque, mais d'une analyse approfondie de ses nombreuses versions au cours des quinze dernières années.
Explorons un extrait de code issu du code source de POCO :
Cette implémentation de méthode se caractérise par :
- Un petit nombre de paramètres.
- Des assertions utilisées pour vérifier la validité des entrées.
- Les noms de variables sont faciles à comprendre.
- La méthode est courte.
- Aucun commentaire superflu dans le corps ; le code est auto-explicatif.
- Le corps de la fonction est bien indenté.
- La STL est utilisée à bon escient.
En explorant le code source de POCO, on constate immédiatement la cohérence de son implémentation : les mêmes règles de bonnes pratiques sont appliquées à chaque fonction. En parcourant le code source, il devient évident que POCO reste accessible même aux débutants en C++. Plus précisément, POCO présente les caractéristiques suivantes :
- Il n'est pas victime de sur-ingénierie, et il n'est pas nécessaire de posséder des compétences avancées en C++ pour comprendre son implémentation.
- Les classes publiques proposées aux utilisateurs finaux sont bien organisées et simples à utiliser.
- La conception est modulaire : la bibliothèque est divisée en plusieurs projets, chacun répondant à un besoin précis.
- Pour ceux qui recherchent une utilisation avancée de la bibliothèque, étendre, personnaliser ou modifier le comportement de certaines classes est remarquablement simple.
Dans ce billet, nous nous concentrerons sur quelques aspects clés de sa conception :
ABSTRACTION CONTRE INSTABILITÉ
Robert C. Martin a écrit un article intéressant sur un ensemble de métriques permettant de mesurer la qualité d'une conception orientée objet du point de vue de l'interdépendance entre les sous-systèmes de cette conception.
Voici ce qu'il disait dans cet article à propos de l'interdépendance entre modules :
Qu'est-ce qui rend une conception rigide, fragile et difficile à réutiliser ? C'est l'interdépendance des sous-systèmes qui la composent. Une conception est rigide si elle ne peut pas être modifiée facilement. Cette rigidité tient au fait qu'une simple modification d'un logiciel fortement interdépendant déclenche une cascade de changements dans les modules dépendants. Lorsque l'ampleur de cette cascade ne peut être anticipée par les concepteurs ou les mainteneurs, l'impact de la modification ne peut être estimé. Cela rend son coût impossible à évaluer. Face à une telle imprévisibilité, les responsables deviennent réticents à autoriser les changements. La conception devient ainsi rigide.
Et pour combattre la rigidité, il a introduit des métriques telles que le couplage afférent, le couplage efférent, l'abstraction, l'instabilité, la « distance par rapport à la séquence principale » et le graphe « Abstraction vs Instabilité ».
Le graphe « Abstraction vs Instabilité » peut être utile pour identifier les projets difficiles à maintenir et à faire évoluer. Voici ce graphe pour la bibliothèque POCO :

L'idée derrière ce graphe est que plus un élément de code est largement utilisé, plus il devrait être abstrait. Autrement dit, évitez de dépendre trop fortement des implémentations ; dépendez plutôt d'abstractions. Par élément de code largement utilisé, j'entends un projet (mais l'idée vaut aussi pour les packages et les types) massivement utilisé par les autres projets du programme.
Il n'est pas judicieux d'avoir des types concrets largement utilisés dans toute votre base de code. Cela crée des zones de douleur (Zones of Pain) dans votre programme, où modifier les implémentations peut potentiellement affecter une grande partie du programme. Or les implémentations sont connues pour évoluer plus souvent que les abstractions.
La ligne de la séquence principale (en pointillés) dans le diagramme ci-dessus montre comment abstraction et instabilité devraient s'équilibrer. Un composant stable se situerait à gauche. En examinant la séquence principale, on constate qu'un tel composant devrait être très abstrait pour se rapprocher de la ligne souhaitable — à l'inverse, si son degré d'abstraction est faible, il se situe dans une zone appelée « zone de douleur ».
Seul le projet Foundation se trouve dans la zone de douleur, ce qui est normal car il est largement utilisé par les autres projets et contient surtout des classes utilitaires qui ne sont pas abstraites.
COHÉSION DES TYPES
Le principe de responsabilité unique énonce qu'une classe ne devrait pas avoir plus d'une raison de changer. Une telle classe est dite cohésive. Une valeur LCOM élevée signale généralement une classe peu cohésive. Il existe plusieurs métriques LCOM. Le LCOM prend ses valeurs dans l'intervalle [0-1]. Le LCOMHS (HS pour Henderson-Sellers) prend ses valeurs dans l'intervalle [0-2]. Notez que la métrique LCOMHS est souvent considérée comme plus efficace pour détecter les types non cohésifs. Une valeur LCOMHS supérieure à 1 doit être considérée comme alarmante.


Seuls 1 % des types sont considérés comme non cohésifs.
Dans ce billet, nous avons offert un bref aperçu de la conception de POCO. Dans de prochains billets, nous explorerons sa conception et son implémentation plus en détail pour comprendre pourquoi cette bibliothèque se distingue comme l'une des bibliothèques C++ open source les mieux implémentées.
