Refactorisation de Code avec les 10 Règles de la NASA

Vous pensez pouvoir gérer la complexité comme si vous aviez affaire à un simple xénomorphe ? Réfléchissez encore. Les Règles du Pouvoir de Dix de la NASA sont votre armure dans l'espace sombre du code critique. Ces règles, issues du JPL par Gerard J. Holzmann, sont votre bouclier dans les environnements où chaque ligne de code peut être une question de vie ou de mort.
J'ai affronté le chaos des calculs financiers: 'European interest rate option' & 'currency option' en appliquant ces règles. Voici comment elles ont transformé le code : 

1. Option de Taux d’Intérêt Européen (C++ conforme aux règles de la NASA)

Le calcul du profit ou de la perte d’une option de taux d'intérêt suit l’équation suivante :


P=Principal×(Taux reˊelTaux d’exercice)×(DureˊeJours dans l’anneˊe)




'''cpp

#include <iostream> #include <cassert> // Règle 8 : Utilisation de constantes au lieu de macros constexpr double DAYS_IN_YEAR = 360.0; // Règle 4 : Vérification des entrées avec des assertions double calculateProfitOrLoss(double principal, double actualRate, double strikeRate, double duration) { assert(principal > 0); assert(actualRate >= 0); assert(strikeRate >= 0); assert(duration > 0); // Règle 5 : Minimiser la portée des variables const double profitOrLoss = principal * (actualRate - strikeRate) * (duration / DAYS_IN_YEAR); return profitOrLoss; } int main() { // Règle 2 : Pas d’allocation dynamique, utilisation de variables statiques const double principal = 50000000; // 50 millions d'euros const double actualRate = 0.05; // Taux réel 5% const double strikeRate = 0.04; // Taux d'exercice 4% const double duration = 180; // Durée du contrat (180 jours) // Règle 6 : Vérification du retour de la fonction const double profitOrLoss = calculateProfitOrLoss(principal, actualRate, strikeRate, duration); std::cout << "Profit ou perte de l'option de taux d'intérêt : " << profitOrLoss << " Euros" << std::endl; return 0; }
'''
Respect des règles NASA :
- Pas de mémoire dynamique (Règle 1)
Portée des variables minimisée (Règle 5)
Assertions pour valider les entrées (Règle 4)
Constantes utilisées au lieu de macros (Règle 8)
Pas de récursivité, complexité maîtrisée (Règles 3 et 9)

2. Option de Change (C++ conforme aux règles de la NASA)

Le profit net d’une option de change est donné par :


P=Principal×(Prix finalPrix initialPrime)


'''cpp

#include <iostream> #include <cassert> // Règle 8 : Utilisation de constantes au lieu de macros constexpr double MINIMUM_EXCHANGE_RATE = 0.01; // Valeur minimale réaliste // Règle 4 : Vérification stricte des entrées double calculateNetProfit(double principal, double endingStrikePrice, double beginningStrikePrice, double premiumPaid) { assert(principal > 0); assert(endingStrikePrice >= MINIMUM_EXCHANGE_RATE); assert(beginningStrikePrice >= MINIMUM_EXCHANGE_RATE); assert(premiumPaid >= 0); // Règle 5 : Minimiser la portée des variables const double netProfit = principal * (endingStrikePrice - beginningStrikePrice - premiumPaid); return netProfit; } int main() { // Règle 2 : Pas de mémoire dynamique, utilisation de variables statiques const double principal = 100000; // Montant en USD const double endingStrikePrice = 1.3987; // Prix final (EUR/USD) const double beginningStrikePrice = 1.3568; // Prix initial (EUR/USD) const double premiumPaid = 0.0156; // Prime payée (en USD par Euro) // Règle 6 : Vérification du retour de la fonction const double netProfit = calculateNetProfit(principal, endingStrikePrice, beginningStrikePrice, premiumPaid); std::cout << "Profit net de l'option de change : " << netProfit << " USD" << std::endl; return 0; }
'''


•  Respect des règles NASA :

Validation stricte des entrées avec assert (Règle 4)
Utilisation de constexpr pour éviter les macros (Règle 8)
Portée des variables limitée au strict nécessaire (Règle 5)
Aucune allocation dynamique (new ou delete interdit) (Règle 1)
Code déterministe et testable (Règle 10)

En appliquant les règles de codage strictes de la NASA, nous avons obtenu des implémentations fiables, robustes et maintenables des options financières. Ces principes ne sont pas uniquement pertinents pour les logiciels spatiaux, mais aussi pour les applications critiques en financeaéronautique, et systèmes embarqués.

•  Points-clés de cette méthodologie :

-  Contrôle strict des erreurs: des assertions sur toutes les entrées.
-  Suppression des allocations dynamiques: garantir la stabilité mémoire.
-  Utilisation des constexpr: éviter les erreurs liées aux macros.
-  Portée des variables réduite: limiter les effets de bord.
-  Structures de contrôle explicites: opter pour lisibilité maximale.

Ces techniques garantissent une 'sécurité maximale et un contrôle précis des erreurs', assurant une 'maintenance réduite et prévisible' du code.


3.  Perceptions sur les Règles de la NASA

La NASA interdit la récursivité dans son code. Pourquoi ? Parce que la récursivité peut facilement faire sauter la pile, ce qui est un risque inacceptable dans les systèmes critiques. Vous devez comprendre la récursivité juste assez pour l'aplatir et la transformer en une version itérative. C'est une pratique courante dans les systèmes embarqués critiques. 


Les systèmes embarqués et les applications à durée limitée qui nécessitent un système d'exploitation en temps réel (RTOS) fonctionnent généralement sur du code C/C++. Ce choix est dû à la nécessité d'un contrôle précis de la mémoire, du timing et des interactions matérielles. Donc, ce n'est pas une surprise pour moi si la NASA déteste la récursivité.

Sinon, la vérification manuelle des fuites de mémoire et des problèmes de concurrence au lieu de l'automatisation construit le caractère et n'est certainement pas une perte de temps. 


De plus, la NASA interdit l'allocation dynamique de mémoire (sauf dans un segment de code d'initialisation de programme), les boucles non limitées et une série d'autres modèles de programmation très courants. Ces restrictions visent à garantir que le code est prévisible, fiable et facile à déboguer. C'est fou, non ? Mais quand vous travaillez sur des systèmes où une erreur peut coûter des vies ou des milliards de francs, ces règles deviennent indispensables.  


Le problème fondamental avec tous les styles de code obligatoires (même les miens) est qu’aucun d’entre eux n’est basé sur des données réelles. C’est toute la sagesse “tribale” qui dépend d’un mélange d’expérience personnelle, de préférence personnelle et de tous les outils dont vous disposez. 


J’aimerais que nous ayons un mécanisme formel pour juger ce genre de règles de codage. Ensuite, nous pourrions, personnellement l’appliquer à la conception du langage pour déterminer si certaines langues ont des taux de défauts plus faibles ou une productivité plus élevée. 

Dans l’état actuel des choses, je n’ai aucune raison de croire que les directives de codage JPL produisent un meilleur ensemble de code ou qu’elles peuvent évoluer vers des problèmes plus complexes (c’est-à-dire que si des directives de codage décentes produisent des résultats similaires uniquement en raison de l’espace problématique et des contraintes. 

4.  Gestion de la Mémoire dans les Systèmes Critiques


Le code affectant une mission spatiale n’a qu’une seule chance de bien faire les choses dans de nombreux cas. En général, la gestion de la mémoire dans ces systèmes est une affaire extrêmement sérieuse. Pensez à toutes les façons dont la gestion manuelle de la mémoire en C pourrait endommager la fiabilité des programmes que vous avez écrits. 

En outre, de nombreuses règles sont créées pour faciliter la lecture du code source, tant pour les humains que pour les machines. Gerard Holzmann voulait interdire toute déclaration de pointeurs, sauf à l’initialisation statique: 

'Ne pas autoriser l’indirection du pointeur rendrait la tâche de certaines techniques d’analyse automatisée beaucoup, beaucoup plus simple à réaliser. L’ajout d’une indirection de pointeur peut vraiment confondre les choses parfois'. 

Ces règles strictes visent à garantir que le code est aussi simple et prévisible que possible, ce qui est essentiel pour les systèmes où une erreur peut avoir des conséquences catastrophiques. 

5. Rapports idiomatiques 


D'un point de vue C++, la récursivité n'est pas si folle. Elle est essentiellement une itération sur la pile. La différence est que vous pouvez soit l'implémenter manuellement, soit laisser le compilateur le faire pour vous, ce qui peut entraîner un débordement de pile, si vous comptez trop sur le compilateur. Vous pouvez allouer manuellement la mémoire de la pile pour effectuer les itérations vous-même, ou laisser chaque appel récursif occuper de l'espace sur la pile d'appels. Le problème est que cette pile est partagée avec tout le programme et a un espace limité. 


Que se passe-t-il si vous devez travailler avec un grand ensemble de données ? C'est là que vous allouez sur le tas, une zone de mémoire beaucoup plus grande qui n'a pas besoin d'être utilisée pour les éléments essentiels du programme. Tout dépend de votre perspective! Pour certains, ces règles strictes sont souvent le symptôme de ce qui se passe lorsqu'une bureaucratie est chargée de gérer des artistes, des règles stupides et rigides pour vos projets. 

Il est à noter que C++ gaspille +34 % d'énergie par rapport à C dans certains repères. Pour d’autres, C++ gaspille des cycles en faisant ou en accédant à des allocations de mémoire d'objet unique.. 


Dans cet univers où la moindre erreur peut être fatale, la simplicité est votre alliée. Apprenez de la NASA, ou restez à jamais vulnérable aux défaillances de votre propre création. 


Qu'en pensez-vous ? Ces règles sont-elles utiles ? 


P.s. 'Sauvez notre planète, utilisez C ou C++'.

Comments

Popular posts from this blog

Les expressions régulières gourmandes & non gourmandes en C++

MANIFESTO DU DÉVELOPPEUR/PROGRAMMEUR TOGOLAIS