Pregunta

Tengo el siguiente método e interfaz:

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

Debido a que las reglas tienen prioridad, en realidad nunca deberían procesarse fuera de servicio. Esto me lleva con (creo) tres soluciones:

  1. Ordenar reglas antes de pasarlas al evaluador.
  2. Cambie el tipo de parámetro a algo que imponga un orden de clasificación.
  3. Ordenar dentro del evaluador.

Me gusta la opción 3 porque siempre garantiza que esté ordenada y me gusta la opción 1 porque parece más coherente. Y la opción 2 parece un buen compromiso.

¿Es un escenario como este contexto específico / subjetivo, o hay realmente una mejor práctica para aplicar aquí?

¿Fue útil?

Solución

Creo que es más como una violación de la Ley de Demeter y la encapsulación. EvaluateExpression parece que pertenece a las reglas. Considera esto:

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

public interface IRule {
    object EvaluateExpression();
}

De esa manera, no tiene que exponer las partes internas de las reglas, como Exp o Result.

Y sí, si el comportamiento que desea es que las reglas se evalúen en orden de precedencia, asegúrese de que estén ordenadas. La responsabilidad de la regla es evaluarse a sí misma, mientras que es la decisión de quien llama en qué orden evaluarlas.

Otros consejos

Mi voto iría por la opción 3. En un esfuerzo por minimizar el acoplamiento, desea asegurarse de no hacer demasiadas suposiciones sobre los datos enviados a una función.

Si una clase diferente hiciera uso de esto en una fecha posterior, ¿asumirías que saben pasarlos ordenados por prioridad?

En un escenario como este, haría algo como:

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

}

Podría hacer que una clase abstracta o algún tipo de funcionalidad agreguen otras clases.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top