Это нарушение принципа единой ответственности? - PullRequest
0 голосов
/ 13 сентября 2009

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

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 ]

4 голосов
/ 13 сентября 2009

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

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

public interface IRule {
    object EvaluateExpression();
}

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

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

0 голосов
/ 13 сентября 2009

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

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

}

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

0 голосов
/ 13 сентября 2009

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

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

...