I. Maturité du processus de développement logiciel
Le fondement de la qualité logicielle réside dans la standardisation des processus de développement. Les niveaux de capacité SPICE pour l'automobile constituent actuellement la référence du secteur en matière de maturité des processus logiciels, mais atteindre CL2 ou CL3 n'est que la référence. Ce qui détermine véritablement la qualité de la livraison des logiciels, c'est le contrôle des écarts lors de l'exécution du processus. En prenant la gestion des exigences comme exemple, une déviation courante est qu'après une modification d'une exigence, les scénarios de test associés ne sont pas mis à jour de manière synchrone. Dans un projet, une fonction de mise à niveau OTA s'est avérée après une SOP comme présentant un problème : lorsque le véhicule était dans un état de charge faible, la tâche de téléchargement OTA était suspendue indéfiniment sans signaler d'erreur. La cause première était que le document d'exigence avait ajouté une logique de protection contre un faible état de charge, mais les scénarios de test correspondants couvraient toujours uniquement la vérification de la fonction de téléchargement sans inclure les scénarios d'interruption et de récupération. De l’introduction à la découverte, ce défaut s’est étendu sur quatre versions itératives, et le coût de correction était près de quarante fois plus élevé que s’il avait été découvert plus tôt. La matrice de traçabilité des exigences doit être intégrée dans le pipeline d'intégration continue. Lorsqu'un statut d'exigence devient modifié, les tâches de révision pour les scénarios de test associés doivent être automatiquement déclenchées et les scénarios de test qui n'ont pas réussi la révision doivent être marqués comme éléments bloquants. La révision du code doit également être quantifiée. La recherche montre que les modules avec moins de deux commentaires de révision pour mille lignes de code ont une densité de défauts post--plus de trois fois supérieure à celle des modules avec plus de cinq commentaires pour mille lignes. Cependant, le nombre de commentaires d'avis ne peut pas être utilisé comme indicateur absolu car il existe également des commentaires de faible-qualité. Une approche efficace consiste à classer les commentaires d'examen en cinq catégories : erreurs logiques, conditions aux limites manquantes, lisibilité du code, risques de performances et risques de sécurité, avec un accent particulier sur le taux de détection des deux catégories fatales : erreurs logiques et risques de sécurité.
II. Intégration continue et tests continus
L'accélération de l'itération logicielle nécessite de déplacer les tests vers la gauche, ce qui signifie que la vérification de la qualité est introduite au stade de la validation du code. Les tests unitaires constituent la ligne de défense la plus à gauche, mais dans les projets réels, la couverture du code des tests unitaires souffre souvent de valeurs exagérées. Dans un projet de contrôleur, le rapport de test unitaire indiquait une couverture de ligne de 92 %, mais un grand nombre d'erreurs fondamentales étaient encore détectées lors des tests d'intégration. Une analyse rétrospective a révélé que bien que les lignes de code contenant ces erreurs aient été exécutées, les assertions de test n'ont pas vérifié les sorties pertinentes. La couverture de ligne indique uniquement que le code a été exécuté, et non que les sorties ont été vérifiées. Une méthode d'amélioration consiste à introduire des tests de mutation, qui génèrent automatiquement des mutants de code pour évaluer l'efficacité des cas de test. Si un mutant n'est pas tué, cela indique une lacune dans les assertions du test. Un autre problème dans les pipelines d’intégration continue est le temps d’exécution excessif des tests. Dans le référentiel de logiciels d'un OEM, l'exécution de la suite complète de tests de régression nécessitait plus de 20 heures, ce qui signifiait que les développeurs devaient souvent attendre le lendemain pour recevoir des commentaires après avoir soumis le code. Les solutions incluent des tests parallèles, la priorisation des cas de test et des tests incrémentiels. Les tests parallèles répartissent la suite de tests sur plusieurs nœuds d'exécution, réduisant ainsi le temps d'exécution à environ un -dixième de celui d'origine. La priorisation des cas de test est basée sur la distribution historique des défauts, en donnant la priorité aux 20 % de cas de test les plus susceptibles de détecter de nouveaux défauts. Ce sous-ensemble peut capturer environ 70 % des nouveaux défauts. Les tests incrémentiels exécutent uniquement les cas de test liés à la modification de code actuelle, en utilisant une analyse statique pour identifier l'étendue de l'impact de la modification afin de filtrer dynamiquement la portée du test.
III. Mesure des défauts logiciels et analyse des causes profondes
Les mesures de mesure des défauts logiciels doivent être traitées différemment des défauts matériels. Les défauts matériels se concentrent généralement sur la densité des défauts, comme le nombre de défauts par million de pièces. Cependant, la répartition des défauts logiciels suit le principe de Pareto, avec environ 80 % des défauts graves concentrés dans 20 % des modules. Par conséquent, une mesure plus efficace est la tendance de convergence des défauts au niveau du module-, c'est-à-dire la variation nette des défauts ouverts pour chaque module au fil des itérations. Si un module montre une augmentation nette des défauts ouverts pendant trois itérations consécutives, cela suggère un problème architectural fondamental nécessitant une révision de refactorisation. La profondeur de l’analyse des causes profondes des défauts détermine l’efficacité des actions préventives. Un cadre de classification couramment utilisé classe les causes profondes des défauts logiciels en cinq types : écart de compréhension des exigences, défauts de logique de conception, erreurs d'implémentation de codage, erreurs de gestion de configuration et différences de dépendance environnementale. Les erreurs de gestion de configuration constituent une catégorie unique pour les projets logiciels. Les exemples courants incluent l'utilisation d'une mauvaise version d'une bibliothèque middleware, des paramètres d'options de compilateur incohérents et des correctifs critiques manquants lors de la fusion de branches. Dans un projet, une erreur logique de commande des feux stop a été découverte lors de la dernière série de tests avant la livraison. L'erreur remonte à une fusion de branche trois mois plus tôt, où le développeur avait choisi à tort d'ignorer toutes les modifications apportées au module de commande des feux stop lors de la fusion du code de fonctionnalité de la branche principale. Ce cas suggère que la comparaison des différences après la fusion de succursales devrait devenir une porte obligatoire, avec un personnel désigné chargé d'examiner les demandes de fusion.
IV. Rappel de logiciels et gestion OTA
Avec l’adoption généralisée de la technologie OTA, la méthode de correction des défauts logiciels subit un changement fondamental. Les rappels de logiciels traditionnels nécessitent que les véhicules se rendent dans des centres de service pour le flashage, ce qui est coûteux, prend du temps- et souffre d'une faible conformité des utilisateurs. Les rappels OTA peuvent être effectués directement via push à distance, mais les exigences réglementaires





