Diego Mariani, évangeliste PHP pour le compte de Trivago, a proposé quelques points clés pour adopter une approche de programmation défensive.
Ne faites jamais confiance aux données entrées par l'utilisateur :
Supposez toujours que vous allez recevoir quelque chose d'inattendu. Ce devrait être votre approche en tant que programmeur défensif : vous méfier des données entrées par des utilisateurs, ou en général de toutes données qui entrent dans dans votre système. Il faut donc essayer d'être aussi strict que possible. Assurez-vous que vos valeurs d'entrée correspondent à vos attentes. Autrement vous pourrez finir avec des erreurs sur la validité de vos valeurs (exemple valeur négative pour une durée).
Il peut être plus utile et simple de faire des listes blanches que des listes noires par exemple pour valider des extensions d’image : ne recherchez pas les types invalides, mais recherchez plutôt les types valides et excluez le reste. Vous pouvez également vous servir de bibliothèques open source de validation.
Utilisez une abstraction de base de données :
La première des 10 vulnérabilités de sécurité figurant dans la liste d'OWASP (Open Web Application Security Project, un organisme à but non lucratif voué à fournir des informations impartiales et pratiques sur la sécurité des applications) est l’injection. Cela signifie qu’il y a encore beaucoup de personnes qui ne se servent pas, ou se servent mal, d'outils sécurisés pour faire des requêtes sur leurs bases de données. Il serait préférable d’utiliser des packages et des bibliothèques pour faire de l’abstraction de données. En PHP par exemple il y a la PDO (Php Data Object) qui est une couche d'abstraction des fonctions d'accès aux bases de données.
Ne réinventez pas la roue :
« Vous ne vous servez pas d’un framework (ou d’un micro-framework) ? Eh bien !!! Vous devez aimer faire du travail supplémentaire sans aucune raison, félicitations ! ». Il ne s'agit pas seulement de framework, mais de nouvelles fonctionnalités que vous voulez déployer et que vous pouvez facilement prendre dans des paquets testés et approuvés par des milliers de développeurs plutôt que de commencer à élaborer quelque chose par vous-même. L’une des raisons principales qui devraient vous motiver à aller dans ce sens est de créer quelque chose qui n’existe pas encore ou alors qui existe mais ne correspond pas à vos besoins (mauvaises performances, fonctionnalités manquantes, etc.).
Diego Mariani
Ne faites pas confiance aux développeurs :
La programmation défensive peut être liée à la notion de conduite défensive dans laquelle nous supposons que tout le monde autour de nous peut potentiellement et probablement faire des erreurs. Nous devons donc faire attention aux comportements des autres. Le même concept s'applique à la programmation défensive où nous, en tant que développeurs, ne devons pas faire confiance au code des autres développeurs. Nous ne devons pas faire confiance au nôtre non plus.
À ce propos, dans son blog nommé Building Real Software, Jim Bird, directeur de technologie chez BIDS Trading, évoquait les Code Reviews comme étant l’une des clés pour obtenir de meilleurs logiciels. le but étant de relire le code pour repérer les erreurs à un stade précoce. Toutefois, il a rappelé que les reviews coûtent quand même cher et qu’il ne faut pas faire perdre le temps des reviewers à chercher des problèmes futiles.
Pour Mariani, dans les grands projets où de nombreuses personnes sont impliquées, nous pouvons avoir de nombreuses façons d'écrire et d'organiser le code. Cela peut également conduire à la confusion et apporter encore plus de bogues.
Écrire un code SOLID (un acronyme représentant cinq principes de bases pour la programmation orientée objet) :
SOLID :
- S : principe de responsabilité unique (Single Responsibility Principle) ; une classe doit avoir une et une seule responsabilité
- O : ouvert/fermé (open/close principle) ; une classe doit être ouverte à l'extension, mais fermée à la modification
- L : substitution de Liskov (Liskov substitution Principle) ; une instance de type T doit pouvoir être remplacée par une instance de type G, tel que G sous-type de T, sans que cela ne modifie la cohérence du programme
- I : ségrégation des interfaces (Interface segregation principle) ; préférer plusieurs interfaces spécifiques pour chaque client plutôt qu'une seule interface générale
- D : Inversion des dépendances (Dependency Inversion Principle) ; il faut dépendre des abstractions, pas des implémentations
« Il s’agit de la partie difficile pour un programmeur défensif : l’écriture d’un code qui ne soit pas merdique. C’est une chose que beaucoup de gens savent, beaucoup de gens en parlent mais peu sont ceux qui se soucient vraiment ou mettent suffisamment d’attention et d’effort dans l’écriture d’un code SOLID ».
Voici un mauvais exemple à ne pas suivre : oublier d’initialiser des propriétés :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php class BankAccount { protected $currency = null; public function setCurrency($currency) { ... } public function payTo(Account $to, $amount) { // sorry for this silly example $this->transaction->process($to, $amount, $this->currency); } } // I forgot to call $bankAccount->setCurrency('GBP'); $bankAccount->payTo($joe, 100); |
Plusieurs problèmes peuvent être détectés pour un programme qui n’est pas consistant. Cela peut conduire ou être manifesté par exemple par :
- un temps de compilation anormalement long (qui peut être la résultante d’une non utilisation de bibliothèque, de technique d’accélération, etc.) ;
- des fichiers sources inclus dans un projet mais qui ne sont pas utilisés ;
- la mémoire dynamique qui n’est pas libérée ;
- de nombreux avertissements lors de la compilation (qui peuvent cacher un bogue).
Écrire des tests
Avons-nous besoin de le rappeler ? Mariani estime qu’écrire des tests unitaire va non seulement vous aider à tester des modules, mais également de vérifier la façon dont vous avez structuré vos objets.
Source : billet Diego Mariani, une définition de la programmation défensive
Et vous ?
Quels sont, selon vous, les points clés de la programmation défensive ?
Avec quel type de projet vous semble-t-elle le plus adaptée ?
Appliquez-vous cette philosophie ? Pour quelles raisons ?
Voir aussi
Que faut-il faire pour avoir de meilleurs logiciels ? Selon un développeur senior, il faut miser sur les techniques d'ingénierie du génie logiciel
Comprendre PDO