web-dev-qa-db-fra.com

Programmation si-moins (essentiellement sans condition)

Un de mes collègues m'a dit qu'il avait déjà travaillé pour une entreprise dont la politique était de ne jamais avoir de condition conditionnelle (déclarations "if" et "switch") dans le code et qu'ils laissaient toutes les décisions dans le code se faire en utilisant polymorphisme et (je suppose) d'autres principes OO.

Je en quelque sorte comprends le raisonnement derrière cela, à savoir que le code est plus DRY et plus facile à mettre à jour, mais je cherche une explication plus détaillée de ce concept. Ou peut-être que cela fait partie d'une approche de conception plus générale.

Si quelqu'un a des ressources pour cela ou serait disposé à expliquer ou même à avoir plus de termes liés à cela, je peux utiliser pour trouver plus de réponses, je serais très obligé.

J'ai trouvé une question sur SO était un peu liée, mais je ne suis pas familier avec C++, je ne comprends donc pas trop les réponses.

(Je ne suis pas OO guru mais je peux me débrouiller)

Je maîtrise très bien PHP, et après cela, Python, je préférerais donc utiliser des informations utilisant ces langages.

Mise à jour: je demanderai à mon collègue plus d'informations sur ce qu'il voulait dire exactement.

Mise à jour 2015: après quelques années d'expérience supplémentaire en programmation, je constate à présent que l'objectif de cette politique était probablement d'empêcher les programmeurs d'ajouter des fonctionnalités de manière aléatoire en ajoutant simplement des conditions (instructions if) à certains endroits. Une meilleure façon d'étendre un logiciel consiste à utiliser le "Principe Open/Closed" lorsque le logiciel est étendu en utilisant l'héritage et le polymorphisme. Je doute fortement que la politique soit extrêmement stricte pour tous les conditionnels, car il est difficile de s'en passer complètement.

61
Niels Bom

Il existe des ressources sur le site Anti-IF Campaign , telles que cet article .

Je crois que c'est une question de degré. Les conditions ne sont pas toujours mauvaises, mais elles peuvent être (et sont souvent) maltraitées.

Pensées supplémentaires (un jour plus tard)

Refactoring: Améliorer la conception du code existant est une bonne référence sur ce sujet (et beaucoup d’autres). Il couvre Remplace le conditionnel par le polymorphisme . Il y a aussi un nouveau, Remplacer conditionnel par visiteur , sur le site Web.

J'apprécie la simplicité et la responsabilité unique de supprimer toutes les déclarations if. Ces trois objectifs coïncident souvent. Les outils d'analyse statique prenant en charge la complexité métrique métrique peuvent rapidement pointer du code avec des conditions imbriquées ou en série. Les instructions if peuvent rester après le refactoring, mais peuvent être décomposées en méthodes plus petites et/ou en plusieurs classes.

Mise à jour: Michael Feathers a écrit un article sur Programmation inconditionnelle .

Ceci est un sujet populaire: Phil Haack sur Mort à la déclaration SI !

51
TrueWill

Après quelques années de programmation, je reviens à ma propre question, dont je comprends maintenant un peu mieux le contexte.

Sandi Metz a fait une bonne conversation dans laquelle elle refactorise une boule de déclarations-if vraiment très poilue en quelque chose de moins poilu: https://www.youtube.com/watch?v=8bZh5LMaSmE

10
Niels Bom

J'ai lu le message que vous avez lié et il semble qu'ils parlaient surtout de supprimer le besoin de conditionnels au sein d'une classe , à ne pas confondre avec tout le code en général. L'idée est que si vous devez vérifier l'état d'un objet (à l'aide d'un conditionnel) pour déterminer s'il possède certaines fonctionnalités, vous avez en réalité deux objets (un qui prend en charge la fonctionnalité et un qui ne le fait pas) et vous devez les définir comme deux. classes liées à la place.

7
user849425

Un de mes collègues m'a dit qu'il avait déjà travaillé pour une entreprise qui avait pour politique de ne jamais avoir de conditionnelles ("if" et "switch" déclarations) dans le code et qu'elles laissent toutes les décisions dans le code être fait en utilisant le polymorphisme et (je devine) un autre OO des principes.

Je pense que votre collègue a mal compris quelque chose ou utilisé les mauvais mots pour l'expliquer ..__ Et vous ne pouvez pas complètement éviter les déclarations conditionnelles.

Il y a une chose à dire: proliférer si les déclarations à l'intérieur de OOP peuvent être le symptôme d'une mauvaise programmation. Quelques exemples:

Ne pas utiliser si vérifier la valeur de retour de la fonction comme dans une ancienne programmation de style C:

int ret = some_func();
if (ret != null)
   //do something

C'était typique du code C, mais avec OOP, vous devriez utiliser l'exception:

try{
    do_something();
}catch(Exception e){
    e.printStackTrace(); //why I was not able to do something
    handle(e); //there is something else I could do to handle the occurred error
}

Parfois, si la prolifération des déclarations est liée à une mauvaise conception. Prenons l'exemple suivant en Java:

BaseClass base;
if (base instanceof DerivedClassOneFromBase){
    DerivedClassOneFromBase d = (DerivedClassOneFromBase)base;
    d.methodOne();
}else if (base instanceof DerivedClassOneFromBase){
    DerivedClassTwoFromBase d = (DerivedClassTwoFromBase)base;
    d.methodTwo();
}

Ceci est un autre exemple d'énoncés de mauvaise qualité, probablement liés à un mauvais design. Si les deux objets dérivés ont une méthode commune définie dans leur classe de base BaseClass, vous auriez pu appeler cette méthode au lieu de vérifier leur type concret et de les convertir:

base.commonMethod();
6
Heisenbug

Parfois, les conditions conditionnelles dans les méthodes sont mauvaises car elles indiquent que vous exécutez simplement plusieurs fonctions ou plusieurs méthodes de type dans la même méthode.

Si vous avez une classe appelée Automobile et des sous-classes telles que Voiture et Vélo, et une méthode telle que:

drive(Automobile a)
   if (a.isCar)
      // do stuff
   else if (a.isBike)
      // do stuff

vous êtes le plus susceptible de faire quelque chose de mal. Même s'il ne s'agit pas d'un commutateur basé sur le type, cela peut souvent être faux. Si la méthode exécute plusieurs fonctions en fonction d'une variable, elle tente souvent de faire plus d'une chose et doit probablement être séparée en plusieurs méthodes.

Par exemple:

save(Car c)
   if (c is new)
      // do some stuff
   else if (c is old)
      // do some stuff

pourrait potentiellement être divisé en enregistrer et mettre à jour, car ils sont deux fonctions différentes. Bien que cela dépend.

Interdire complètement les déclarations si elles seraient idiotes, car elles ont de nombreux cas d'utilisation valables.

4
BobTurbo

Éviter les conditionnelles ne signifie pas nécessairement que vous devez le faire par polymorphisme ou par héritage, prenez par exemple:

Vous avez 3 dossiers différents pour stocker les images téléchargées, les vidéos téléchargées et les pdf téléchargés

Vous pouvez écrire le code en tant que: 

uploadMedia(mediaType){
   if(mediaType == images){
     uploadTo("myProject/images");
   }else if(mediaType == videos){
     upoloadTo("myProject/videos);  
   }else if(mediaType == pdf){
     uploadTo("myProject/pdf");
  }
}

Une autre alternative que les gens pourraient utiliser est le cas de figure: 

uploadMedia(mediaType){
         switch(mediaType){
         case : images
         uploadTo("myProject/images");
         break;

         case : videos
         uploadTo("myProject/videos");
         break;

         case : pdf
         uploadTo("myProject/pdf");
         break;
    }
}

Mais alors vous pouvez totalement éviter les instructions conditionnelles en utilisant quelque chose comme dictionnaire/hashmap/json (selon ce que vous travaillez): 

Par exemple : 

HashMap<String,String> mediaMap = new HashMap<>();

mediaMap.put("images","myProject/images");
mediaMap.put("videos","myProject/videos");
mediaMap.put("pdf","myProject/pdf");

//mediaType can be images/videos/pdf same as keys of mediaMap
uploadMedia(mediaType){
  uploadTo(mediaMap.get(mediaType));
}

C'est en quelque sorte un pseudo-code, il peut donc y avoir des erreurs de syntaxe, mais dans l'ensemble, ce concept est également utile pour éviter les conditions. La ligne de code peut également être réduite.

0
TGW