Bonnes pratiques de programmation — Algorithmique (2024)

Lorsque l'on programme, on passe un certaintemps à écrire du code, mais on passe beaucoupplus de temps à lire du codeque soi, ou d'autres, ont écrit.

On peut facilement faire l'analogie entre l'écrituredu code et l'écriture d'un texte. Lorsque le texteest mal écrit, qu'il contient des fautes d'orthographe,que les phrases sont mal structurées et que les idées nesont pas organisées, ce texte est très difficile à lire etdonc à comprendre. Il en va de même pour le code: un codebrouillon est très difficile et fatiguant à comprendre... deplus, les bugs s'y cachent beaucoup plus facilement.

Observez par exemple le code ci-dessous:

def k(i: int) -> int: # rxkfghh = rxkfgh2 sauf si i = 1 rxkfghh="gh" if i==1: p=7 a=p+2 rxkfgh=1 rxkfghh="temporaire" print(rxkfghh, rxkfgh) else: rxkfghh2="tempoaussi" rxkfgh = i*k(i-1) print(rxkfghh, rxkfgh) return rxkfgh

Reconnaissez-vous cet algorithme? C'est celuide factorielle. Ce serait plus simple àcomprendre si l'algorithme était bien écrit non?

Il est donc très important de respecter certainesbonnes pratiques de programmation(qui s'appliquentnaturellement à la rédaction d'algorithmes) pourrendre le plus agréable possible la lecture de code.

Ce chapitre n'a pas vocation à vous enseigner toutesles bonnes pratiques de programmation... vous aurez uncous à ce sujet au second semestre. Néanmoins, ilprésente quelques bonnes habitudes que vousdevez prendre dès le début.

Interface vs. implémentation d'un algorithme

Dans la première partie de ce cours, nous avons parléà plusieurs reprises de "contrat" ou "spécification formelle".

Le contrat caractérise l'interface d'un algorithme, c'est-à-direqu'il explique le plus clairement possible ce que l'algorithmeest capable de produire comme sorties étant donné ce qu'on luifournit en entrée. Les pré-conditions permettent de préciser sousquelles conditions l'algorithme sera capable de fonctionner et lespost-conditions nous renseignent sur ce que l'on peut s'attendreà obtenir comme résultats.

Par conséquent, lorsqu'on lit un contrat, i.e. que l'on consultel'interface d'un algorithme, on est renseigné sur ce à quoi on peuts'attendre, ainsi que sur les limites de l'algorithme que l'on vautiliser, sans pour autant avoir besoin de comprendre commentl'algorithme est implémenté.Il nous appartient de composer avec ces informations.Par exemple, quand vous utilisez range(0,4) en Python, voussavez que vous allez obtenir une liste de 4 éléments de 0 à 3,mais vous ne savez pas comment Python procède pour créer cetteliste.

Le contrat permet donc de savoir très exactement ce que l'algorithmeest capable de faire, mais il ne dit rien sur comment l'algorithmeva s'y prendre pour résoudre le problème.

Le reste de ce chapitre porte sur les bonnes pratiquesde programmation pour coder des algorithmes, donc sur lecomment.

Qu'est-ce qui caractérise un code "bien écrit"?

Un algorithme, ou code "bien écrit" doit avoir lespropriétés suivantes:

  • Être facile à lire, pas soi-même mais aussi par les autres.

  • Avoir une organisation logique et évidente.

  • Être explicite, montrer clairement les intentions du développeur.

  • Être soigné et robuste au temps qui passe.

Nous allons regarder un peu plus en détails chacune de cescaractéristiques.

La code doit être facile à lire

Pour que le code soit facile à lire, il faut d'une partqu'il soit bien structuré et bien présenté, et d'autre part,que les noms des variables et des fonctions soient choisisavec soin.

Pour ce qui est de la structure et de la présentation, Pythonnous aide beaucoup car le langage impose beaucoup de chosesqui nous "forcent" à bien présenter notre code. Par exemple,les blocs d'instructions du même niveau doivent être précédésdu même nombre d'espaces, ce qui nous conduit naturellement àbien indenter notre code.

Dans d'autres langages, plus de libertés de présentation sontoffertes au développeur, par conséquent, il convient de seforcer à respecter des conventions pour écrire le code le pluspropre possible.

Par exemple, regardez le code Java ci-dessous. Il estévident que le manque d'indentation ne facilite pas lalecture et la compréhension du code, n'est-ce pas?

int i,j,k, m, n, o = 0;n = 9; o=13;int [][] p = new int [n][o];for(i=0;i<n;i++){p[i][0] = i;m = i;for(j=1;j<o;j++){for(k=0;k<j-1;k++){m = m + p[i][k];}p[i][j] = m;}}System.out.println("----");for(i=0;i<o;i++){for(j=0;j<n;j++){System.out.print("|" + p[j][i]);}System.out.println("|");}

Pour ce qui est du choix des noms des choses(variableset fonctions), nous en reparlerons un peu plus loin dans cechapitre.

Le code doit avoir une organisation logique et évidente

Ce point est plus délicat car nous avons souvent des solutionsdifférentes pour résoudre le même problème. Il est donc normalqu'un code qui semble logique à quelqu'un semble "tordu" à sonvoisin.

Étant conscient de cela, il faut vous efforcer de trouver dessolutions logiques aux problèmes que vous devez résoudre etd'éviter d'emprunter des chemins plus compliqués qui ne feraientque semer la confusion.

Par exemple, si l'on vous demande d'afficher tous les nombresde 1 à 10, il suffit de faire une boucle qui fait évoluer uncompteur entre 1 et 10 et qui affiche, à chaque tour, la valeurde ce compteur. La solution qui consisterait à faire une bouclequi fait évoluer un compteur de 9 à 0 et qui afficherait àchaque tour le résultat de 10 - compteur fonctionne aussimais est à proscrire car elle est "tordue".

Le code doit être explicite

Lorsque l'on écrit des algorithmes ou que l'on développe desprogrammes, on est parfois tenté de prendre des raccourciscar "on sait" que telle ou telle méthode permet de faire telleou telle chose bien pratique.

Il n'est pas interdit de prendre ces raccourcis, mais il fauttoujours prendre le soin d'expliquer, au moins à travers descommentaires, pourquoi on fait cela. C'est important à la foispour permettre aux autres de comprendre pourquoi votre solutionest astucieuse... mais aussi pour vous, au cas où vous ne voussouveniez plus de "pourquoi vous avez fait ça".

Par exemple, si vous devez afficher une matrice de dimensionsMxM, la procédure usuelle est de faire deux boucles imbriquéespermettant d'afficher chacun des éléments de la matrice. Or,si vous savez que votre matrice est triangulaire, vous allezprobablement vouloir optimiser votre double boucle d'affichage.C'est naturellement une bonne idée... mais pensez bien à rappelerdans le commentaire pourquoi vous procédez de la sorte.

Le code doit être soigné et robuste au temps qui passe

Lorsque l'on écrit du code, on a la fâcheuse tendance à s'arrêterdès que celui-ci fonctionne. C'est un tort! Le code doit êtreentretenu. Cela signifie qu'il faut relire son code après l'avoirterminé, vérifié que l'on a bien supprimé les éléments obsolètes,vérifier que les commentaires sont à jour et cohérents avec lecode conservé, etc.

Cette opération de "maintenance" du code est cruciale, mais elle estpourtant souvent négligée par beaucoup, ce qui peut poser des problèmes,notamment lorsque vous rencontrez un bug.

L'exemple le plus classique est celui-ci: vous implémentez une méthodetri qui permet de trier les éléments d'un tableau. Vous n'êtespas satisfait du comportement de cette méthode lorsque vous l'utilisezdepuis votre programme principal. Vous implémentez doncune autre méthode test qui utilise une autre stratégie pour trierles éléments du tableau. Cette méthode marche mieux. Vous l'utilisezdonc dans votre programme principal. Votre programme fonctionne et vouspassez à autre chose, sans penser à intégrer vos modificationsproprement dans votre programme.Quelques jours plus tard, vous reprenez votrecode et vous observez un bug. Vous pensez que cela provient du tri dutableau. Vous allez donc observer ce qui se passe dans tri. Aprèsquelques heures de recherche, vous êtes furieux contre vous-même carvous réalisé enfin que la méthode tri n'est plus utilisée depuislongtemps dans votre code...

Croyez-le, les problèmes de ce type arrivent beaucoup plus souventqu'on ne le pense... surtout quand on cherche à faire vite.

Avant de passer à la suite, un autre exemple de code. Voyez-vous unproblème?

#la boucle s'arrête si i est négatif ou si continuer prend la valeur falsei = 0j = 4while continuer: print("mon code marche") #i += 1 j += 1 if j > 10: continuer = False

C'est bien joli tout ça, mais coder proprement ça prend du temps!

C'est faux! Il ne faut pas confondre vitesse et précipitation.

On a souvent tendance à penser que l'on perd énormément de tempsà soigner son code, à le structurer correctement, à le réorganiseret à le documenter, mais c'est faux. Au contraire, on gagne du tempsà faire tout cela.

Voici quelques explications pour vous en convaincre:

  • Si vous adoptez les bonnes pratiques dès le début,vous faites déjà 50% du travail.

  • Si le code est bien écrit, il est plus facile, et doncplus rapide à relire, et n'oubliez pas que vous passezplus de temps à lire votre code qu'à l'écrire... donc quandvotre code est propre, vous vous faites gagner du temps.

  • Si le code est logique et bien structuré, il sera plus facilede retrouver les bugs qu'il contient, et donc de l'améliorer..

Ce sont donc autant de raisons qui devraient vous convaincre qu'ilest important d'être organisé, clair, méthodique et rigoureux quandvous développez.

De l'importance des commentaires

Les commentaires sont essentiels pour "éclairer" le code.Un commentaire est un texte qui est ignoré par l'ordinateurlorsqu'il exécute le programme, mais qui peut être lu par ledéveloppeur lorsqu'il lit le programme.

En Python, une ligne qui débute par le signe # est uncommentaire. On peut aussi faire des blocs de commentaires,sur plusieurs lignes, en utilisant les triples guillemets.

Bien que les commentaires soient essentiels, il ne faut pas enabuser.

Un bon commentaire peut:

  • Faciliter la lecture du code,

  • Apporter une indication sur un choix de conception,

  • Expliquer une motivation qui ne serait pas évidente(comme dans l'exemple de la matrice triangulaire vu plushaut)

  • Donner un exemple pour permettre de mieux comprendrece que fait le code.

Quelques exemples de mauvais commentaires:

  • Un commentaire qui décrit un morceau de code qui n'existe plus,

  • Un commentaire qui explique une évidence,

  • Un commentaire sur plusieurs lignes pour expliquer une chose simple.

  • Un commentaire sur l'historique des modifications d'un fichier.C'est parfois utile, mais dans la plupart des cas, il vaut mieuxconfier cette tâche à votre gestionnaire de versions qui fera letravail pour vous.

Vous trouverez ci-dessous quelques exemples de mauvaiscommentaires:

i = 0 #initialisation de la variable i à 0i = i + 1 # incrémentation de la variable i# Additionne a et b et stocke le résultat dans cc = a + b# Ci-dessous une double boucle pour afficher un tableaufor i in range(10): print("Valeur ", i)# fin du for# Et maintenant, on va s'occuper de retourner la valeur de i# Pour cela, on utilise le mot clé return# Et on passe ensuite la valeur de ireturn i

Comme vous le voyez dans l'exemple ci-dessus, il n'est pasjudicieux d'utiliser un commentaire pour signaler la fin d'unbloc d'instructions. En général, si vous avez besoin de cetype de commentaire, c'est que votre code est déjà trop long.Dans ce cas, demandez-vous si vous ne pouvez pas découper votrecode en fragments plus simples.

Attention: les commentaires ne doivent pas pallier un manquede clarté du code. Si vous avez besoin de commentaires pour cela,c'est probablement que vous pouvez améliorer votre code pour lerendre plus lisible. Essayez donc de le refactorer, c'est-à-direde le ré-écrire, au moins partiellement, en l'améliorant.

Comme nous l'avons dit plus haut, les commentaires, toutcomme le code, doivent être maintenus, c'est-à-dire qu'ils doiventévoluer avec le code, et disparaître si le code disparaît. Parconséquent, il faut veiller au bon dosage de vos commentaires,de sorte à ne pas alourdir inutilement votre travail de maintenance.

Enfin, une bonne pratique est d'utiliser des outils tels quedoctest qui permettent d'écrire des petit* tests pour vos fonctionstout en les documentant. Les avantages de cette pratique sont d'unepart que cela vous "force" à tester votre code, et qu'il permet enmême temps d'en avoir une documentation "par l'exemple" qui seraforcément cohérente avec le code et à jour(sinon, les tests nefonctionneraient pas). Pour en savoir plus, n'hésitez pas à consulterla documentation de doctest pour Python,https://docs.python.org/3.5/library/doctest.html.

Comment nommer les choses?

Les noms que vous choisissez pour vos variables et vos fonctionsvont grandement contribuer à la lisibilité de votre code.

Par exemple, vous conviendrez que le bloc de code suivant n'est pas trèslisible tandis que celui d'après, qui fait exactement la même chose, est plusclair.

xretyers = 4eijfzeipfjzpeij = 1xretyers = eijfzeipfjzpeij + xretyers
x = 4x += 1

La première règle est donc de choisir des noms de variables prononçables et faciles à retenir.

Vous devez choisir des noms de variables explicites pour vous mais aussi pour lesautres.

Par exemple, a est bien moins explicite que adresseClient. De même, lf estmoins explicite que largeurFenetre. Pensez également que vous serez probablementamenés à chercher vos variables dans votre code avec un outil de recherche. À votreavis, combien d'occurrences de a allez vous trouver? Et combien d'occurrences deadresseClient?

Évitez également de choisir des noms de variables qui induisent un contre-sense.Par exemple, si vous écrivez matrice=8, on pourrait penser que la variable estune matrice, or, il s'agit clairement d'un entier.Au moment de l'affectation, il est facile de se rendre compte du type de la variable,mais maintenant, imaginez que vous rencontriez, au beau milieu du code, la ligne suivante:

matrice = matrice * 4

Comment allez vous interpréter cette instruction?

Évitez également les noms de variable qui n'ont pas de sens, comme plop,surtout si vous en utilisez plusieurs dans la même portion de code. Vousrisquez de vous perdre dans les noms et donc d'introduire inutilement des bugsdans votre code.

Ne trichez pas non plus quand vous choisissez vos noms de variables.Dans la plupart des langages de programmation, certains mots sont "réservés"car ce sont des instructions du langage. Par exemple, en Python, on ne peutpas nommer une variable if ou list car ce sont des mots réservésdu langage. Si vous pensez avoir besoin de ces mots pour nommer vos variables,ne trichez pas en écrivant iff ou llist, vous risqueriez de vous perdredans vos propres astuces.

La plupart des langages imposent des règles pour le choix des noms de variables.Par exemple, en Python, un nom de variable ne peut pas commencer par un chiffre(il y a d'autres règles).En plus de ces règles imposées par les langages, essayezde ne pas utiliser des caractères qui pourraient porter à confusion. En particulier,les caractères o 0 O l i et 1 peuvent se ressembler fortement, voire êtreidentiques en fonction de la police de caractères utilisée pour l'affichage à l'écran.

Enfin, essayez d'être cohérents lorsque vous choisissez vos noms de variables.Par exemple, si vous décidez d'utiliser le français pour nommer vos variables,utilisez le français tout du long, n'alternez pas avec l'anglais. longueurPathou lenghtChemin sont des noms pour le moins curieux!

À propos des environnements de développement

Vous avez à votre disposition des environnements de développement.Pensez à les utiliser et apprenez à exploiter leurs nombreuses possibilités.

La plupart de ces environnements vous offrent des outils de refactoring quivous permettent de réorganiser votre code facilement tout en garantissant unecertaine cohérence. Par exemple, ils vous permettent de renommer une variablepartout dans le code. C'est l'occasion de changer tous vos plop par desnoms plus significatifs.

En général, ces outils vous permettent également de vérifier que votre codeest correctement indenté, et qu'il respecte des conventions de programmationpréétablies et matérialisées par des règles. Vous devez apprendre à lesutiliser, cela vous fera gagner beaucoup de temps.

Ces outils vous offrent également des fonctionnalités d'auto-complétion(c'est-à-dire qu'ils complètent automatiquement le texte que vous êtes en train de taper).Ce sont des fonctionnalités très pratiques qu'il faut égalementapprendre à maîtriser. Grâce à ces fonctionnalités, vous n'avez plusd'excuses: inutile de choisir des noms de variables courts(type a b c)sous prétexte que c'est plus rapide à taper...

Référence

La plupart des idées de ce cours proviennent de l’ouvrage formidable "Coder proprement". Robert C. Martin. Pearson Education France, 2009.

Bonnes pratiques de programmation — Algorithmique (2024)
Top Articles
Latest Posts
Article information

Author: Msgr. Benton Quitzon

Last Updated:

Views: 6476

Rating: 4.2 / 5 (43 voted)

Reviews: 90% of readers found this page helpful

Author information

Name: Msgr. Benton Quitzon

Birthday: 2001-08-13

Address: 96487 Kris Cliff, Teresiafurt, WI 95201

Phone: +9418513585781

Job: Senior Designer

Hobby: Calligraphy, Rowing, Vacation, Geocaching, Web surfing, Electronics, Electronics

Introduction: My name is Msgr. Benton Quitzon, I am a comfortable, charming, thankful, happy, adventurous, handsome, precious person who loves writing and wants to share my knowledge and understanding with you.