Algorithmie – Bonnes pratiques Javascript

Bonnes pratiques pour bien organiser le code de ses premiers algorithmes en Javascript.

En algorithmie, et en programmation d’une manière générale, adopter de bonnes pratiques est essentiel pour concevoir des algorithmes clairs, efficaces et faciles à comprendre. Cela facilite non seulement la lecture et la maintenance du code mais également la collaboration avec d’autres membres de son équipe.

Si tu as déjà beaucoup codé, cette liste te paraitra peut être « évidente » ou « triviale », mais il y a sans doute quelques éléments à découvrir et n’hésite pas à la voir comme une check list à garder en tête pendant que tu codes 😉

On alternera à chaque fois un bout de code et les explications qui vont avec (cet article étant écrit juste après les JO de Paris 2024, on va utiliser le thème du sport dans les exemples).

Voici donc 9 bonnes pratiques en Javascript :

  1. Utiliser des noms de variables clairs et significatifs
  2. Utiliser correctement var, let et const
  3. Utiliser la bonne boucle
  4. Eviter les else inutiles
  5. Ecrire des fonctions pour réutiliser son code
  6. Commenter son code
  7. Diviser les problèmes en sous problèmes
  8. Tester l’algorithme avec différents cas
  9. Ce n’est pas un concours du code le + court
  10. Bonus : autres langages

Noms de variables clairs et significatifs en javascript

// Mauvais exemple
let a = 90;
let b = 45;
let c = a - b;

// Bon exemple
const totalMatchTime = 90;
const halfTimeDuration = 15;
const effectivePlayTime = totalMatchTime - halfTimeDuration;

Explications :

En utilisant des noms de variables explicites, ton code devient plus lisible et facile à comprendre. Dans le bon exemple, les noms totalMatchTime, halfTimeDuration et effectivePlayTime décrivent clairement leur rôle, ce qui facilite la compréhension du code pour toi et pour les autres.

Il n’y a ni limite ni besoin d’abréviation lorsqu’on nomme une variable, une fonction, une classe, une méthode, etc.

L’utilisation de var, const et let en javascript

// Mauvais exemple (utilisation de var)
function afficherJoueursVar() {
    for (var i = 0; i < 11; i++) {
        var joueur = "Joueur " + i;
        console.log(joueur + " est sur le terrain.");
    }
    console.log("Dernier joueur traité : " + joueur); // Fonctionne, mais peut causer des problèmes
}

// Bon exemple (utilisation de let et const)
function afficherJoueursLetConst() {
    for (let i = 0; i < 11; i++) {
        const joueur = "Joueur " + i;
        console.log(joueur + " est sur le terrain.");
    }
    console.log("Traitement terminé."); // 'joueur' n'est pas accessible ici, évitant les erreurs
}

afficherJoueursVar();
afficherJoueursLetConst();

Explications :

En Javascript, il est essentiel de choisir le bon mot-clé pour déclarer tes variables. Utiliser var peut entraîner des problèmes de portée, car les variables déclarées avec var sont accessibles en dehors du bloc où elles ont été définies. Dans le mauvais exemple, la variable joueur reste accessible après la boucle for, ce qui peut causer des comportements inattendus si le même nom de variable est utilisé ailleurs.

En revanche, let et const limitent la portée des variables au bloc dans lequel elles sont déclarées.

Utilise let pour les variables dont la valeur peut changer, comme le compteur i dans une boucle. Utilise const pour les variables qui ne doivent pas être réassignées, comme joueur dans cet exemple. Ainsi, tu évites les effets de bord et ton code devient plus sûr et plus facile à maintenir.

Abandonner var et adopter let et const te permet d’écrire du code plus propre et prévisible. Cela t’aide à prévenir les erreurs liées à la portée des variables et à rendre ton code plus lisible.

La bonne boucle en javascript

// Mauvais exemple (utilisation de while pour un nombre connu d'itérations)
let i = 0;
while (i < 11) {
    console.log("Joueur numéro " + i);
    i++;
}

// Bon exemple (utilisation de for pour un nombre connu d'itérations)
for (let i = 0; i < 11; i++) {
    console.log("Joueur numéro " + i);
}

Explications :

Choisir la boucle appropriée rend ton code plus clair et plus efficace. Utilise une boucle for lorsque tu connais à l’avance le nombre d’itérations. D’autant qu’une boucle while peut entrainer une boucle infinie !

Si tu maitrises les callables, tu peux aussi te passer des boucles en utilisant des fonctions comme map, filter ou reduce, mais attention à garder ton code lisible !

Eviter les else inutiles en javascript

// Mauvais exemple
function checkQualification(score) {
    if (score >= 10) {
        console.log("Tu es qualifié.e pour la finale.");
    } else {
        console.log("Tu n'es pas qualifié.e.");
    }
}

// Bon exemple
function checkQualification(score) {
    if (score < 10) {
        console.log("Tu n'es pas qualifié.e.");
        return;
    }
    console.log("Tu es qualifié.e pour la finale.");
}

Explications :

En éliminant les else inutiles, tu simplifies ton code et le rends plus lisible. En retournant ou en sortant de la fonction dès que possible, tu évites les conditions imbriquées et facilites la compréhension du flux logique.

Ecrire des fonctions pour réutiliser son code

// Mauvais exemple
let athlete1SpeedKmH = (100 / 9.58) * 3.6;
let athlete2SpeedKmH = (100 / 9.80) * 3.6;

// Bon exemple
function calculateSpeedKmH(distanceMeters, timeSeconds) {
    return (distanceMeters / timeSeconds) * 3.6;
}

let athlete1SpeedKmH = calculateSpeedKmH(100, 9.58);
let athlete2SpeedKmH = calculateSpeedKmH(100, 9.80);

Explications :

En créant des fonctions pour les opérations répétitives, tu rends ton code plus modulable et facile à maintenir. Dans cet exemple, la fonction calculateSpeedKmH te permet de calculer la vitesse en km/h de n’importe quel athlète en fonction de la distance et du temps, sans répéter le calcul à chaque fois !

Commenter son code

Pas d’exemple de code ici.

Le but n’est pas de commenter pour commenter mais de prendre le temps d’écrire les commentaires avant de coder, pour expliciter la portion de code qui arrive, à quoi elle sert, comment elle fonctionne, etc. Cela permet d’écrire le plan du code à produire, avant de le produire !

J’en parle dans la vidéo : méthodologie pour résoudre un challenge de code partir de 4min27, c’est du PHP mais ça ne change rien au principe)

Diviser les problèmes en sous problèmes

// Mauvais exemple (fonction monolithique)
function getTeamStatistics(team) {
    let totalPoints = 0;
    let totalAssists = 0;
    team.forEach(player => {
        totalPoints += player.points;
        totalAssists += player.assists;
    });
    let averagePoints = totalPoints / team.length;
    let averageAssists = totalAssists / team.length;
    console.log(`Points moyens par joueur : ${averagePoints}`);
    console.log(`Passes décisives moyennes par joueur : ${averageAssists}`);
}

// Bon exemple (division en sous-fonctions)
function calculateTotal(team, stat) {
    return team.reduce((total, player) => total + player[stat], 0);
}

function calculateAverage(total, count) {
    return total / count;
}

function displayTeamStatistics(averagePoints, averageAssists) {
    console.log(`Points moyens par joueur : ${averagePoints}`);
    console.log(`Passes décisives moyennes par joueur : ${averageAssists}`);
}

function getTeamStatistics(team) {
    const totalPoints = calculateTotal(team, 'points');
    const totalAssists = calculateTotal(team, 'assists');
    const averagePoints = calculateAverage(totalPoints, team.length);
    const averageAssists = calculateAverage(totalAssists, team.length);
    displayTeamStatistics(averagePoints, averageAssists);
}

En divisant un problème complexe en sous-problèmes, tu rends ton code plus facile à gérer et à comprendre. Chaque fonction a une responsabilité spécifique, ce qui facilite les tests, car tu pourras tester les fonctions une par une et non tout le programme à la fois. C’est pareil pour la maintenance, tu vas pouvoir faire évoluer ou optimiser ton code portion par portion.

Tu peux retrouver des méthodes pour réfléchir au découpage d’un algorithme.

Tester son algorithme avec différents cas

Pas d’exemple de code ici.

Le but est de rappeler que bien souvent, le diable se cache dans les détails ! Ou plutôt que les bugs se cachent dans les cas particuliers ! Alors prends le temps d’analyser ton code et de définir les cas principaux et, surtout, les cas particuliers qui te permettront de déterminer si ton code est correct ou non.

Par « cas », j’entends un ensemble de données cohérentes entre elles qui sont susceptibles d’être des paramètres d’entrée de ton code.

Et quand on parle de tests, on ne peut pas ne pas parler de tests unitaires. Donc n’hésite pas à découvrir ce que sont les tests unitaires et comment en réaliser en javascript (des contenus dédiés arrivent sur Tainix, en attendant, Google et ChatGPT sont tes amis 😉 )

Le code le + court, une fausse bonne idée

// Mauvais exemple (code condensé et peu lisible)
players.forEach(p => { totalScore += (p.trophies > 2) ? p.points : 0; });

// Bon exemple (code clair et bien formaté)
let totalScore = 0;
players.forEach(player => {
    if (player.trophies > 2) {
        totalScore += player.points;
    }
});

Explications :

L’exemple ici est un peu extrême ! Mais fais attention aux ternaires qui s’enchainent, aux conventions non respectées, aux variables mal nommées, etc. Sur l’instant, le code parait clair et intelligent… mais quand on revient dessus quelques jours plus tard, bien souvent on y comprend plus rien !

Autres langages

Cet article existe également dans ses versions PHP et Python.


Qui a codé ce superbe contenu ?

Keep learning

Other content to discover