Question

J'ai la méthode et l'interface suivantes:

public object ProcessRules(List<IRule> rules)
{
    foreach(IRule rule in rules)
    {
        if(EvaluateExpression(rule.Exp) == true) return rule.Result;
    }

    //Some error handling here for not hitting any rules
}

public interface IRule
{
    Expression Exp;
    Object Result;
    int Precedence;
}

Comme les règles ont la priorité, elles ne doivent en réalité jamais être traitées de manière erronée. Cela me conduit avec (je pense) trois solutions:

  1. Triez les règles avant de les transmettre à l'évaluateur.
  2. Changez le type de paramètre en quelque chose qui applique un ordre de tri.
  3. Tri au sein de l'évaluateur.

J'aime l’option 3 car elle garantit toujours qu’elle est triée et j’aime l’option 1 car elle semble plus cohérente. Et l'option 2 semble être un bon compromis.

Un scénario comme celui-ci est-il spécifique au contexte / subjectif ou existe-t-il vraiment une meilleure pratique à appliquer ici?

Était-ce utile?

La solution

Je pense que cela ressemble plus à une violation de la loi de Demeter et à son encapsulation. EvaluateExpression semble appartenir aux règles. Considérez ceci:

public object ProcessRules(List<IRule> rules) {
    foreach(IRule rule in rules) {
        return rule.EvaluateExpression();
    }
}

public interface IRule {
    object EvaluateExpression();
}

De cette façon, vous n'avez pas à exposer les éléments internes des règles, comme Exp ou Result.

Et oui, si le comportement souhaité est que les règles soient évaluées par ordre de priorité, assurez-vous qu’elles sont triées. La règle a la responsabilité de s’évaluer, alors que l’appelant décide dans quel ordre les évaluer.

Autres conseils

Je voterais pour l'option 3. Pour minimiser le couplage, vous voulez éviter de faire trop d'hypothèses sur les données envoyées à une fonction.

Si une classe différente devait l'utiliser plus tard, supposeriez-vous qu'elle sache les passer en ordre de priorité?

Dans un scénario comme celui-ci, je ferais quelque chose comme:

public class RuleProcessor
{   
     public void SortRules(List<IRule> rules){}

     //You could make this an abstract method
     public object ProcessSortedRules(List<IRule> rules)
     {
         foreach(IRule rule in rules)
         {
             if(EvaluateExpression(rule.Exp) == true) return rule.Result;
         }

     //Some error handling here for not hitting any rules

     }

     public object ProcessRules(List<IRule> rules)
     {
          SortRules(rules);
          ProcessSortedRules(rules);
     }

}

Vous pouvez en faire une classe abstraite ou une sorte de fonctionnalité agrégée par d'autres classes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top