76 votes

Déclarations de grand commutateur: Bad OOP?

J'ai toujours été d'avis que les grandes instructions de commutation sont un symptôme d'une mauvaise conception de la programmation orientée objet. Dans le passé, j'ai lu des articles qui traitent de ce sujet et ils ont fourni des altnerative de la programmation orientée objet en fonction des approches, généralement basés sur le polymorphisme d'instancier l'objet juste pour gérer le cas.

Je suis maintenant dans une situation qui a un monsterous instruction switch basé sur un flux de données à partir d'une socket TCP, dans lequel le protocole consiste, fondamentalement, de retour à la ligne résiliée de commande, suivi par des lignes de données, suivie par un marqueur de fin. La commande peut être l'un des 100 commandes différentes, donc je voudrais trouver un moyen de réduire ce monstre instruction switch pour quelque chose de plus gérable.

J'ai fait quelques recherches sur google afin de trouver les solutions je me souviens bien, mais malheureusement, Google est devenu un terrain vague de résultats non pertinents pour de nombreux types de requêtes de ces jours.

Existe-il des modèles pour ce genre de problème? Toutes les suggestions sur les implémentations possibles?

Une pensée que j'ai eu était d'utiliser une recherche dans le dictionnaire, correspondant au texte de commande pour le type d'objet à instancier. Ceci a l'avantage agréable de simplement créer un nouvel objet et de l'insertion d'une nouvelle commande/type dans la table pour toutes les nouvelles commandes.

Cependant, cela a aussi le problème du type d'explosion. J'ai maintenant besoin de 100 nouvelles classes, plus j'ai trouver un moyen d'interface proprement le modèle de données. Est le "seul vrai instruction switch" vraiment la voie à suivre?

Je vous remercie de vos pensées, des opinions ou des commentaires.

34voto

nezroy Points 2413

Vous pouvez obtenir des avantages d'un Modèle de Commande.

Pour la programmation orientée objet, vous pouvez être en mesure de l'effondrement de plusieurs autres commandes à chaque en une seule classe, si les variations de comportement sont assez petits, pour éviter une classe complète d'explosion (ouais, je peux entendre la programmation orientée objet, les gourous en hurlant sur ce point). Cependant, si le système est déjà de la programmation orientée objet, et chacune des 100+ commandes est vraiment unique, alors il suffit de leur faire unique de classes et de profiter de l'héritage de consolider la commune de trucs.

Si le système n'est pas de la POO, alors je ne voudrais pas ajouter de la POO juste pour cela... vous pouvez facilement utiliser le Modèle de Commande avec une simple recherche dans le dictionnaire et des pointeurs de fonction, ou même générées dynamiquement en fonction des appels basé sur le nom de la commande, en fonction de la langue. Ensuite, vous pouvez simplement liée logiquement fonctions dans les bibliothèques qui font partie d'une collection de commandes similaires à atteindre gérable séparation. Je ne sais pas si il y a un bon terme pour ce genre de mise en oeuvre... je pense toujours à elle comme un "répartiteur" style", basé sur l'architecture MVC-approche à la gestion des Url.

24voto

ChrisW Points 37322

Je vois avoir deux instructions de commutation comme un symptôme de la non-OO conception, où le commutateur-sur-enum type peut être remplacé avec de multiples types qui fournissent des implémentations différentes d'une interface abstraite; par exemple, la suite ...

switch (eFoo)
{
case Foo.This:
  eatThis();
  break;
case Foo.That:
  eatThat();
  break;
}

switch (eFoo)
{
case Foo.This:
  drinkThis();
  break;
case Foo.That:
  drinkThat();
  break;
}

... devrait peut-être être réécrite comme ...

IAbstract
{
  void eat();
  void drink();
}

class This : IAbstract
{
  void eat() { ... }
  void drink() { ... }
}

class That : IAbstract
{
  void eat() { ... }
  void drink() { ... }
}

Toutefois, une instruction switch n'est pas de l'omi, telle un indicateur fort que l'instruction switch devrait être remplacé par quelque chose d'autre.

16voto

Jonas Kölker Points 4520

La commande peut être l'un des 100 de différentes commandes

Si vous avez besoin de faire de 100 des choses différentes, vous ne pouvez pas éviter d'avoir un 100 de la branche. Vous pouvez l'encoder dans le flux de contrôle (switch, if-elseif^100) ou de données (100 élément de carte de la chaîne de commande/usine/stratégie). Mais il sera là.

Vous pouvez essayer d'isoler le résultat de l'100 de la branche de choses qui n'ont pas besoin de connaître l'issue. Peut-être juste 100 différentes méthodes est très bien; il n'y a pas besoin d'inventer des objets que vous n'en avez pas besoin si cela rend le code difficile à manier.

3voto

Loren Pechtel Points 5730

Je pense que c'est l'un des rares cas où les grands commutateurs sont la meilleure solution, à moins qu'une autre solution ne se présente.

2voto

Jason Punyon Points 21244

Je vois le modèle de stratégie. Si j'ai 100 stratégies différentes ... ainsi soit-il. La déclaration de commutateur géant est moche. Les noms de classe de toutes les commandes sont-ils valides? Dans ce cas, utilisez simplement les noms de commande en tant que noms de classe et créez l'objet de stratégie avec Activator.CreateInstance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X