Domanda

Ho il metodo e l'interfaccia seguenti:

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;
}

Poiché le regole hanno una precedenza, in realtà non devono mai essere elaborate in modo anomalo. Questo mi porta con (penso) tre soluzioni:

  1. Ordina le regole prima di passarle nel valutatore.
  2. Cambia il tipo di parametro in qualcosa che impone un ordinamento.
  3. Ordina all'interno del valutatore.

Mi piace l'opzione 3 perché assicura sempre che sia ordinata e mi piace l'opzione 1 perché sembra più coerente. E l'opzione 2 sembra un buon compromesso.

Uno scenario come questo contesto è specifico / soggettivo o esiste davvero una buona pratica da applicare qui?

È stato utile?

Soluzione

Penso che sia più come una violazione della Legge di Demetra e incapsulamento. EvaluateExpression sembra appartenere alle regole. Considera questo:

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

public interface IRule {
    object EvaluateExpression();
}

In questo modo non devi esporre gli interni delle regole, come Exp o Result.

E sì, se il comportamento che desideri è che le regole vengano valutate in ordine di precedenza, assicurati che siano ordinate. La responsabilità della regola è di valutare se stessa, mentre è la decisione del chiamante in quale ordine valutarli.

Altri suggerimenti

Il mio voto andrebbe per l'opzione 3. Nel tentativo di minimizzare l'accoppiamento, vuoi assicurarti di non fare troppe ipotesi sui dati inviati in una funzione.

Se una classe diversa dovesse usarlo in un secondo momento, penseresti che sapessero passarli ordinati per precedenza?

In uno scenario come questo farei qualcosa del tipo:

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);
     }

}

Potresti rendere aggregata una classe astratta o una sorta di funzionalità di altre classi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top