3 techniques de codage puissantes pour éliminer les conditionnelles désordonnées
Présente trois techniques de codage puissantes pour optimiser et simplifier les structures conditionnelles complexes, améliorant ainsi la qualité et la maintenabilité du code.
Dans le développement de logiciels, nous rencontrons souvent des logiques de code qui doivent gérer plusieurs scénarios. Si elles ne sont pas gérées correctement, ces logiques peuvent facilement évoluer en de longues chaînes if-else ou de grandes instructions switch. Cet article introduira plusieurs techniques efficaces pour optimiser ces structures, améliorant ainsi la qualité et la maintenabilité du code.
1. Programmation défensive : retour anticipé
Disons que nous développons un système d'authentification d'utilisateur qui doit vérifier différents statuts d'utilisateur avant de permettre l'accès :
Ce code présente des problèmes structurels évidents. Il utilise des structures if-else profondément imbriquées, rendant le code difficile à lire et à maintenir.À mesure que le nombre de vérifications de condition augmente, le niveau d'indentation du code s'approfondit, formant un code dit en forme de "flèche". La logique de gestion des erreurs est dispersée à travers différents niveaux d'imbrication, ce qui n'est pas propice à une gestion unifiée. Plus important encore, la logique centrale du code — le cas où l'accès est autorisé — est enfouie profondément dans plusieurs couches de jugements conditionnels, manquant d'intuitivité. Ce style de codage réduisant non seulement la lisibilité du code, mais aussi augmentant le risque d'erreurs et rendant l'extension du code difficile.
Nous pouvons optimiser ce code en utilisant l'approche du "retour anticipé" :
En adoptant la stratégie du "retour anticipé", nous avons réussi à optimiser la structure originale du code.
Cette méthode apporte plusieurs améliorations :
- Elle réduit considérablement la complexité de l'imbrication du code. Chaque vérification de condition est traitée de manière indépendante, rendant la logique globale plus claire et compréhensible. Cette structure aplatie améliore non seulement la lisibilité du code mais réduit également grandement la difficulté de maintenance.
- Cette méthode d'optimisation réalise une gestion centralisée de la logique de traitement des erreurs. En retournant des résultats immédiatement après chaque vérification de condition, nous évitons l'exécution inutile de code tout en centralisant le traitement des divers scénarios d'erreur, rendant l'ensemble du processus de gestion des erreurs plus organisé.
- La logique centrale du code — les conditions permettant l'accès — devient plus saillante. Cette structure rend le but principal du code immédiatement apparent, améliorant grandement l'expressivité et la compréhensibilité du code.
2. Méthode de la table de consultation
Nous rencontrons souvent des scénarios où différents résultats doivent être retournés en fonction de différentes entrées. Si elles ne sont pas gérées correctement, ces logiques peuvent facilement évoluer en de longues chaînes if-else ou de grandes instructions switch. Par exemple, sur une plateforme de commerce électronique, nous devons retourner des descriptions de statut correspondantes en fonction de différents statuts de commande :
C'est un scénario typique de retour de résultats différents selon différents cas. À mesure que le nombre de cas augmente, l'instruction switch ou les jugements if-else deviennent long. De plus, dans ce scénario, si les utilisateurs ont besoin de traduire ces contenus de statut dans d'autres langues, cela nécessiterait de modifier le corps de la fonction ou d'ajouter de nouvelles fonctions, ce qui apporterait des coûts de maintenance significatifs.
Dans ce cas, nous pouvons utiliser la méthode de la table de consultation pour optimiser le code :
Tout d'abord, en utilisant un objet Map pour stocker la relation de mappage entre les statuts et les descriptions, le code devient plus concis. Nous avons également facilité le déplacement des descriptions de statut vers des fichiers de configuration, offrant une commodité pour l'internationalisation et les mises à jour dynamiques. Lorsque de nouveaux statuts sont ajoutés, nous n'avons pas besoin de modifier le code logique de base ; il nous suffit d'ajouter des paires clé-valeur correspondantes dans la configuration.
3. Programmation orientée interface
Lors du développement de grands systèmes logiciels, nous devons souvent prendre en charge plusieurs fournisseurs de services ou modules fonctionnels. Nous pouvons envisager d'utiliser la programmation orientée interface à l'étape de conception logicielle pour faciliter les extensions ultérieures, éliminant ainsi la complexité des multiples jugements conditionnels induite par le codage en dur dans des systèmes complexes.
Supposons que nous développons un système de traduction multilingue qui doit prendre en charge différents fournisseurs de services de traduction. Si nous ne considérons pas la programmation orientée interface dès l'étape de conception, les extensions ultérieures deviendront très difficiles :
Cette implémentation utilise une structure if-else simple et brute pour sélectionner les fournisseurs de services de traduction, rendant le code difficile à maintenir et à étendre. Lors de l'ajout de nouveaux fournisseurs de traduction à l'avenir, le code existant doit être modifié, et à mesure que de plus en plus de fournisseurs de traduction doivent être pris en charge, le code deviendra encombré et difficile à maintenir. En même temps, cette méthode complexe est également difficile à tester unitairement car elle n'est pas facile à simuler avec différents fournisseurs de traduction.
Pour résoudre ces problèmes, nous pouvons utiliser la programmation orientée interface pour optimiser le code. La programmation orientée interface est un moyen important de mettre en œuvre le polymorphisme, permettant à différents objets de répondre différemment au même message.
Processus d'implémentation :
- Définir l'interface de stratégie de traduction :
- Implémenter cette interface pour chaque fournisseur de traduction :
- Réorganiser la classe TranslationService, en passant la stratégie en paramètre :
- Utiliser le code optimisé :
En définissant l'interface TranslationStrategy
et en introduisant la programmation orientée interface, nous avons gagné les avantages suivants :
TranslationService
peut utiliser différentes stratégies de traduction pour chaque appel.- Ajouter de nouveaux fournisseurs de traduction devient simple, il suffit de créer une nouvelle classe de stratégie et d'implémenter l'interface.
- Le code client peut choisir de manière flexible la stratégie à utiliser pour chaque traduction sans modifier la logique centrale de
TranslationService
. - Chaque stratégie de traduction peut être testée indépendamment, améliorant ainsi la testabilité du code.
- Éviter de maintenir l'état dans
TranslationService
rend le service plus sans état et sûr pour les threads.
Conclusion
L'optimisation des structures de déclarations conditionnelles est un moyen important d'améliorer la qualité du code. Les trois méthodes introduites dans cet article — la programmation défensive, la méthode de la table de consultation, et la programmation orientée interface (combinée avec le polymorphisme) — ont chacune leurs scénarios d'application :
- La programmation défensive est adaptée à la gestion de plusieurs vérifications de condition indépendantes et peut efficacement réduire l'imbrication du code.
- La méthode de la table de consultation est adaptée à la gestion des exigences qui réagissent différemment à différents cas, rendant le code plus concis et facile à maintenir.
- La programmation orientée interface combinée avec le polymorphisme est adaptée à la construction de systèmes complexes mais flexibles, améliorant la flexibilité et l'évolutivité du code.
Dans le développement réel, nous devons souvent choisir des méthodes appropriées en fonction des situations spécifiques, et parfois même appliquer de manière exhaustive plusieurs techniques. L'important est de trouver un équilibre entre la simplicité, la lisibilité et la maintenabilité du code, en choisissant la solution qui convient le mieux au problème actuel.
Rappelez-vous, une sur-optimisation peut entraîner un code excessivement complexe. Garder le code simple et lisible est toujours le principe de base. Lors de l'application de ces techniques, des choix judicieux doivent être faits en fonction des besoins spécifiques du projet et du niveau technique de l'équipe.