Это нарушение принципа единой ответственности?

У меня есть следующий метод и интерфейс:

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

Поскольку правила имеют приоритет, они никогда не должны обрабатываться не по порядку. Это приводит меня (я думаю) к трем решениям:

  1. Сортируйте правила, прежде чем передавать их в оценщик.
  2. Измените тип параметра на что-то, обеспечивающее порядок сортировки.
  3. Сортировка в оценщике.

Мне нравится вариант 3, потому что он всегда обеспечивает сортировку, и мне нравится вариант 1, потому что он кажется более сплоченным. И вариант 2 кажется хорошим компромиссом.

Является ли сценарий, подобный этому контексту, специфическим / субъективным, или здесь действительно есть лучшая практика?

3 ответа

Решение

Я думаю, что это больше похоже на нарушение закона Деметры и инкапсуляции. Выражение EvaluateExpression выглядит так, как будто оно принадлежит правилам. Учти это:

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

public interface IRule {
    object EvaluateExpression();
}

Таким образом, вам не нужно выставлять внутренние правила, такие как Exp или Result.

И да, если вы хотите, чтобы правила оценивались в порядке приоритета, убедитесь, что они отсортированы. Правило ответственности состоит в том, чтобы оценивать себя, в то время как вызывающий абонент решает, в каком порядке их оценивать.

В таком сценарии я бы сделал что-то вроде:

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

}

Вы можете сделать это абстрактным классом или какой-то функциональностью, которую агрегируют другие классы.

Мой голос был бы за вариант 3. Чтобы минимизировать связывание, вы должны убедиться, что вы не делаете слишком много предположений о данных, отправляемых в функцию.

Если другой класс будет использовать это позднее, вы предполагаете, что они знают, как передать их, отсортированные по приоритету?

Другие вопросы по тегам