Méthodes pour éliminer le commutateur dans le code [fermé]

175

Quels sont les moyens d'éliminer l'utilisation du commutateur dans le code?

Mariano
la source
18
Pourquoi voudriez-vous éliminer les commutateurs lorsqu'ils sont utilisés de manière appropriée? Pouvez-vous préciser votre question.
RB.
Je vote que cette question soit rendue modifiable par la communauté car tout le monde dit la même chose et il serait peut-être bien de consolider toutes les opinions;)
Josh
2
Le commutateur n'est pas aussi standard que les autres instructions. Par exemple, en C ++, vous risquez d'oublier la «pause» et vous obtiendrez alors des résultats inattendus. En outre, cette «pause» est trop similaire à un GOTO. Je n'ai jamais essayé d'éliminer les interrupteurs, mais ce n'est certainement pas mon instruction préférée. ;)
2
Je pense qu'il fait référence au concept de commutateur et non à l'instruction de commutateur C ++ ou Java. Un commutateur peut également être une chaîne de blocs «if-else if».
Outlaw Programmer
2
Vous pouvez être amusé: il y a un grand nombre de programmeurs notables de la communauté agile qui se joignent à la campagne anti-IF: antiifcampaign.com/supporters.html
Mike A

Réponses:

267

Les instructions Switch ne sont pas un anti-modèle en soi, mais si vous codez en orienté objet, vous devriez vous demander si l'utilisation d'un switch est mieux résolue avec le polymorphisme au lieu d'utiliser une instruction switch.

Avec le polymorphisme, ceci:

foreach (var animal in zoo) {
    switch (typeof(animal)) {
        case "dog":
            echo animal.bark();
            break;

        case "cat":
            echo animal.meow();
            break;
    }
}

devient ceci:

foreach (var animal in zoo) {
    echo animal.speak();
}
mlarsen
la source
2
J'ai été critiqué à cause d'une suggestion similaire dans stackoverflow.com/questions/374239/... Tant de personnes ne croient pas au polymorphisme :) Très bon exemple.
Nazgob
30
-1: Je n'ai jamais utilisé d'instruction switch avec typeof, et cette réponse ne suggère pas de moyens ou de raisons de contourner les instructions switch dans d'autres situations.
Kevin
3
Je suis d'accord avec @Kevin - l'exemple donné ne montre pas vraiment comment éliminer le commutateur par polymorphisme. Les exemples simples: obtenez le nom d'énumération en changeant ses valeurs, ou exécutez du code avec des valeurs appropriées dans une sorte d'algorithme.
HotJard
Je me demandais comment l'éliminer avant de pouvoir compter sur des implémentations spécifiques, c'est-à-dire dans une usine. Et j'ai trouvé un excellent exemple ici stackoverflow.com/a/3434505/711855
juanmf
1
exemple très trivial.
GuardianX
239

Voir l' odeur des déclarations Switch :

En règle générale, les instructions de commutation similaires sont dispersées dans un programme. Si vous ajoutez ou supprimez une clause dans un commutateur, vous devez souvent rechercher et réparer les autres.

Les deux refactorisation et refactoring pour modèles ont des approches pour résoudre ce problème.

Si votre (pseudo) code ressemble à:

class RequestHandler {

    public void handleRequest(int action) {
        switch(action) {
            case LOGIN:
                doLogin();
                break;
            case LOGOUT:
                doLogout();
                break;
            case QUERY:
               doQuery();
               break;
        }
    }
}

Ce code viole le principe ouvert fermé et est fragile à chaque nouveau type de code d'action qui se présente. Pour remédier à cela, vous pouvez introduire un objet 'Command':

interface Command {
    public void execute();
}

class LoginCommand implements Command {
    public void execute() {
        // do what doLogin() used to do
    }
}

class RequestHandler {
    private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
    public void handleRequest(int action) {
        Command command = commandMap.get(action);
        command.execute();
    }
}

Si votre (pseudo) code ressemble à:

class House {
    private int state;

    public void enter() {
        switch (state) {
            case INSIDE:
                throw new Exception("Cannot enter. Already inside");
            case OUTSIDE:
                 state = INSIDE;
                 ...
                 break;
         }
    }
    public void exit() {
        switch (state) {
            case INSIDE:
                state = OUTSIDE;
                ...
                break;
            case OUTSIDE:
                throw new Exception("Cannot leave. Already outside");
        }
    }

Ensuite, vous pouvez introduire un objet «État».

// Throw exceptions unless the behavior is overriden by subclasses
abstract class HouseState {
    public HouseState enter() {
        throw new Exception("Cannot enter");
    }
    public HouseState leave() {
        throw new Exception("Cannot leave");
    }
}

class Inside extends HouseState {
    public HouseState leave() {
        return new Outside();
    }
}

class Outside extends HouseState {
    public HouseState enter() {
        return new Inside();
    }
}

class House {
    private HouseState state;
    public void enter() {
        this.state = this.state.enter();
    }
    public void leave() {
        this.state = this.state.leave();
    }
}

J'espère que cela t'aides.

boîte à outils
la source
7
Merci pour cet excellent exemple sur la façon de refactoriser le code. Bien que je pourrais dire au début, il est un peu difficile à lire (car il faut basculer entre plusieurs fichiers pour le comprendre complètement)
rshimoda
8
Les arguments contre switch sont valides tant que vous réalisez que la solution polymorphe sacrifie la simplicité du code. De plus, si vous stockez toujours vos cas de commutateur dans des énumérations, certains compilateurs vous avertiront que des états sont manquants dans le commutateur.
Harvey
1
Ceci est un excellent exemple d'opérations complètes / incomplètes et bien sûr de la restructuration du code en POO. Merci beaucoup. Je pense qu'il sera utile que les partisans de la POO / des modèles de conception suggèrent de traiter les concepts de POO comme des opérateurs plutôt que des concepts . Je veux dire que "extend", "factory", "implements", etc. sont si souvent utilisés dans les fichiers, classes, branches. Ils doivent être simples comme des opérateurs tels que "+", "-", "+ =", "?:", "==", "->" etc. Quand un programmeur les utilise dans son esprit aussi simplement que des opérateurs, seulement alors il peut réfléchir à toute la bibliothèque de classes sur l'état du programme et les opérations (in) complètes.
namespaceform
13
Je commence à penser que SWITCH est beaucoup plus compréhensible et logique que cela. Et j'aime généralement beaucoup la POO, mais cette résolution me semble trop abstraite
JK
1
Avec l'objet Command, le code à générer n'aurait-il Map<Integer, Command>pas besoin d'un commutateur?
ataulm
41

Un commutateur est un modèle, qu'il soit implémenté avec une instruction switch, une chaîne if else, une table de recherche, un polymorphisme oop, une correspondance de modèle ou autre.

Voulez-vous éliminer l'utilisation de l '" instruction switch " ou du " modèle de commutation "? Le premier ne peut être éliminé, le second, que si un autre modèle / algorithme peut être utilisé, et la plupart du temps ce n'est pas possible ou ce n'est pas une meilleure approche pour le faire.

Si vous souhaitez éliminer l' instruction switch du code, la première question à poser est de savoir est -il judicieux d'éliminer l'instruction switch et d'utiliser une autre technique. Malheureusement, la réponse à cette question est spécifique au domaine.

Et rappelez-vous que les compilateurs peuvent effectuer diverses optimisations pour changer d'instructions. Ainsi, par exemple, si vous souhaitez traiter efficacement les messages, une instruction switch est à peu près la voie à suivre. Mais d'un autre côté, exécuter des règles métier basées sur une instruction switch n'est probablement pas la meilleure façon de procéder et l'application doit être ré-recherchée.

Voici quelques alternatives à l'instruction switch:

Pop Catalin
la source
1
Quelqu'un pourrait-il donner une comparaison du traitement des messages utilisant le commutateur par rapport à d'autres alternatives?
Mike A
37

Changer en soi n'est pas si mal, mais si vous avez beaucoup de "switch" ou "if / else" sur les objets dans vos méthodes, cela peut être un signe que votre conception est un peu "procédurale" et que vos objets ne sont que de la valeur seaux. Déplacez la logique vers vos objets, invoquez une méthode sur vos objets et laissez-les décider comment répondre à la place.

Lars Westergren
la source
En supposant bien sûr qu'il n'écrit pas en C. :)
Bernard
1
en C, il peut (ab?) utiliser des pointeurs de fonction et des structures pour construire quelque chose de semblable à un objet;)
Tetha
Vous pouvez écrire FORT ^ H ^ H ^ H ^ H Java dans n'importe quel langage. ; p
Bernard
Tout à fait d'accord - le commutateur est un excellent moyen de réduire les lignes de code, mais ne jouez pas trop avec.
HotJard
21

Je pense que le meilleur moyen est d'utiliser une bonne carte. En utilisant un dictionnaire, vous pouvez mapper presque n'importe quelle entrée à une autre valeur / objet / fonction.

votre code ressemblerait à quelque chose (psuedo) comme ceci:

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}
Josh
la source
4
Cela dépend de la langue. Il peut être beaucoup moins lisible qu'un interrupteur
Vinko Vrsalovic
C'est une belle solution élégante dans la bonne situation. J'ai fait ce mappage des codes clés récemment, et il semblait bien lire à cette fin.
Bernard
C'est vrai, je ne l'utiliserais probablement pas pour quelque chose de simple, mais cela offre une certaine flexibilité en termes de configuration par rapport à une instruction switch. Un dictionnaire peut être préparé à la volée tandis qu'un commutateur sera toujours codé en dur.
Josh
Peut être plus propre dans certaines circonstances. Aussi plus lent, car il nécessite des appels de fonction.
Nick Johnson
1
Cela dépend de vos clés. Un compilateur peut compiler une instruction switch en une simple recherche ou une recherche binaire statique extrêmement rapide, dans les deux cas sans nécessiter aucun appel de fonction.
Nick Johnson
12

Tout le monde aime les if elseblocs ÉNORMES . Si facile à lire! Je suis cependant curieux de savoir pourquoi vous voudriez supprimer les instructions switch. Si vous avez besoin d'une instruction switch, vous avez probablement besoin d'une instruction switch. Sérieusement, je dirais que cela dépend de ce que fait le code. Si tout le commutateur fait appel à des fonctions (disons), vous pouvez passer des pointeurs de fonction. Que ce soit une meilleure solution est discutable.

La langue est un facteur important ici aussi, je pense.

Bernard
la source
13
Je suppose que c'était du sarcasme :)
Craig Day
6

Je pense que ce que vous recherchez, c'est le modèle de stratégie.

Cela peut être implémenté de plusieurs manières, qui ont été mentionnées dans d'autres réponses à cette question, telles que:

  • Une carte de valeurs -> fonctions
  • Polymorphisme. (le sous-type d'un objet décidera comment il gère un processus spécifique).
  • Fonctions de première classe.
UN J.
la source
5

switch Il serait bon de remplacer les instructions si vous vous surprenez à ajouter de nouveaux états ou un nouveau comportement aux instructions:

état int;

String getString () {
   commutateur (état) {
     case 0: // comportement pour l'état 0
           retourne "zéro";
     cas 1: // comportement pour l'état 1
           retourne "un";
   }
   throw new IllegalStateException ();
}

double getDouble () {

   commutateur (this.state) {
     case 0: // comportement pour l'état 0
           return 0d;
     cas 1: // comportement pour l'état 1
           return 1d;
   }
   throw new IllegalStateException ();
}

Ajouter un nouveau comportement nécessite de copier le switch, et ajouter de nouveaux états signifie en ajouter un autre caseà chaque switch instruction.

En Java, vous ne pouvez changer qu'un nombre très limité de types primitifs dont vous connaissez les valeurs au moment de l'exécution. Cela pose un problème en soi: les états sont représentés sous forme de nombres ou de caractères magiques.

L'appariement de modèles et plusieurs if - elseblocs peuvent être utilisés, bien qu'ils aient vraiment les mêmes problèmes lors de l'ajout de nouveaux comportements et de nouveaux états.

La solution que d'autres ont suggérée comme "polymorphisme" est une instance du modèle d'état :

Remplacez chacun des états par sa propre classe. Chaque comportement a sa propre méthode sur la classe:

État IState;

String getString () {
   return state.getString ();
}

double getDouble () {
   return state.getDouble ();
}

Chaque fois que vous ajoutez un nouvel état, vous devez ajouter une nouvelle implémentation de l' IStateinterface. Dans un switchmonde, vous ajouteriez un caseà chacun switch.

Chaque fois que vous ajoutez un nouveau comportement, vous devez ajouter une nouvelle méthode à l' IStateinterface et à chacune des implémentations. C'est le même fardeau qu'avant, bien que maintenant le compilateur vérifie que vous avez des implémentations du nouveau comportement sur chaque état préexistant.

D'autres ont déjà dit que cela peut être trop lourd, donc bien sûr, il y a un point où vous atteignez où vous passez de l'un à l'autre. Personnellement, la deuxième fois que j'écris un switch, c'est le moment où je refactore.

Jamesh
la source
4

sinon

Je réfute la prémisse selon laquelle le changement est intrinsèquement mauvais.

Titulaire Iain
la source
3

Eh bien, d'une part, je ne savais pas que l'utilisation de switch était un anti-pattern.

Deuxièmement, switch peut toujours être remplacé par des instructions if / else if.

SCdF
la source
exactement - switch est juste de la méthadone syntaxique pour un tas de if / elsifs.
Mike A
3

Pourquoi voulez-vous? Entre les mains d'un bon compilateur, une instruction switch peut être beaucoup plus efficace que les blocs if / else (en plus d'être plus facile à lire), et seuls les plus gros commutateurs sont susceptibles d'être accélérés s'ils sont remplacés par une sorte de la structure de données de recherche indirecte.

Nick Johnson
la source
2
À quel point vous remettez en question le compilateur et apportez des modifications à votre conception en fonction des composants internes du compilateur. La conception doit suivre la nature du problème et non la nature du compilateur.
Mike A
3

«switch» est juste une construction de langage et toutes les constructions de langage peuvent être considérées comme des outils pour faire un travail. Comme pour les vrais outils, certains outils sont mieux adaptés à une tâche qu'à une autre (vous n'utiliseriez pas de marteau pour installer un crochet). La partie importante est de savoir comment «faire le travail» est défini. Doit-il être maintenable, doit-il être rapide, doit-il évoluer, doit-il être extensible, etc.

À chaque étape du processus de programmation, il existe généralement une gamme de constructions et de modèles qui peuvent être utilisés: un commutateur, une séquence if-else-if, des fonctions virtuelles, des tables de sauts, des cartes avec des pointeurs de fonction, etc. Avec l'expérience, un programmeur connaîtra instinctivement le bon outil à utiliser pour une situation donnée.

Il faut supposer que quiconque maintient ou révise le code est au moins aussi qualifié que l'auteur original afin que toute construction puisse être utilisée en toute sécurité.

Skizz
la source
OK, mais pourquoi avons-nous besoin de 5 façons différentes et redondantes de faire la même chose - l'exécution conditionnelle?
Mike A
@ mike.amy: Parce que chaque méthode a des avantages et des coûts différents et qu'il s'agit d'obtenir le plus d'avantages avec le moindre coût.
Skizz
1

Si le commutateur est là pour faire la distinction entre différents types d'objets, il vous manque probablement des classes pour décrire précisément ces objets, ou des méthodes virtuelles ...

Xavier Nodet
la source
1

Pour C ++

Si vous faites référence à ie un AbstractFactory, je pense qu'une méthode registerCreatorFunc (..) est généralement meilleure que de demander d'ajouter un cas pour chaque "nouvelle" déclaration qui est nécessaire. Puis laisser toutes les classes créer et enregistrer une creatorFunction (..) qui peut être facilement implémentée avec une macro (si j'ose le mentionner). Je pense que c'est une approche courante que font de nombreux cadres. Je l'ai vu pour la première fois dans ET ++ et je pense que de nombreux frameworks qui nécessitent une macro DECL et IMPL l'utilisent.

Epatel
la source
1

Dans un langage procédural, comme C, alors le commutateur sera meilleur que n'importe laquelle des alternatives.

Dans un langage orienté objet, il existe presque toujours d'autres alternatives disponibles qui utilisent mieux la structure de l'objet, en particulier le polymorphisme.

Le problème avec les instructions de commutation se produit lorsque plusieurs blocs de commutation très similaires se produisent à plusieurs endroits dans l'application et que la prise en charge d'une nouvelle valeur doit être ajoutée. Il est assez courant pour un développeur d'oublier d'ajouter la prise en charge de la nouvelle valeur à l'un des blocs de commutateurs dispersés dans l'application.

Avec le polymorphisme, une nouvelle classe remplace la nouvelle valeur et le nouveau comportement est ajouté dans le cadre de l'ajout de la nouvelle classe. Le comportement à ces points de commutation est alors soit hérité de la superclasse, remplacé pour fournir un nouveau comportement, soit implémenté pour éviter une erreur du compilateur lorsque la super méthode est abstraite.

Là où il n'y a pas de polymorphisme évident, cela peut valoir la peine de mettre en œuvre le modèle de stratégie .

Mais si votre alternative est un gros bloc IF ... ALORS ... ELSE, alors oubliez-le.

Bill Michell
la source
1

Utilisez un langage qui n'est pas fourni avec une instruction switch intégrée. Je pense à Perl 5.

Sérieusement, pourquoi voudriez-vous l'éviter? Et si vous avez de bonnes raisons de l'éviter, pourquoi ne pas simplement l'éviter alors?

innaM
la source
1

Les pointeurs de fonction sont un moyen de remplacer une énorme instruction switch, ils sont particulièrement utiles dans les langages où vous pouvez capturer des fonctions par leurs noms et créer des trucs avec elles.

Bien sûr, vous ne devez pas forcer les instructions switch à sortir de votre code, et il y a toujours une chance que vous le fassiez mal, ce qui se traduit par des morceaux de code stupides et redondants. (C'est parfois inévitable, mais un bon langage devrait vous permettre de supprimer la redondance tout en restant propre.)

Voici un excellent exemple de division et de conquête:

Disons que vous avez une sorte d'interprète.

switch(*IP) {
    case OPCODE_ADD:
        ...
        break;
    case OPCODE_NOT_ZERO:
        ...
        break;
    case OPCODE_JUMP:
        ...
        break;
    default:
        fixme(*IP);
}

Au lieu de cela, vous pouvez utiliser ceci:

opcode_table[*IP](*IP, vm);

... // in somewhere else:
void opcode_add(byte_opcode op, Vm* vm) { ... };
void opcode_not_zero(byte_opcode op, Vm* vm) { ... };
void opcode_jump(byte_opcode op, Vm* vm) { ... };
void opcode_default(byte_opcode op, Vm* vm) { /* fixme */ };

OpcodeFuncPtr opcode_table[256] = {
    ...
    opcode_add,
    opcode_not_zero,
    opcode_jump,
    opcode_default,
    opcode_default,
    ... // etc.
};

Notez que je ne sais pas comment supprimer la redondance de l'opcode_table en C. Peut-être que je devrais poser une question à ce sujet. :)

Gai
la source
0

La réponse la plus évidente, indépendante de la langue, est d'utiliser une série de «si».

Si le langage que vous utilisez a des pointeurs de fonction (C) ou des fonctions qui sont des valeurs de 1ère classe (Lua), vous pouvez obtenir des résultats similaires à un "commutateur" en utilisant un tableau (ou une liste) de (pointeurs vers) des fonctions.

Vous devriez être plus précis sur la langue si vous voulez de meilleures réponses.

Remo.D
la source
0

Les instructions Switch peuvent souvent être remplacées par une bonne conception OO.

Par exemple, vous disposez d'une classe Account et utilisez une instruction switch pour effectuer un calcul différent en fonction du type de compte.

Je suggérerais que cela soit remplacé par un certain nombre de classes de compte, représentant les différents types de compte, et implémentant toutes une interface de compte.

Le basculement devient alors inutile, car vous pouvez traiter tous les types de comptes de la même manière et grâce au polymorphisme, le calcul approprié sera exécuté pour le type de compte.

Jason
la source
0

Cela dépend de la raison pour laquelle vous souhaitez le remplacer!

De nombreux interpréteurs utilisent des 'gotos calculés' au lieu d'instructions switch pour l'exécution d'opcode.

Ce qui me manque dans le commutateur C / C ++, c'est le Pascal 'in' et les plages. J'aimerais aussi pouvoir activer les cordes. Mais ceux-ci, bien que simples à manger pour un compilateur, sont un travail difficile lorsqu'ils utilisent des structures, des itérateurs et des choses. Donc, au contraire, il y a plein de choses que j'aimerais pouvoir remplacer par un switch, si seulement le switch C () était plus flexible!

Volonté
la source
0

Switch n'est pas une bonne façon de procéder car il brise le principal Open Close. Voilà comment je fais.

public class Animal
{
       public abstract void Speak();
}


public class Dog : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Hao Hao");
   }
}

public class Cat : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Meauuuu");
   }
}

Et voici comment l'utiliser (en prenant votre code):

foreach (var animal in zoo) 
{
    echo animal.speak();
}

En gros, ce que nous faisons, c'est déléguer la responsabilité à la classe enfant au lieu de laisser le parent décider quoi faire des enfants.

Vous voudrez peut-être également lire le "Principe de substitution de Liskov".

Sheraz
la source
0

En JavaScript utilisant un tableau associatif:
ceci:

function getItemPricing(customer, item) {
    switch (customer.type) {
        // VIPs are awesome. Give them 50% off.
        case 'VIP':
            return item.price * item.quantity * 0.50;

            // Preferred customers are no VIPs, but they still get 25% off.
        case 'Preferred':
            return item.price * item.quantity * 0.75;

            // No discount for other customers.
        case 'Regular':
        case
        default:
            return item.price * item.quantity;
    }
}

devient ceci:

function getItemPricing(customer, item) {
var pricing = {
    'VIP': function(item) {
        return item.price * item.quantity * 0.50;
    },
    'Preferred': function(item) {
        if (item.price <= 100.0)
            return item.price * item.quantity * 0.75;

        // Else
        return item.price * item.quantity;
    },
    'Regular': function(item) {
        return item.price * item.quantity;
    }
};

    if (pricing[customer.type])
        return pricing[customer.type](item);
    else
        return pricing.Regular(item);
}

Courtoisie

Premraj
la source
-12

Un autre vote pour if / else. Je ne suis pas un grand fan des déclarations de cas ou d'interrupteurs, car certaines personnes ne les utilisent pas. Le code est moins lisible si vous utilisez le cas ou le commutateur. Peut-être pas moins lisible pour vous, mais pour ceux qui n'ont jamais eu besoin d'utiliser la commande.

Il en va de même pour les usines d'objets.

Les blocs if / else sont une construction simple que tout le monde obtient. Il y a quelques choses que vous pouvez faire pour vous assurer de ne pas causer de problèmes.

Premièrement, n'essayez pas d'indenter les déclarations if plus d'une ou deux fois. Si vous vous trouvez en retrait, c'est que vous le faites mal.

 if a = 1 then 
     do something else 
     if a = 2 then 
         do something else
     else 
         if a = 3 then 
             do the last thing
         endif
     endif 
  endif

Est vraiment mauvais - faites-le à la place.

if a = 1 then 
   do something
endif 
if a = 2 then 
   do something else
endif 
if a = 3 then 
   do something more
endif 

L'optimisation soit damnée. Cela ne fait pas beaucoup de différence pour la vitesse de votre code.

Deuxièmement, je ne suis pas opposé à la sortie d'un bloc If tant qu'il y a suffisamment d'instructions break dispersées dans le bloc de code particulier pour le rendre évident

procedure processA(a:int)
    if a = 1 then 
       do something
       procedure_return
    endif 
    if a = 2 then 
       do something else
       procedure_return
    endif 
    if a = 3 then 
       do something more
       procedure_return
    endif 
end_procedure

EDIT : Sur Switch et pourquoi je pense qu'il est difficile de grok:

Voici un exemple d'instruction switch ...

private void doLog(LogLevel logLevel, String msg) {
   String prefix;
   switch (logLevel) {
     case INFO:
       prefix = "INFO";
       break;
     case WARN:
       prefix = "WARN";
       break;
     case ERROR:
       prefix = "ERROR";
       break;
     default:
       throw new RuntimeException("Oops, forgot to add stuff on new enum constant");
   }
   System.out.println(String.format("%s: %s", prefix, msg));
 }

Pour moi, le problème ici est que les structures de contrôle normales qui s'appliquent dans les langages de type C ont été complètement brisées. Il existe une règle générale selon laquelle si vous souhaitez placer plus d'une ligne de code dans une structure de contrôle, vous utilisez des accolades ou une instruction de début / fin.

par exemple

for i from 1 to 1000 {statement1; statement2}
if something=false then {statement1; statement2}
while isOKtoLoop {statement1; statement2}

Pour moi (et vous pouvez me corriger si je me trompe), l'instruction Case jette cette règle hors de la fenêtre. Un bloc de code exécuté conditionnellement n'est pas placé dans une structure de début / fin. Pour cette raison, je pense que Case est conceptuellement suffisamment différent pour ne pas être utilisé.

Espérons que cela répond à vos questions.

seanyboy
la source
Wow - évidemment une réponse controversée. Je serais intéressé de savoir ce que je suis si mal.
seanyboy
Euh, changer comme étant trop complexe? Je ne sais pas ... il me semble qu'il n'y aurait plus beaucoup de fonctionnalités de langage que vous pourriez utiliser. :) De plus, dans votre exemple central, ne serait-il pas plus intelligent de faire si (a == 1 || a == 2 || a == 3) fait quelque chose?
Lars Westergren
De plus, dans votre dernier exemple, "break" ne fera rien dans la plupart des langues - qui sort du bloc le plus proche (généralement une boucle), ce qui dans votre cas se produit quand même sur la ligne suivante (endif). Si vous utilisez un langage où break est "return", de nombreux retours sont également mal vus (à l'exception des "déclarations de garde")
Lars Westergren
4
"L'optimisation soit damné. Cela ne fait pas beaucoup de différence pour la vitesse de votre code." Mon code fonctionne sur une plate-forme mobile. Les optimisations comptent. De plus, les commutateurs peuvent rendre le code TRÈS propre (par rapport à if..elseif..elseif..elseif ...) s'ils sont utilisés correctement. Jamais vu? Apprenez-les.
Swati
Changer n'est pas du tout compliqué, mais j'ai toujours essayé de minimiser le nombre de constructions utilisées dans le code pour réduire les frictions dans la compréhension.
seanyboy