éviter si les déclarations

voix
34

Je pensais à la conception orientée objet aujourd'hui, et je me demandais si vous devriez éviter si des déclarations. Ma pensée est que dans tous les cas où vous avez besoin d'une instruction if vous pouvez simplement créer deux objets qui mettent en œuvre la même méthode. Les deux implémentations de la méthode serait tout simplement les deux branches possibles de l'original si la déclaration.

Je me rends compte que cela semble extrême, mais il semble que vous pouvez essayer et argumenter dans une certaine mesure. Toute réflexion sur ce sujet?

MODIFIER

Wow cela n'a pas pris longtemps. Je suppose que cela est trop extrême. Est-il possible de dire cependant, que sous POO vous devriez vous attendre de manière moins si les déclarations?

EDIT DEUXIÈME

Qu'en est- il ceci: Un objet qui détermine la mise en œuvre de la méthode en fonction de ses attributs. C'est - à - dire que vous pouvez mettre en œuvre someMethod()de deux manières et de préciser certaines restrictions. A tout moment un objet acheminera à la mise en œuvre correcte de la méthode en fonction de ses propriétés. Ainsi , dans le cas d' if(x > 5)avoir juste deux méthodes qui reposent sur l' xattribut

Créé 26/08/2009 à 22:21
source utilisateur
Dans d'autres langues...                            


24 réponses

voix
12

Expliquer comment mettre en œuvre ce qui suit sans instruction if ou la logique ternaire:

if ( x < 5 ) {
   x = 0
} else {
   print x;
}
Créé 26/08/2009 à 22:23
source utilisateur

voix
3

Comment décidez-vous de la méthode de l'objet à utiliser sans instruction if?

Créé 26/08/2009 à 22:23
source utilisateur

voix
0

Il est tout à fait extrême. Faire ce que vous suggérez causerait beaucoup de duplication de code inutile, à moins que l'ensemble de la fonction était complètement différente, basée sur une seule entourant si; et si oui, que si aurait probablement dû être de l'autre côté de l'appel de méthode.

Si-déclarations ont certainement leur place dans la conception-orient objet.

Créé 26/08/2009 à 22:24
source utilisateur

voix
0

Certes, une certaine forme de comparaison doit être faite indépendamment de ce que vous faites? En fin de compte ... que vous pouvez éviter si les déclarations mais vous auriez du code de production qui est identique au code en utilisant une instruction if.

Quelqu'un me corriger si im tort, mais je ne peux pas penser à un moment où vous pouvez obtenir toute forme de victoire faire.

Créé 26/08/2009 à 22:24
source utilisateur

voix
1

C'est une idée intéressante. Je pense que vous pourriez théoriquement faire, mais ce serait une énorme douleur dans une langue non spécifiquement conçu pour le soutenir. Je ne vois certainement aucune raison de.

Créé 26/08/2009 à 22:24
source utilisateur

voix
2

Création d' une nouvelle classe pour un else, alors que techniquement faisable, entraînerait probablement un code qui est difficile à lire, maintenir ou même se révéler correcte.

Créé 26/08/2009 à 22:24
source utilisateur

voix
1

Je pense que ce qu'il dit ou ce qu'il veut dire est qu'il pense qu'il est préférable d'éviter de trop d'abus de « marquage » et en ajoutant des fonctionnalités personnalisées à une classe par plusieurs instructions if quand il mieux est logique de sous-classe ou repenser l'objet hiérarchie.

Créé 26/08/2009 à 22:26
source utilisateur

voix
4

À certains égards, cela peut être une bonne idée. Swiching sur un champ de type à l'intérieur d'un objet est généralement une mauvaise idée quand vous pouvez utiliser functtions virtuelle à la place. Mais le mécanisme de fonction virtuelle est en aucun cas destiné à remplacer le cas () d'essai en général.

Créé 26/08/2009 à 22:27
source utilisateur

voix
0

Je pense l'application de cet argument à l'idée de chaque instruction if est assez extrême, mais certaines langues, vous donner la possibilité d'appliquer cette idée dans certains scénarios.

Voici un exemple de mise en œuvre Python je l'ai écrit dans le passé pour un deque taille fixe (file d'attente à double extrémité). Au lieu de créer une méthode « supprimer » et ayant si des déclarations à l'intérieur pour voir si la liste est pleine ou non, vous venez de créer deux méthodes et les réaffecter à la fonction « supprimer » au besoin.

L'exemple suivant répertorie uniquement la méthode « supprimer », mais il y a évidemment « ajouter » méthodes et autres aussi.

class StaticDeque(collections.deque):

    def __init__(self, maxSize):

        collections.deque.__init__(self)
        self._maxSize = int(maxSize)
        self._setNotFull()

    def _setFull(self):

        self._full = True
        self.remove = self._full_remove

    def _setNotFull(self):

        self._full = False
        self.remove = self._not_full_remove

    def _not_full_remove(self,value):

        collections.deque.remove(self,value)

    def _full_remove(self,value):

        collections.deque.remove(self,value)
        if len(self) != self._maxSize and self._full:
            self._setNotFull()

Dans la plupart des cas, il est pas très utile d'une idée, mais parfois il peut être utile.

Créé 26/08/2009 à 22:28
source utilisateur

voix
3

Cela dépend de ce que la déclaration originale compare. Ma règle de base est que si elle est un switchou iftester l' égalité contre une énumération, alors c'est un bon candidat pour une méthode distincte. Cependant, switchet les ifdéclarations sont utilisées pour beaucoup, beaucoup d' autres types de tests - il n'y a pas de bonne façon de remplacer les opérateurs relationnels ( <, >, <=, >=) avec des méthodes spécialisées, et certains types de tests énumérés fonctionnent beaucoup mieux avec les déclarations standards.

Donc , vous ne devriez remplacer ifs si elles ressemblent à ceci:

if (obj.Name == "foo" || obj.Name == "bar") { obj.DoSomething(); }
else if (obj.Name == "baz") { obj.DoSomethingElse(); }
else { obj.DoDefault(); }
Créé 26/08/2009 à 22:28
source utilisateur

voix
8

Oui il est vrai que peuvent être simplifiées avec polymorphishm conditionals souvent complexes. Mais ce ne est pas utile tout le temps. Allez lire le livre Refactoring Fowler pour avoir une idée du moment.

http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html

Créé 26/08/2009 à 22:30
source utilisateur

voix
8

Éliminer complètement si les déclarations n'est pas réaliste et je ne pense pas que ce soit Ori suggère. Mais ils peuvent souvent être remplacés par polymorphisme. (Et peut donc plusieurs instructions switch).

Francesco Cirillo a commencé la campagne anti-Si pour sensibiliser le public à cette question. Il dit:

Savoir utiliser des objets permet aux développeurs d'éliminer en fonction du type FI, ceux que la plupart des compromis souvent la flexibilité du logiciel et sa capacité à évoluer.

Vous ou votre équipe peut également se joindre à la campagne .

Créé 26/08/2009 à 22:33
source utilisateur

voix
0

Je dirai que la réponse est vaguement oui-ish. Surtout quand la langue permet une programmation fonctionnelle lourds (c.-à-C #, F #, OCaml).

Un composant qui contient 2 si les déclarations fortement couples deux règles d'affaires, PORTER vers le haut.

Prenez comme règle empirique très générale, mais je suis d'accord. Si vous avez un tas de déclarations si, peut-être vous devriez penser à une autre approche.

Créé 26/08/2009 à 22:40
source utilisateur

voix
0

Si-déclarations sont assez coeur à la programmation de sorte, bref, vous ne pouvez pas les éviter sensiblement.

Cependant, un objectif clé dans POO - en fait, l'un des « piliers » - est l'encapsulation. L'ancien « encapsulent ce qui varie » règle vous aide à supprimer ces gênants si et déclarations cas où vous essayez de rendre compte de toutes les options de votre objet. Une meilleure solution pour traiter avec des branches, des cas particuliers, etc. est d'utiliser quelque chose comme le modèle de conception « Factory » (Résumé usine ou méthode d'usine - en fonction des besoins, bien sûr).

Par exemple, plutôt que d'avoir votre principal contrôle de boucle de code qui OS votre utilisant avec des instructions if ramifient pour créer des fenêtres de l'interface graphique avec différentes options pour chaque système d'exploitation, votre code principal serait de créer un objet à partir de l'usine, qui utilisent le système d'exploitation pour déterminer quel système d'exploitation objet concret à Spécifiques faire. En faisant cela, vous prenez les variations (et les longues clauses if-then-else) sur votre boucle de code principal et laisser l'enfant manipuler des objets - donc la prochaine fois que vous avez besoin de faire un changement comme le soutien d'un nouveau système d'exploitation , vous ajoutez simplement une nouvelle classe de l'interface d'usine.

Créé 26/08/2009 à 22:41
source utilisateur

voix
3

En réponse à la question de ifTrue:

Eh bien, si vous avez des classes ouvertes et un système de type dépendant suffisamment fort, il est facile, si un peu bête. Officieusement et en aucune langue particulière:

class Nat {
    def cond = {
        print this;
        return this;
    }
}

class NatLessThan<5:Nat> { // subclass of Nat
    override cond = {
        return 0;
    }
}

x = x.cond();

(a continué...)

Ou, sans classes ouvertes, mais en supposant l'envoi multiple et les classes anonymes:

class MyCondFunctor {
    function branch(Nat n) {
        print n;
        return n;
    }

    function branch(n:NatLessThan<5:Nat>) {
        return 0;
    }
}

x = new MyCondFunctor.branch(x);

Ou, comme avant, mais avec des classes anonymes:

x = new {
    function branch(Nat n) {
        print n;
        return n;
    }

    function branch(n:NatLessThan<5:Nat>) {
        return 0;
    }
}.branch(x);

Vous auriez un temps beaucoup plus facile si vous refactorisé cette logique, bien sûr. Rappelez-vous qu'il existe des systèmes de type entièrement Turing-complet.

Créé 26/08/2009 à 22:44
source utilisateur

voix
0

J'ai suivi l'anti-si parler ces derniers temps et il ne sonne comme la rhétorique extrême / hyperbolique pour moi. Cependant , je pense qu'il ya du vrai dans cette affirmation: souvent la logique d'une instruction if peut être plus correctement mis en œuvre par le polymorphisme. Je pense qu'il est bon de garder à l' esprit que chaque fois que vous droit une instruction if. Cela étant dit, je pense que si la déclaration est encore une structure logique de base, et il ne faut pas craindre ou évitais comme principe.

Créé 26/08/2009 à 23:01
source utilisateur

voix
6

Un de mon professeur disait que. Je tends à penser que les gens d'être si dogmatique de ce genre de chose ne sont généralement pas le programme pour gagner leur vie.

Créé 26/08/2009 à 23:05
source utilisateur

voix
5

Jetez un oeil à la campagne anti-Si l'idée est de ne pas remplacer chaque cas dans votre application avec le modèle de stratégie ou de l' État. L'idée est que lorsque vous avez une logique de ramification complexe en particulier basé sur quelque chose comme une énumération, vous devriez chercher à refactorisation au modèle de stratégie.

Et ce cas, vous pouvez supprimer le si tous ensemble à l'aide d'une usine. Voici un exemple relativement simple. Bien sûr, comme je l'ai dit dans un cas réel, la logique dans vos stratégies serait un peu plus complexe que juste l'impression de « Je suis actif ».

public enum WorkflowState
{
  Ready,
  Active,
  Complete
}

public interface IWorkflowStrategy
{
  void Execute();
}

public class ActiveWorkflowStrategy:IWorkflowStrategy
{
  public void Execute()
  {
    Console.WriteLine("The Workflow is Active");
  }
}

public class ReadyWorkflowStrategy:IWorkflowStrategy
{
  public void Execute()
  {
    Console.WriteLine("The Workflow is Ready");
  }
}

public class CompleteWorkflowStrategy:IWorkflowStrategy
{
  public void Execute()
  {
    Console.WriteLine("The Workflow is Complete");
  }
}

public class WorkflowStrategyFactory
{
  private static Dictionary<WorkflowState, IWorkflowStrategy> _Strategies= 
    new Dictionary<WorkflowState, IWorkflowStrategy>();
  public WorkflowStrategyFactory()
  {
    _Strategies[WorkflowState.Ready]=new ReadyWorkflowStrategy();
    _Strategies[WorkflowState.Active]= new ActiveWorkflowStrategy();
    _Strategies[WorkflowState.Complete = new CompleteWorkflowStrategy();
  }
  public IWorkflowStrategy GetStrategy(WorkflowState state)
  {
    return _Strategies[state];
  }
}

public class Workflow
{
    public Workflow(WorkflowState state)
    {
        CurrentState = state;
    }
    public WorkflowState CurrentState { get; set; }
}

public class WorkflowEngine
{
    static void Main(string[] args)
    {
        var factory = new WorkflowStrategyFactory();
        var workflows =
            new List<Workflow>
                {
                    new Workflow(WorkflowState.Active),
                    new Workflow(WorkflowState.Complete),
                    new Workflow(WorkflowState.Ready)
                };
        foreach (var workflow in workflows)
        {
            factory.GetStrategy(workflow.CurrentState).
                Execute();
        }
    }
}   
Créé 26/08/2009 à 23:08
source utilisateur

voix
0

Mes deux bits ici de ce que je comprends de l'approche orientée objet -

Tout d'abord, quels objets dans un programme doit être intuitif. Autrement dit, je ne devrais pas essayer de créer une classe de « Arithmatic » pour fournir des fonctions mathématiques. Ceci est un abus de OOD.

Deuxièmement, ce qui est une opinion très forte de la mienne. Il ne doit pas être appelée conception orientée objet , mais l' objet et la méthode de conception orientée! Si les noms des méthodes des objets eux - mêmes ne sont pas des objets intuitifs alors hérités pourraient finir par réimplémentant les méthodes déjà disponibles.

approche orientée objet, selon moi, ne remplace pas l'approche procédurale. Au contraire, il est principalement pour deux raisons principales pour les créateurs de la langue -

  1. Une meilleure capacité de détermination de la portée des variables.

  2. Une meilleure capacité de collecte des ordures plutôt que d'avoir trop de variables globales.

Créé 26/09/2009 à 14:19
source utilisateur

voix
32

Je peux vous dire une chose. Peu importe ce que les gens disent, penser à simplifier et à éliminer inutiles est un branchement signe de vous venant à échéance en tant que développeur de logiciels. Il y a beaucoup de raisons pour lesquelles est mauvais branchement, les tests, la maintenance, le taux plus élevé de bugs et ainsi de suite. Ceci est l'une des choses que je recherche lors des entretiens avec les gens et est un excellent indicateur comment ils sont arrivés à maturité en tant que développeur. Je vous encourage à continuer à expérimenter, simplifier votre code et la conception en utilisant des conditions moins. Quand je l'ai fait ce commutateur j'ai trouvé beaucoup moins de temps de débogage mon code, simplement travaillé, quand je devais changer quelque chose, les changements ont été super facile à faire puisque la plupart du code est séquentiel. Encore une fois, je vous encourage 100% à continuer à faire ce que vous faites, peu importe ce que les autres disent. Gardez à l'esprit la plupart des développeurs travaillent et la réflexion au niveau beaucoup plus faible et il suffit de suivre les règles. Donc bon travail avoir soulevé cette question.

Créé 29/05/2011 à 18:08
source utilisateur

voix
5

Éviter Si Affirmation: Il y a plusieurs façons de le faire, l'un d'eux est ci-dessous:

int i=0;
if(i==1)
{
//Statement1
}

if(i==2)
{
//Statement2
}

if(i==3)
{
//Statement3
}

if(i==4)
{
//Statement4
}

En utilisant Dictionnaire et délégué:

delegate void GetStatement ();

Dictionary<int,GetStatement > valuesDic=new Dictionary<int,GetStatement >();

void GetStatement1()
{
//Statement1
}
void GetStatement2()
{
//Statement2
}
void GetStatement3()
{
//Statement3
}


void GetStatement4()
{
//Statement4
}

void LoadValues()
{
valuesDic.Add(1,GetStatement1);
valuesDic.Add(2,GetStatement2);
valuesDic.Add(3,GetStatement3);
valuesDic.Add(4,GetStatement4);

}

Remplacement Si Déclaration:

int i=0;
valuesDic[i].Invoke();
Créé 15/04/2012 à 16:47
source utilisateur

voix
2
Assume we have conditional values.

public void testMe(int i){

if(i=1){
somevalue=value1;
}


if(i=2){
 somevalue=value2;
}

if(i=3){
somevalue=value3;
}

}

//**$$$$$you can replace the boring IF blocks with Map.$$$$$**

// ================================================ ============

Same method would look like this:
--------------------------------
public void testMe(int i){

Map<Integer,String> map = new HashMap<Integer,String>();

map.put(1,value1);
map.put(2,value2);
map.put(3,value3);

}
This will avoid the complicated if conditions.

Vous pouvez utiliser la solution simliar lors de l'utilisation des modèles d'usine pour les classes de chargement.

public void loadAnimalsKingdom(String animalKingdomType)
    if(animalKingdomType="bird"){
    Bird b = new Bird();
    }
    if(animalKingdomType="animal"){
    Animal a= new Animal();
    }
    if(animalKingdomType="reptile"){
    Reptile r= new Reptile();
    }
  }

Maintenant, en utilisant la carte:

   public void loadAnimalsKingdom(String animalKingdomType)
    {
       Map <String,String> map = new HashMap<String,String>();

       map.put("bird","com.animalworld.Bird.Class");
       map.put("animal","com.animalworld.Animal.Class");
       map.put("reptile","com.animalworld.Reptile.Class");

       map.get(animalKingdomType);

***Use class loader to load the classes on demand once you extract the required class from the map.***
}

Comme la solution? Donnez pouce vers le haut. - Vv

Créé 28/07/2017 à 06:04
source utilisateur

voix
0

Je suis d'accord avec Vance que le SI est pas bon, car elle augmente la complexité conditionnelle et devrait être évité autant que possible.

Polymorphisme est une solution tout à fait viable à condition, il est utilisé pour donner un sens et non à « éviter si ».

Une note de côté qui ne correspond pas à vos besoins POO , mais l'approche axée sur les données a aussi tendance à éviter la ramification .

Créé 06/09/2017 à 10:28
source utilisateur

voix
0

Vous devez comprendre ce que (x > 5)signifie vraiment. En supposant que xreprésente un nombre, il essentiellement « classe » tous les nombres supérieurs à cinq. Ainsi , le code ressemblerait à ceci dans une langue avec la syntaxe python:

class Number(Object):

    # ... Number implementation code ... #

    def doSomething():
        self = 0
        return self

    def doSomethingElse():
        pass

class GreaterThan5(Number):
    def doSomething():
        print "I am " + self

    def doSomethingElse():
        print "I like turtles!"

Ensuite, nous pourrions exécuter du code comme ce qui suit:

>>> type(3)
<class Number>
>>> type(3+3)
<class GreaterThan5>
>>> 3.doSomething()
0
>>> (3 + 3).doSomething()
I am 6
>>> (7 - 3).doSomethingElse()
>>>

La conversion automatique de type ici est important. Pour autant que je sache, aucun des aujourd'hui langues vous permet de jouer avec des entiers autant.

En fin de compte, vous pouvez le faire dans votre code que ce soit. Tant que les gens qui lisent, il peut comprendre immédiatement. Ainsi, l'envoi polymorphes sur les entiers ou quoi que ce soit unordinary doit vraiment avoir un bon raisonnement derrière elle.

Créé 28/01/2018 à 03:02
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more