Quelle est la meilleure alternative à une déclaration de commutateur hors de contrôle?
J'ai hérité d'un projet qui a un énorme interrupteur de blocs, certains contenant jusqu'à 20 cas. Ce qui est une bonne façon de réécrire ces?
source d'informationauteur Asmussen
Vous devez vous connecter pour publier un commentaire.
Pourquoi voulez-vous de les réécrire dans une autre structure? Si vous avez vraiment des 20 cas qui doivent être traitées individuellement, un switch/case est le chemin à parcourir. Une grande chaîne de si/alors, la logique serait horrible à gérer.
Polymorphisme est une autre option si vous utilisez un langage orienté objet. Chaque sous-classe serait de mettre en œuvre sa propre fonctionnalité dans la méthode.
Polymorphisme. Mais il ne peut pas être une mince refactoring.
Quelques exemples et références:
Refactoring (fourni par google livres)
Code d'Instruction Switch odeur et le Polymorphisme
Refactoring de l'interrupteur-états
Comme d'autres l'ont souligné, il dépend de l'instruction switch. Cependant, dans le passé, j'ai refait les instructions switch en procédant de la manière suivante. Supposons que nous avons une instruction switch comme ça, avec beaucoup de répétition du code
la première chose à faire est de reconnaître les parties communes (dans le monde réel, ce sera probablement un peu plus importante)
et le transformer en une fonction
alors pour les pièces à changer, dans chaque cas, utiliser une table de hachage ou d'un tableau;
de là, nous pouvons le faire:
Et avec tvals pris en compte de l'instruction switch, il pourrait même être fourni à l'externe, afin d'élargir le nombre de cas que vous pouvez manipuler. Ou vous pourriez construire dynamiquement. Dans le monde réel, l'instruction switch ont souvent des cas particuliers, cependant. Je laisse ça comme un exercice pour le lecteur.
Trois suggestions (en écho à certains déjà cités):
Peut-être un commutateur n'est pas aussi mauvais que vous le pensez. Il peut être laid si le cas de blocs sont de grande taille. Raccourcir par l'extraction de la logique dans les méthodes.
Dans un langage OO, polymorphisme pourrait être la réponse, comme beaucoup l'ont souligné.
Dans un langage fonctionnel, comme le Javascript, écrire une fonction qui renvoie la fonction dont vous avez besoin pour exécuter quelle que soit l'entrée. Qui peut utiliser l'instruction switch lui-même, ou il peut utiliser une table de recherche.
Vous pouvez toujours utiliser une table de recherche.
Il n'y a rien de mal à avoir 20 cas dans une instruction switch. Vous pouvez ranger le code refactoring et, à tout le moins, déplacez le traitement des cas dans les méthodes/fonctions.
En fonction de ce que l'instruction switch est de l'évaluation, vous pouvez refactoriser le code en utilisant le Modèle de Stratégie. Jetez un oeil à ce post pour un exemple de remplacement d'un interrupteur sur les valeurs de l'enum avec des classes séparées pour chaque fonction.
Il peut être également que l'aide de l'interrupteur avec 20 cas est peut être le meilleur plan d'action. Tant que c'est lisible et chaque résultat indique clairement que l'action il n'y a pas vraiment besoin de refactoriser le code.
En général, je pense que vous devriez refactoriser uniquement lorsque vous en avez besoin, par exemple lorsque vous voulez ajouter plus de fonctionnalités, mais la conception actuelle n'est pas pour la tâche. Vous devez ensuite refactoriser sans l'ajout de la nouvelle fonctionnalité, et seulement ensuite, ajouter la nouvelle fonctionnalité.
Dans d'autres circonstances, ne vous embêtez pas avec le refactoring. Faites-le quand vous en avez besoin, sinon il n'y a sans doute des choses plus importantes à faire.
Si vous avez vraiment vraiment besoin, puis le Visiteur Modèle De Conception est une commune de commutateur-en cas de remplacement, mais vous devriez noter qu'il a des inconvénients. (c'est à dire, découvrez http://www.objectmentor.com/resources/articles/acv.pdf)
Cela dépend de ce que l'instruction switch est en train de faire.
Si c'est de la correspondance des caractères ou des chaînes, dire dans un analyseur syntaxique, et vous n'avez pas le même ensemble de motifs répétés partout dans le code, puis d'une instruction switch peut être ok.
Si c'est la congruence (dire) un entier dans une liste de valeurs autorisées, vous pouvez créer une classe de base et un ensemble de classes dérivées pour chaque valeur. Alors, ce que génère les données entières en premier lieu peut créer une instance de la classe dérivée avec l'ensemble de l'instruction switch "réponses" à la place.
Une troisième option est de créer une structure de données de cartes de motifs pour les actions (par exemple, des fonctions ou des objets avec des méthodes virtuelles). Vous pouvez consulter le commutateur de valeur dans cette structure de données, et d'exécuter l'action appropriée.
si ça fonctionne sans bugs majeurs (par pas majeur, je veux dire qu'ils ne vous font pas tirer les cheveux) pourquoi s'embêter à refactoriser? Ne pas refactoriser tout.
Si vous le souhaitez, vous pouvez le changer pour le polymorphisme, mais ce sera un fusil de chasse à la chirurgie, vous aurez probablement à refactoriser un ensemble beaucoup plus que juste ce bloc de commutateurs.
Visite https://github.com/Pedram-Ahmadpour/Switch-Case
Côté Client
Créer une instance de votre Conditionpuis de passer d'un état à Condition objet par Switch() fonction.
Côté serveur
Créer un action de condition. Cette interface définit la façon d'exécuter une Condition.
Créer une liste de dossiers que vous le souhaitez. Ces classes doivent implémenter action de condition et ICase; Garder la lumière.
ICase tient juste un Clé qu'il est utilisé par Switch() fonction pour naviguer le cas.
Créer un Condition classe qu'il Inherites SwitchCase générique de la classe abstraite.
Définir un Switch() de la fonction et de naviguer Cas bien de trouver des correspondances des cas, puis les exécuter comme un action de condition.
SourirePleurer..., peut être énorme, ne vous inquiétez pas au sujet de leur dimension; action de condition et ICase garder le lazy load.