Aikido

Pourquoi utiliser les retours anticipés et les clauses de garde pour un code plus propre et plus lisible

Lisibilité

Règle

Utilisation précoce retours et garde et les clauses de garde.
L'imbrication imbrication et tardive paramètres tardive
faire fonctions plus difficiles plus lire et de maintenance.

Langues prises en charge : 45+

Introduction

Les clauses de garde valident les préconditions au début d'une fonction et retournent immédiatement si les conditions ne sont pas remplies. Cela aplatit l'imbrication en gérant les cas d'erreur en amont, laissant la logique principale non imbriquée et facile à lire. Les fonctions qui valident les paramètres à mi-chemin ou imbriquent les chemins de succès dans plusieurs conditionnelles forcent les lecteurs à suivre le contexte sur de nombreux niveaux d'indentation.

Pourquoi c'est important

Lisibilité du code : Les clauses de garde rendent le chemin nominal visible à la fin de la fonction sans imbrication. Les lecteurs voient toutes les conditions d'erreur en amont, puis lisent la logique principale à un seul niveau d'indentation sans suivre mentalement plusieurs conditions imbriquées.

Maintenance et modification : L'ajout de nouvelles conditions de validation ou d'erreur à un code profondément imbriqué nécessite un placement minutieux pour éviter de casser la logique existante. Les clauses de garde en début de fonction permettent d'ajouter de nouvelles vérifications sans toucher à la logique principale, réduisant ainsi le risque d'introduire des bugs.

Exemples de code

❌ Non conforme :

function processPayment(user, amount) {
    if (user) {
        if (user.isActive) {
            if (amount > 0) {
                if (user.balance >= amount) {
                    user.balance -= amount;
                    return { success: true, newBalance: user.balance };
                } else {
                    return { success: false, error: 'Insufficient funds' };
                }
            } else {
                return { success: false, error: 'Invalid amount' };
            }
        } else {
            return { success: false, error: 'Inactive user' };
        }
    } else {
        return { success: false, error: 'User required' };
    }
}

Pourquoi c'est incorrect : Quatre niveaux d'imbrication cachent la logique principale (déduction du solde) profondément à l'intérieur de la fonction. Chaque condition d'erreur ajoute un niveau d'indentation supplémentaire, rendant le chemin nominal difficile à trouver et à comprendre d'un coup d'œil.

✅ Conforme :

function processPayment(user, amount) {
    if (!user) {
        return { success: false, error: 'User required' };
    }
    if (!user.isActive) {
        return { success: false, error: 'Inactive user' };
    }
    if (amount <= 0) {
        return { success: false, error: 'Invalid amount' };
    }
    if (user.balance < amount) {
        return { success: false, error: 'Insufficient funds' };
    }

    user.balance -= amount;
    return { success: true, newBalance: user.balance };
}

Pourquoi c'est important : Les clauses de garde valident toutes les préconditions avec des retours anticipés, maintenant la fonction à un seul niveau d'indentation. Le chemin nominal (déduction du solde) est clairement visible à la fin sans imbrication, ce qui rend la fonction facile à lire et à modifier.

Conclusion

Validez les entrées et gérez les cas d'erreur au début des fonctions avec des clauses de garde. Retournez tôt lorsque les conditions échouent, plutôt que d'imbriquer le chemin de succès. Cela maintient le code plat, lisible et facile à modifier sans rompre la logique existante.

FAQ

Des questions ?

Les retours multiples ne rendent-ils pas les fonctions plus difficiles à comprendre ?

Non. L'ancienne règle du "retour unique" datait de l'époque du nettoyage manuel des ressources. Les langages modernes gèrent le nettoyage automatiquement. Les retours anticipés multiples pour les conditions d'erreur clarifient l'intention plutôt que de suivre des conditionnelles imbriquées pour trouver où l'exécution se termine.

Les clauses de garde doivent-elles lever des exceptions ou retourner des valeurs d'erreur ?

Dépend du contexte. Utilisez des exceptions pour les erreurs inattendues (bugs de programmation, pannes système). Retournez des valeurs d'erreur pour les échecs de validation attendus (entrée invalide, violations de règles métier). Les clauses de garde fonctionnent avec les deux approches, la clé est d'échouer rapidement au début de la fonction.

Qu'en est-il des performances des multiples instructions de retour ?

Impact nul. Les compilateurs et interpréteurs optimisent les instructions de retour de manière identique, quel que soit leur nombre. Les retours anticipés peuvent en fait améliorer les performances en évitant un travail inutile lorsque les préconditions échouent.

Comment gérer une logique de validation complexe dans les clauses de garde ?

Extrayez la validation dans des fonctions distinctes : `if (!isValidAmount(amount)) return error;`. Cela maintient la lisibilité des clauses de garde tout en encapsulant une logique de validation complexe. Chaque fonction de validation peut avoir ses propres tests et sa propre documentation.

Que se passe-t-il si j'ai besoin de code de nettoyage avant le retour ?

Utilisez des blocs `try-finally` ou des mécanismes de nettoyage spécifiques au langage (`defer` en Go, `using` en C#, gestionnaires de contexte en Python). Les clauses de garde vont à l'intérieur des blocs `try`, le nettoyage va dans `finally`. La structure reste plate avec des retours anticipés tout en garantissant que le nettoyage a lieu.

Sécurisez-vous maintenant.

Sécuriser votre code, votre cloud et votre runtime dans un système centralisé unique.
Détectez et corrigez les vulnérabilités rapidement et automatiquement.

Pas de carte de crédit requise | Résultats du scan en 32 secondes.