35 votes

Refactoring si / autre logique

J'ai une classe Java avec une méthode de 1000 lignes de la logique if / else comme ceci:

 if (userType == "admin") {
     if (age > 12) {
          if (location == "USA") {
               // do stuff
          } else if (location == "Mexico") {
               // do something slightly different than the US case
          }
     } else if (age < 12 && age > 4) {
          if (location == "USA") {
               // do something slightly different than the age > 12 US case
          } else if (location == "Mexico") {
               // do something slightly different
          }
     }
 } else if (userType == "student") {
     if (age > 12) {
          if (location == "USA") {
               // do stuff
          } else if (location == "Mexico") {
               // do something slightly different than the US case
          }
     } else if (age < 12 && age > 4) {
          if (location == "USA") {
               // do something slightly different than the age > 12 US case
          } else if (location == "Mexico") {
               // do something slightly different
          }
     }
 

Comment devrais-je reformer ceci en quelque chose de plus maniable?

26voto

Péter Török Points 72981

Vous devez utiliser des Stratégies, éventuellement mis en œuvre dans un enum, par exemple:

enum UserType {
  ADMIN() {
    public void doStuff() {
      // do stuff the Admin way
    }
  },
  STUDENT {
    public void doStuff() {
      // do stuff the Student way
    }
  };

  public abstract void doStuff();
}

Comme la structure du code à l'intérieur de chaque ultrapériphériques if succursale dans votre code ressemble à peu près la même, dans la prochaine étape de refactoring vous pourriez facteur que la duplication à l'aide du modèle de méthodes. Sinon, vous pouvez tourner à l'Emplacement (et éventuellement de l'Âge) dans une stratégie.

Mise à jour: dans Java4, vous pouvez mettre en œuvre un typesafe enum par la main, et l'utilisation de la plaine de vieux-classement pour mettre en œuvre les différentes stratégies.

12voto

Bill the Lizard Points 147311

La première chose que je ferais avec ce code est de créer les types Admin et Student , qui héritent tous deux du type de base User . Ces classes doivent avoir une méthode doStuff() laquelle vous masquez le reste de cette logique.

En règle générale, chaque fois que vous vous surprenez à changer de type, vous pouvez utiliser le polymorphisme à la place.

9voto

duffymo Points 188155

Des milliers? Peut-être un moteur de règles est ce que vous avez besoin. Bave pourrait être une alternative viable.

Ou un modèle de Commande qui encapsule tous les "faire quelque chose de différent" logique pour chaque cas. Stocker chaque Commande une Carte avec la concaténation de l'âge, l'emplacement et d'autres facteurs comme la clé. La recherche de la Commande, de l'exécuter, et vous avez terminé. Agréable et propre.

La Carte peut être stockée que la configuration et le lire sur démarrer. Vous pouvez ajouter de nouveaux logique par l'ajout de nouvelles classes et de reconfiguration.

6voto

Andreas_D Points 64111

Le premier à utiliser les énumérations pour userType et de l'emplacement - ensuite, vous pouvez utiliser les instructions switch (améliore la lisibilité)

La deuxième utilisation de plusieurs méthodes.

Exemple:

switch (userType) {
  case Admin: handleAdmin(); break;
  case Student: handleStudent(); break;
}

et plus tard

private void handleAdmin() {
  switch (location) {
    case USA: handleAdminInUSA(); break;
    case Mexico: handleAdminInMexico(); break;
  }
}

En outre, d'identifier les doublons de code et de le mettre dans des méthodes supplémentaires.

MODIFIER

Si quelqu'un vous force à du code Java sans les énumérations (comme vous êtes obligés d'utiliser Java 1.4.2), de l'utilisation finale de la statique au lieu d'énumérations ou de faire quelque chose comme:

  if (isAdmin(userType)) {
    handleAdmin(location, age);
  } else if (isStudent(userType)) {
    handleStudent(location, age));
  }

//...

private void handleAdmin(String location, int age) {
  if (isUSA(location)) {
    handleAdminInUSA(age);
  } else if (isUSA(location)) {
    handleAdminInMexico(age);
  }
}

//...

private void handleAdminInUSA(int age) {
  if (isOldEnough(age)) {
    handleAdminInUSAOldEnough();
  } else if (isChild(age)) {
    handleChildishAdminInUSA(); // ;-)
  } //...
}

1voto

Hank Gay Points 36173

En me basant uniquement sur les noms de variable, je suppose que vous devriez sous-classer User (ou quoi que ce soit qui possède une variable userType ) en AdminUser et StudentUser (et éventuellement d'autres) et utilise le polymorphisme .

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