Это нарушение принципа единой ответственности?
-
06-07-2019 - |
Вопрос
У меня есть следующий метод и интерфейс:
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;
}
Поскольку правила имеют приоритет, они фактически никогда не должны обрабатываться не по порядку. Это приводит меня (я думаю) к трем решениям:
<Ол>Мне нравится вариант 3, потому что он всегда обеспечивает сортировку, и мне нравится вариант 1, потому что он кажется более сплоченным. И вариант 2 кажется хорошим компромиссом.
Является ли сценарий, подобный этому контексту, специфическим / субъективным, или действительно есть лучшая практика, которую следует применять здесь?
Решение
Я думаю, что это больше похоже на нарушение закона Деметры и инкапсуляции. Выражение EvaluateExpression выглядит так, как будто оно принадлежит правилам. Учтите это:
public object ProcessRules(List<IRule> rules) {
foreach(IRule rule in rules) {
return rule.EvaluateExpression();
}
}
public interface IRule {
object EvaluateExpression();
}
Таким образом, вам не нужно раскрывать внутренние правила, такие как Exp или Result.
И да, если вы хотите, чтобы правила оценивались в порядке приоритета, убедитесь, что они отсортированы. Правило несет ответственность за оценку самого себя, в то время как вызывающий абонент решает, в каком порядке их оценивать.
Другие советы
Мой голос был бы за вариант 3. Чтобы минимизировать связывание, вы должны убедиться, что вы не делаете слишком много предположений о данных, отправляемых в функцию.
Если другой класс воспользуется этим позже, вы предполагаете, что они знают, что они прошли сортировку по приоритету? Р>
В подобном сценарии я бы сделал что-то вроде:
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);
}
}
Вы можете сделать это абстрактным классом или какой-либо функциональностью, объединяющей другие классы.