La complexité croissante des structures logicielles modernes met régulièrement les développeurs de logiciels au pied du mur. La complexité des logiciels rend le travail des développeurs épuisant car la planification, la construction et le test des produits deviennent difficiles. L’introduction de nouveaux défis en matière de sécurité crée une frustration chez les administrateurs et les utilisateurs. Dans la plupart des cas, il est impossible de distinguer ce qui est compliqué de ce qui est complexe, mais ce n’est pas le cas ici. La complexité suggère que quelque chose est difficile à comprendre, mais qu’avec le temps et des efforts, on peut finir par le connaître. D’autre part, le complexe représente l’interconnexion entre plusieurs entités. Lorsque le nombre d’entités augmente, les interconnexions augmentent aussi considérablement et atteignent un point où il est impossible de les connaître et de les comprendre.
De même, une complexité excessive des logiciels augmente le risque d’obstruction accidentelle des interconnexions. Un élément qui augmente le risque d’introduire des défauts lors de la mise en œuvre de changements peut rendre l’amélioration du logiciel pratiquement impossible.
Complexité des logiciels
La complexité d’un logiciel est la difficulté de maintenir, d’analyser, de tester, de modifier et de concevoir un logiciel. Plus la complexité est élevée, plus il est difficile de lire et de maintenir le logiciel, et plus les risques d’erreurs et de défauts sont élevés. La complexité d’un logiciel est une technique qui exprime un ensemble spécifique de caractéristiques du code. Ces caractéristiques se concentrent toutes sur la manière dont votre code se connecte à d’autres morceaux de code.
La complexité des logiciels est considérée comme un facteur déterminant des coûts de maintenance des logiciels. Une complexité logicielle accrue implique que les projets de maintenance et d’amélioration prendront plus de temps, coûteront beaucoup plus cher et entraîneront plus de défauts. La complexité logicielle d’un système particulier est l’un des principaux avantages à long terme des outils et approches utilisés lors de son développement initial. Par exemple, l’utilisation de nouveaux équipements CASE entraîne le développement de logiciels mal structurés. Les conséquences de cette mauvaise structure se feront sentir lorsqu’il sera temps d’ajuster le système.
Types de complexité des logiciels
La complexité des logiciels devient de plus en plus problématique à mesure que l’industrie de l’ingénierie évolue. En tant que développeur, vous passez souvent beaucoup de temps à écrire, mais vous passez encore plus de temps à maintenir ce code. Combien de fois vous arrive-t-il de constater que le code s’est enchevêtré et que vous n’arrivez presque plus à le comprendre ? Pour bien comprendre comment gérer la complexité sans cesse croissante, il est essentiel de différencier les trois types fondamentaux de complexité logicielle.
Complexité essentielle
La complexité essentielle se trouve généralement dans le domaine d’activité dans lequel vous travaillez. Elle est liée au problème et ne peut être supprimée. Vous vous associez à des règles d’entreprise qui régissent les procédures d’entreprise de manière plus spécifique. Lorsque vous vous efforcez d’appliquer et d’automatiser le traitement de ces règles, vous rencontrez différents niveaux de complexité. Le fait que les entreprises soient généralement des environnements extrêmement impénétrables rend le problème que vous tentez de résoudre intrinsèquement complexe. La complexité essentielle est générée par les attributs du problème à résoudre et ne peut être réduite.
Quels que soient vos efforts, cette complexité ne peut être réduite car la politique commerciale régissant le traitement d’une demande d’indemnisation prévoit 15 étapes distinctes. Par conséquent, vous ne pouvez pas clarifier les règles en sautant certaines étapes et en réduisant le traitement à quelques étapes de base. En résumé, la complexité essentielle est inévitable et c’est principalement la véritable raison pour laquelle vous êtes employé en tant qu’ingénieur logiciel.
Complexité accidentelle
Cette complexité est liée à la résolution d’un problème directement liée à la manière dont vous choisissez de le résoudre et est moins associée à la nature de la complication. Lorsque vous adoptez une stratégie pour résoudre un problème qui nécessite plus de complexité et de travail, il s’agit d’une complexité accidentelle. Il peut s’agir du choix de vos outils de développement logiciel et de ce que vous mettez sur la table lorsque vous déchiffrez le problème. Cette complexité n’est pas inhérente à la situation que vous devez résoudre, mais s’y est glissée par accident. La complexité accidentelle se manifeste par une mauvaise conception ou structure, un code médiocre et des procédures de développement logiciel inférieures aux normes. La seule façon de supprimer la complexité accidentelle est d’en éliminer la source.
Vous ne pouvez pas mettre en place une complexité accidentelle intentionnellement. Le nom même de la complexité accidentelle en dit long. Elle apparaît parfois lorsque vous :
- Vous souhaitez utiliser un nouveau langage ou un nouvel outil pour venir à bout d’un projet qui n’est pas approprié ?
- Êtes-vous obligé d’utiliser une technologie spécifique ?
- Manque de connaissance des pratiques les plus acceptables pour déchiffrer ce problème particulier.
Causes de la complexité des logiciels
Le problème fondamental des logiciels est leur complexité. Un logiciel est un système à grande échelle composé de centaines de microservices qui s’appellent et dépendent les uns des autres. De nombreux aspects du logiciel peuvent ne pas être très clairement définis. Nous abordons ici certaines des causes cruciales qui conduisent à la complexité dans le développement de logiciels, comme indiqué ci-dessous.
- Choisir les mauvais outils. Il arrive que vous soyez pressé de commencer ou que vous aimiez utiliser un outil particulier lorsque vous travaillez sur du code. Disons que vous travaillez sur un site web de quatre pages qui nécessite Ruby on Rails ou une API web RESTful, mais que vous insistez pour construire le site en utilisant Objective C. Je ne veux pas dire que Objective C est efficace ou suffisamment bon, mais il a juste été mis en œuvre pour le mauvais problème. Cela peut entraîner une certaine complexité dans votre code.
- Construire des systèmes sur des systèmes – les systèmes sont formulés de manière hiérarchique. Par exemple, les systèmes bancaires sont créés à partir d’un logiciel Internet construit sur un logiciel de télécommunications. Les logiciels de télécommunication décentralisent le pouvoir d’achat et le pouvoir de décision en interne et en externe en raison de la reconfiguration agile cruciale du nuage. Cela entraîne également une complexité des logiciels.
- Application des mauvaises abstractions. De temps en temps, vous découvrirez un logiciel qui traite d’un vocabulaire particulier, par exemple les notices de bibliothèque, mais qui a été écrit dans un autre langage, par exemple un type de données de type CMSes posts. L’abstraction est bonne, mais ce n’est pas la bonne. Tout a été rendu beaucoup plus difficile par la nécessité de manipuler l’incohérence entre les deux concepts.
DES OUTILS POUR RÉDUIRE LA COMPLEXITÉ DU CODAGE
La fonctionnalité incorporée dans un système et l’intégration entre ses sous-systèmes influencent ouvertement la complexité du système. Une stabilité idéale entre les fonctionnalités et la coordination au sein d’un système est nécessaire pour réduire la complexité. Dans le monde réel, il n’est pas toujours possible de garder le logiciel simple. En règle générale, les attributs d’application qui offrent une valeur commerciale ont tendance à être complexes. Cependant, de nombreuses méthodes se concentrent sur la réduction de la complexité pour les ingénieurs ; d’autres approches peuvent être utilisées pour minimiser le niveau de complexité de votre application au-delà de l’utilisation d’architectures de microservices.
Développement assisté par logiciel
Il s’agit de la capacité à utiliser des outils, généralement assistés par des techniques d’intelligence artificielle et d’apprentissage automatique, pour vous aider à écrire du code, à diagnostiquer les problèmes dans le code et à contrôler la complexité globale du code. Cette approche vous permet d’exécuter des tests précis et rapides qui minimisent le taux de complexité, car les bogues sont facilement repérés et réduisent le processus de développement. Des entreprises comme GitHub utilisent l’IA pour aider les développeurs à écrire un code plus fiable avec moins de défauts.
Mise en place d’une plateforme interne
La complexité croissante a incité de nombreuses entreprises à adopter un modèle de plateforme interne. L’équipe de la plateforme interne est chargée d’évaluer les outils les plus importants pour les ingénieurs, de structurer les modèles et de faciliter leur processus de production. L’équipe se concentre également sur des fonctions telles que la sécurité, les opérations financières et la gouvernance afin de réduire la charge cognitive des développeurs individuels.
La solution pour disposer d’une plateforme interne acceptable pour les développeurs consiste à respecter l’équilibre entre le libre-service pour les développeurs qui veulent s’atteler à la tâche et l’abstraction des tâches pratiques mineures sans restreindre les développeurs.
MESURES DE LA COMPLEXITÉ DES LOGICIELS
Plus la complexité est élevée, plus il est difficile de maintenir et de lire le code, et plus vous rencontrerez d’erreurs et de défauts. Mesurer la complexité d’un logiciel peut vous aider à comprendre le problème et à vous y attaquer lorsqu’il est encore mineur. Les mesures suivantes peuvent être utilisées pour évaluer la complexité.
Complexité cyclomatique
Cette mesure est basée sur la théorie des graphes et d’autres définitions mathématiques. La complexité cyclomatique mesure la complexité structurelle du code. Elle évalue le nombre de chemins linéairement indépendants dans un programme. Une approche linéairement indépendante est une façon élégante de dire qu’il s’agit d’un chemin unique où vous ne comptez les boucles qu’une seule fois. Les opérations telles que IF, DO et SELECT constituent une logique conditionnelle, ce qui rend le programme plus difficile à comprendre. Plus il y a de procédures de ce type dans le code, plus il y a de branches logiques et plus la complexité cyclomatique est élevée.
Cette mesure peut être déterminée à l’aide de la formule suivante
V(G) = e – n + 2p
Où : e = est le nombre d’arêtes dans le graphe
n = nombre de notes dans le graphique
p = nombre de composants connectés
Indice de maintenabilité
Il calcule la valeur de l’indice entre 0 et 100, ce qui constitue la facilité relative de maintenance du code. En d’autres termes, cette métrique mesure le degré de maintenabilité de votre code. Plus la valeur est élevée, meilleure est la maintenabilité de votre code. L’indice de maintenabilité est calculé à partir d’une formule factorisée de SLOC (Source Lines Of Code), de la complexité cyclomatique et du volume de Halstead.
Halstead Metrics
Cette mesure évalue la quantité d’informations factuelles contenues dans le code source, y compris le nombre de variables et la manière dont elles sont utilisées dans le code source, les fonctions et les méthodes. L’hypothèse est que plus il y a d’éléments indépendants dans le code et plus ils sont utilisés, plus le programme est complexe. Cette mesure dépend de l’exécution du code et de ses mesures, qui sont calculées de manière statique à partir des opérateurs et des opérandes du code source.
La métrique de Halstead peut être calculée à l’aide de la formule suivante
Difficile = L / V
Où : L = Niveau du programme
V = Volume du programme
La formule pour déterminer le niveau L du programme est la suivante :
L = (2 + n2*) *log2 (2 + n2*)
Où : n1 = nombre d’opérateurs
N2 = nombre d’opérandes
Le programme permettant de déterminer le volume du programme V est le suivant :
V = (N1 + N2)* log2 (n1 + n2)
Où : N1 = nombre total d’occurrences de l’opérateur : N1 = nombre total d’occurrences de l’opérateur
N2 = nombre total d’occurrences de l’opérande
Métriques de conception orientée objet
Les mesures quantitatives pour la conception orientée objet se concentrent généralement sur les classes et les caractéristiques de conception. Elles permettent aux développeurs d’évaluer le logiciel dès le début du développement et de comprendre comment minimiser la complexité et améliorer la maintenabilité.
LES EFFETS DE LA COMPLEXITÉ DES LOGICIELS
Impact de la complexité sur les taux d’erreur.
La raison pour laquelle nous, développeurs, sommes préoccupés par la complexité est liée à des caractéristiques plus importantes du processus de développement de logiciels. Plus le code est difficile à comprendre, plus les erreurs de programmation risquent de ne pas être découvertes. Lorsqu’un programme est difficile à tester, les erreurs ne seront pas détectées avant que le logiciel ne fonctionne.
Vous vous attendez à des taux d’erreur élevés dans les programmes qui présentent une forte densité de décisions (avec un nombre égal de chemins de décision pour tester les erreurs). Ces systèmes sont susceptibles de générer de nouvelles erreurs.
Impact de la complexité sur les coûts de maintenance
La complexité des logiciels a un impact direct sur les coûts de maintenance. Plus la maintenance d’un système d’application complexe est exigeante, plus les dépenses liées à la maintenance, qui absorbe la majeure partie du processus de développement, seront élevées. La maintenance des logiciels est perçue comme une procédure de production dont les intrants sont les ressources informatiques et la main-d’œuvre, et dont le résultat est un code amélioré. Les heures de travail sont beaucoup plus importantes que les ressources informatiques, et les deux ont des possibilités de remplacement insignifiantes. L’attention est portée sur les heures de travail en tant que dépense considérable.
UN REMÈDE À LA COMPLEXITÉ DANS LE DÉVELOPPEMENT DE LOGICIELS
Même si les architectures de microservices créent des applications plus étendues et plus complexes, elles démêlent le travail des développeurs de base. Les architectures de microservices génèrent une application plus complexe qu’une application correspondante construite comme un monolithe. Cela ne signifie pas pour autant que le travail du développeur est plus compliqué.
Complexité de l’architecture des microservices.
L’architecture microservices est une technique DevOps plus dynamique et plus agile pour l’exécution, le développement et la gestion d’applications en travaillant avec des composants modulaires plutôt qu’avec une construction monolithique.
Pour beaucoup, les microservices sont censés résoudre tous vos problèmes de complexité logicielle. Cependant, ils ne peuvent à eux seuls réhabiliter que 50 % de ces problèmes. Pour résoudre l’autre moitié, vous devez fusionner les microservices avec les dernières pratiques DevSecOps et transformer votre entreprise en une véritable machine à tuer.
Les microservices permettent aux entreprises d’exécuter un million de déploiements par jour, de faire évoluer le système à l’infini, de minimiser la complexité de la base de code et d’économiser des ressources. Les microservices déplacent la complexité des services vers la plateforme, en ignorant les faits, on obtient des résultats sous-optimaux. De nombreuses entreprises ont conçu des applications monolithiques et se sont aperçues qu’elles devenaient trop complexes. En tant que développeur travaillant dans une base de code unique, il est fastidieux d’ajouter des fonctionnalités et de corriger des défauts de manière indépendante. En général, cela limite le nombre de projets sur lesquels vous pouvez travailler dans une seule application.
Les microservices rendent une application moins complexe en en supprimant certains éléments. Lorsque vous divisez l’application en différents modules, vous essayez de diviser cette complexité afin de minimiser le nombre de développeurs travaillant dans une base de code unique. La division peut se faire de manière à développer une complexité organisée et facile à comprendre.
Le modèle de complexité des logiciels
Les causes de la complexité ont été examinées dans la genèse de ce chapitre. La complication donne au projet une complexité inhérente, puis une plus grande complexité apparaît au cours de la conception et de la phase du processus de développement du logiciel. Sur la base de ce modèle, la complexité s’associe à d’autres facteurs pour déterminer la propension aux erreurs et la taille du programme. La discussion sur la nature, les sources et les effets de la complexité des logiciels ainsi qu’un cadre théorique pour une présentation graphique du concept de complexité des logiciels ont également été fournis.
CONCLUSION
De nombreuses entreprises doivent faire face à la complexité des logiciels, et les approches que vous utilisez pour y faire face auront une incidence sur l’avenir de votre entreprise. Il existe plusieurs façons de gérer la complexité des logiciels. Des approches telles que l’établissement d’une plateforme interne et la standardisation des services externes dans l’ensemble de l’entreprise peuvent constituer de bonnes stratégies.
En outre, bien que les architectures de microservices augmentent la complexité du logiciel, elles permettent de minimiser la charge cognitive et la complexité visuelle pour les développeurs individuels.