Les règles d'or de la programmation

| Patrick Catella | Alexandre Laurent |

Cet article recueille des conseils et les bonnes pratiques à adopter en programmation.

Commentez

- Titre : Les règles d'or de la programmation

- Auteurs : Patrick Catella, Alexandre Laurent

- Parution : 18 décembre 2012

- Mise à jour : 3 mars 2013

- Public visé :

- Licence : Copyright ® 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Efficacité

- III. Fiabilité

- IV. Robustesse

- V. Interface

- VI. Portabilité

- VII. Maintenabilité

- VIII. Travail en commun, versionning et sauvegardes

- IX. Conclusion

- X. Remerciements

I - Introduction

Ce document n'a pas pour but d'être une bible de la meilleure méthode de programmation. Il m'a été inspiré non seulement par les différents stagiaires dont je me suis occupé et par les morceaux de code que j'ai pu voir, postés ici et là, mais aussi par ma propre expérience professionnelle. La question que je me suis souvent posée étant la suivante : comment faire pour écrire le meilleur programme possible ?

Au bout de quelque temps, je me suis aperçu que je ne pourrai pas atteindre ce but : en effet, répondre à cette question implique d'atteindre un absolu, sans tenir aucun compte de notre environnement de travail : comment, par exemple, écrire le meilleur programme possible alors que notre responsable ou notre client vient nous parler tous les jours de délai de livraison ?

J'ai donc modifié cette question en une autre : comment faire pour devenir un meilleur développeur ? Nous sommes tous perfectibles et donc, nous devons nous améliorer.

Quel que soit votre environnement de développement, langage, société dans laquelle vous travaillez, votre programme et vous-même devez répondre aux règles décrites dans cet article.

II - Efficacité

Vous, comme votre programme, devez être efficace. C'est-à-dire arriver à un maximum de résultat pour un minimum d'effort. Pour ceci, non seulement il existe des méthodes de programmation dont vous pouvez vous inspirer mais vous devez toujours garder en tête, à la fois le souci de votre propre efficacité mais aussi celui de votre programme.

Votre propre efficacité commence dès la conception en répondant aux besoins de l'utilisateur et uniquement aux besoins de l'utilisateur : il est inutile de développer une fonction compliquée quand il en veut une simple ou même de développer une fonctionnalité non demandée mais qui vous paraîtrait indispensable. Si vous avez des doutes, vous pouvez toujours lui poser des questions complémentaires.

Ne confondez pas l'efficacité de votre programme avec sa rapidité : il est inutile de mettre en œuvre un algorithme plus compliqué si vous passez plus de temps à l'écrire. Si jamais lors de vos tests vous vous rendez compte qu'il y a un problème de temps de réponse, il sera toujours temps d'envisager une autre manière de faire. En résumé, vous devez être rapide à écrire votre programme quitte à réutiliser des morceaux de code que vous avez utilisés dans un autre programme.

Il s'agit d'écrire le moins de code possible. Votre programme devra être clair et sans redondance de code.

Parmi les méthodes de programmation que vous pouvez utiliser, une d'entre elles me semble obligatoire : il s'agit de découper les tâches à réaliser en tâches de plus en plus petites. Par exemple, pour construire une maison, vous aurez une tâche qui va s'appeler contruire_maison et pour construire cette maison vous en aurez d'autres qui pourraient s'appeler construire_fondations, construire_murs, construire_toiture et enfin remplir_maison. Il devient évident que l'on va continuer à découper chacune de ces quatre tâches par d'autres qui le seront encore à leur tour. Une telle méthode présente l'avantage de ne rien oublier et de laisser un programme clair, sous réserve que vous le commentiez un minimum et que vous utilisiez des noms convenables : clair, précis et concis.

Une autre méthode, importante également surtout si vous avez une grosse application à développer est de la développer par module. Vous pourrez alors sans doute livrer au client un premier module dont il pourra se servir pendant que vous écrirez les modules suivants. Par exemple, il pourra commencer à remplir la base de données pendant que vous travaillerez sur la suite. Ce qui vous permettra d'avoir d'un jeu d'essais plus proche du réel. De plus, un module bien conçu pourra être réutilisé dans d'autres projets.

Pour gagner en efficacité, il devient utile de copier-coller du code. En effet, il se peut que certaines fonctionnalités aient déjà été développées. Si votre code est bien conçu, il suffira juste de copier la fonction ou la classe pour l'intégrer dans votre nouveau projet.
Si c'est un code venant d'Internet, il est extrêmement important de le comprendre avant de l'intégrer. Si vous sautez cette étape, vous allez entraîner des failles de sécurité et de fiabilité dans l'application.

Le copier-coller peut être une bonne pratique pour ne pas réécrire un code. Toutefois, si vous effectuez un copier-coller de votre code dans votre propre projet (création d'un duplicata de code), ceci est une mauvaise pratique. En effet, si ce code contient un bogue, vous allez possiblement oublier de le corriger aux deux endroits. De plus, lors de l'utilisation de la copie, il vous faudra peut-être modifier le nom des variables et certaines peuvent être oubliées, créant ainsi de nouveaux bogues.
Ainsi, à la place d'une copie, il est préférable de créer une fonction et de l'appeler deux fois.

III - Fiabilité

Votre programme doit être fiable, c'est-à-dire contenir un minimum d'erreurs de programmation. Cela signifie que vous devez tester votre programme. Vérifiez que le programme fait bien ce que vous voulez qu'il fasse et ce, pas seulement avec un seul test. En général, le développeur a tendance à tester les valeurs qui l'arrangent, il vous faut donc un jeu d'essais complet à lancer à chaque modification que vous apportez à votre application. De plus, ne laissez pas le programme se planter lamentablement : gérez les erreurs proprement. Si une fonction retourne un code d'erreur ou une exception (pour les langages les supportant), vous devez le prendre en compte. Une fois que vous vous apercevez d'un quelconque problème, réfléchissez à ce qui doit être fait selon la gravité de l'erreur. Si une erreur fatale se produit, sauvegardez les documents de l'utilisateur. Si c'est une erreur bénigne, ne bloquez pas l'application, gérez-la de la manière la plus simple (par exemple, en ignorant les résultats produits lorsqu'une erreur est découverte ou en indiquant un petit message à l'utilisateur) et continuez le travail.

Il vous faut tester votre programme non seulement avec des tests unitaires mais aussi avec des tests d'intégration. Les tests unitaires sont à effectuer à chaque étape importante de l'écriture ou de la modification de votre programme ou module. Les tests d'intégration sont à effectuer à la fin de l'écriture ou de la modification d'un module afin de contrôler qu'il s'intègre bien avec les autres. Le must est d'automatiser ces tests dans la chaîne de développement. Par exemple, on peut mettre en place une machine qui exécutera les tests toutes les nuits en prenant la dernière version du code (grâce à un logiciel de contrôle de version). Comme cela, en arrivant le matin, les développeurs sauront si un problème est apparu et seront alertés au plus tôt. Ainsi, chaque bogue doit avoir son test, afin qu'il ne réapparaisse plus jamais.

Lors de vos tests unitaires vous serez amenés à choisir les valeurs à tester. Il faut toujours en tester plusieurs et les choisir à bon escient : au moins la valeur minimale, la valeur maximale, une valeur hors norme par raison d'anormalité et quelques valeurs convenables qui, dans l'idéal, devront être choisies parmi des valeurs réelles, c'est-à-dire des valeurs en vigueur chez vos utilisateurs.

IV - Robustesse

Votre programme doit être robuste, c'est-à-dire résister aux erreurs de l'utilisateur. Vous devez donc tester chaque zone de saisie au mieux. Par exemple, ne le laissez pas utiliser le 22e élément d'un tableau qui n'en comporte que 20. Dites-le-lui avant. Obligez-le à saisir les zones qui sont réellement obligatoires. D'une manière générale, la programmation défensive est une technique qui donne de bons résultats, car elle vous force à supposer que votre utilisateur va commettre des erreurs. En ce qui concerne vos propres erreurs, des tests unitaires et la programmation par contrat doivent donner des résultats suffisants.

V - Interface

Vous devrez en outre faire un effort particulier au moment de créer votre interface, que ce soit en n-tiers ou non. Votre programme doit faciliter la vie de l'utilisateur, il ne doit pas lui créer des problèmes supplémentaires. Chacune des actions que l'utilisateur doit réaliser doit l'être de manière claire et précise pour lui. S'il se pose trop de questions, il risque de se tromper. Par exemple, s'il met trop de temps pour créer une fiche client, il risque de garder ses dossiers alors qu'un des buts de votre application était peut-être de supprimer ces dossiers pour les remplacer par l'écran. Une autre chose qui va considérablement influer sur le ressenti de l'utilisateur : la documentation que vous lui fournirez. Celle-ci doit être claire et agréable à lire. Elle doit inclure toutes les fonctions de votre application et contenir également tous les messages que votre programme est susceptible d'afficher avec leur signification et éventuellement une codification, car lorsqu'il va avoir un message d'erreur il doit pouvoir se débrouiller seul et ne vous appeler qu'en dernier recours.

VI - Portabilité

Rendre son programme portable est un choix. Toutefois, personne n'est à l'abri du changement, donc quelle que soit la bibliothèque que vous utilisez (multiplate-forme ou pas) n'hésitez pas à prévoir un code architecturé pour faciliter le changement de bibliothèque, si besoin.

Si votre programme doit être portable, n'en faites pas trop. Par exemple, si vous écrivez un site web, il faudra que votre utilisateur puisse l'utiliser avec n'importe quel navigateur et pas seulement avec celui sous lequel vous l'avez écrit et testé. Idem en ce qui concerne les versions Windows : si vous développez sous XP, faites attention que votre programme puisse être utilisé sous les versions suivantes plus exigeantes en ce qui concerne la sécurité. Par contre, il sera sans doute inutile d'assurer une portabilité de Windows vers Linux ou vers les portables et inversement. À quoi donc pourrait servir une géolocalisation de l'utilisateur sur un poste fixe ?

VII - Maintenabilité

Votre programme doit être maintenable, c'est-à-dire non seulement pouvoir être modifié facilement par vous-même dans six mois mais également par quelqu'un d'autre.

Pour ceci, une des toutes premières choses à faire est de mettre en place tout un système de documentation. Documenter implique de commenter vos choix dès la conception dans le dossier d'analyse pour les expliquer jusque dans les moindres fonctions afin que l'on puisse savoir à quoi elles servent. Mais mettez des commentaires utiles : il est inutile d'écrire « incrémentation de i » à côté d'un i++. Utiliser des outils tels que Javadoc ou Doxygen peut vous aider à construire la documentation de votre programme. Il restera à faire celle allant avec le MCD.

Maintenable, cela veut dire aussi : facilement lisible. Vous pouvez utiliser des techniques de nommage comme Camel Case. Cette technique fait que vos variables ressemblent à un dos de chameau du fait de l'alternance de majuscules et de minuscules, comme pour « maSuperbeVariable », d'où son nom. Vous pouvez aussi ajouter un préfixe pour savoir si la variable est une variable membre de la classe (m_) ou encore, un pointeur (p). Dans tous les cas, il faut choisir un nom pour vos variables, fonction, classes, explicite tout en étant court. Vous devez aussi indenter votre programme surtout quand des IDE comme NetBeans le font pour vous.

Une autre manière d'améliorer sa maintenabilité est de pratiquer la refactoristion (refactoring), c'est-à-dire de réécrire le code une fois qu'il respecte au mieux les principes énoncés précédemment. Souvent, un code est écrit dans la rapidité afin de répondre à un besoin et à un délai et celui-ci contiendra donc très certainement des erreurs (il se peut qu'il fonctionne, mais qu'il casse le design de l'application, ou qu'il ne vérifie pas les erreurs retournées par les fonctions, par exemple). La refactorisation permet de réécrire ce ou ces morceaux de code afin de fortifier l'architecture de l'application. Ainsi, vous gagnerez en lisibilité, en fiabilité et en maintenabilité. De plus, comme la refactorisation peut être une opération apportant de nouveaux bogues (car modification du code existant), les tests unitaires automatisés permettront de repérer immédiatement les nouveaux problèmes et de les corriger immédiatement. Ainsi, vous pouvez faire progresser votre application tout en vous assurant de ne pas apporter de problèmes.

Il ne faut pas confondre factorisation et refactorisation. Le premier décrit le fait de créer une fonction afin d'éviter la répétition d'un même code. Le second énonce tout le processus mis en place afin d'améliorer le code, le rendre robuste, lisible, réutilisable, … Il permet entre autres de corriger des erreurs insérées lors de l'écriture de code et de corriger des failles que l'on aurait oubliées. Lors d'une refactorisation, le comportement du programme n'est pas modifié. De plus, lors d'une refactorisation, le code peut être factorisé.

VIII - Travail en commun, versionning et sauvegardes

Vous allez, peut-être, travailler en commun : vous avez besoin de vous assurer que vous n'êtes pas plusieurs à modifier le même code source en même temps.

Vous avez besoin de sauvegarder vos programmes : Il faudra garder plusieurs sauvegardes, au moins une pour les deux dernières versions de votre application voire plus si vous aviez besoin de revenir plus loin encore. En plus d'une sauvegarde à chaque version qui fonctionne, une sauvegarde par jour ou demi-journée est nécessaire au moment où vous développez.

Les outils de versionning sont faits pour ça. Voyez par exemple Subversion, Mercurial, ou Git qui sont des logiciels vous permettant de sauvegarder votre travail sur un serveur distant, mais aussi de garder les informations liées à chaque modification du code et ainsi de pouvoir travailler à plusieurs sur le même projet.

La perte de code n'est pas une fiction. Cela arrive à beaucoup de débutants. C'est pourquoi, même pour un projet personnel, il est conseillé d'utiliser un outil de versionning. Toute entreprise en utilise et maintenant, les universités en installent dans leur parc informatique.

IX - Conclusion

Au cours de cet article, nous avons vu les différentes règles de base que tout programmeur doit suivre dans la réalisation de ses projets. En effet, le tout n'est pas de faire une application qui fonctionne, mais aussi faire en sorte que celle-ci puisse être modifiée aisément par vous ou votre successeur tout en étant le plus efficace. C'est en suivant ces règles simples que vous deviendrez un meilleur programmeur.

Toutefois, l'article s'est limité à parler de la programmation de façon générique. Chaque langage possédera des règles spécifiques qui lui seront propres et qui ne pouvaient donc pas être regroupées ici. Sachez que vous apprendrez ces règles en programmant.

X - Remerciements

Je souhaite remercier 3DArchi et fafabzh6. Finalement, je remercie aussi f-leb et zoom61 pour leurs corrections.