Это нарушение принципа единой ответственности?
У меня есть следующий метод и интерфейс:
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 кажется хорошим компромиссом.
Является ли сценарий, подобный этому контексту, специфическим / субъективным, или здесь действительно есть лучшая практика?
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. Чтобы минимизировать связывание, вы должны убедиться, что вы не делаете слишком много предположений о данных, отправляемых в функцию.
Если другой класс будет использовать это позднее, вы предполагаете, что они знают, как передать их, отсортированные по приоритету?