Закрытие против классов? - PullRequest
4 голосов
/ 13 июля 2010

У меня есть понятие «Правило», которое я хочу уметь обрабатывать.Поэтому я создал интерфейс ниже:

  public interface IRule<T>
  {
    Boolean IsSatisfiedBy(T value);
    String GetViolationMessage(T value);
  }

Я планировал создать серию классов «Правило» для представления различных правил, которые в настоящее время поддерживаются системой, таких как:

  public class MatchesPatternRule : IRule<String>
  {
    private readonly Regex _regex;
    private readonly String _pattern;

    public MatchesPatternRule(String pattern)
    {
      Verify.IsFalse(String.IsNullOrWhiteSpace(pattern));

      _regex = new Regex(pattern);
      _pattern = pattern;
    }

    public Boolean IsSatisfiedBy(String value)
    {
      return _regex.IsMatch(value);
    }

    public String GetViolationMessage(String value)
    {
      return String.Format(RuleMessage.MatchesPatternViolation, _pattern, value);
    }
  }

И тогда правила будут использоваться различными методами расширения, такими как:

public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern)
{
  context.AddRule(new MatchesPatternRule(pattern));
  return context;
}

Однако в настоящее время у меня есть планы на 20+ правил, и класс MatchesPatternRule можно легко заменить, написав метод расширения.как:

public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern)
  where T : IComparable
{
  Verify.IsFalse(String.IsNullOrWhiteSpace(pattern));

  Regex regex = new Regex(pattern);
  context.AddRule(value => regex.IsMatch(value), value => String.Format(RuleMessage.MatchesPatternViolation, _pattern, value));
  return context;
}

Интересно, какой подход лучше и почему?Оба легко тестируемы и в конечном итоге достигают конечного результата.Любое понимание будет с благодарностью!

ОБНОВЛЕНИЕ

Основываясь на отзывах Тома, я думаю, что я выбрал подход среднего уровня.Я собираюсь создать статический класс для хранения методов расширения для каждого «правила».Это гарантирует, что любое данное правило легко найти, и будет держать мой код организованным, а также уменьшит общий объем кода.

  public static class MatchesPatternRule
  {
    public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern)
    {
      return MatchesPattern<T>(context, pattern, pattern, RegexOptions.None);
    }

    public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, String friendlyPattern)
    {
      return MatchesPattern<T>(context, pattern, friendlyPattern, RegexOptions.None);
    }

    public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, RegexOptions options)
    {
      return MatchesPattern<T>(context, pattern, pattern, options);
    }

    public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, String friendlyPattern, RegexOptions options)
    {
      Verify.IsFalse(String.IsNullOrWhiteSpace(pattern));

      Regex regex = new Regex(pattern);
      context.AddRule(value => regex.IsMatch(value), value => String.Format(RuleMessage.MatchesPatternViolation, _pattern, value));

      return context;
    }
  }

Ответы [ 2 ]

1 голос
/ 13 июля 2010

Почему вы не можете иметь оба? Для простых правил вы можете использовать замыкания. ValidationContext.AddRule может преобразовать ваши замыкания в правила. Или, возможно, метод расширения, который преобразует замыкание в правило.

1 голос
/ 13 июля 2010

Я не пользователь C #, но в Ruby и Scala у кого-то есть похожие варианты.Наличие класса, который привязывается к определенному интерфейсу в чем-то подобном этому контексту, похоже, имеет аналогичное применение в качестве замыкания, хотя и с немного большим количеством шаблонов.Поскольку технически они преследуют одну и ту же цель, то, несомненно, возникает вопрос, какой из них лучше всего подходит для контекста.

Являются ли люди, которые должны писать эти правила, достаточно умными, чтобы обойти замыкания?Если нет, лучше использовать решение на основе классов.Если я надену свою шляпку Java-программиста, пытающуюся понять все это-C #, решение на основе классов может оказаться немного проще, чем изучение всех этих странных функциональных вещей - я знаю странные функциональные вещи, но я могу представить себя не зная это!Только вы можете решить, что лучше для людей, которые будут писать правила.Если вы единственный человек, которому приходится писать правила, сходите с ума!Выберите то, что вы предпочитаете эстетически.

Как насчет документации и метаданных?Будущая расширяемость?Что если вам нужно добавить дополнительные поля в правила?Легче ли документировать решение на основе классов, а не решение на основе замыканий?Если вам нужно найти и изменить правило, какое из них будет проще сделать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...