Относится ли "скажи, не спрашивай" к проверке пользовательского ввода?

Я почему-то все эти годы игнорировал принцип ООП "говори, не спрашивай", потому что я впервые узнал об этом пару дней назад.

Но контекстом было обсуждение кода проверки, который был перемещен со страницы веб-формы ASP.NET в объект данных / бизнес, и не было никакого метода "Validate()", это был только метод сохранения, который сам выполнял проверку и (предположительно) поднял исключение. Я спросил, почему это было разработано таким образом, и я был направлен на принцип ООП "говори, не спрашивай", о котором я никогда не слышал, поэтому мы вместе посмотрели на Google, и я сразу получил образование.;)

Тем не менее, что-то пахнет неправильно, не следует ли очищать данные до того, как они будут переданы от пользователя в бизнес-уровень, где они обрабатываются и / или собираются, а не наоборот? Я запутался в том, как это способствует хорошему дизайну.

Кажется, что правило "говори, не спрашивай" относится к идее, что вы не должны спрашивать целевой объект о состоянии целевого объекта, и что этот принцип никогда не предназначался для применения к данным, передаваемым в целевой объект

3 ответа

Решение

Я согласен с AviewAview, но выкину исключения, только если пользователь скажет (не если он попросит):

public Foo
{
  bool Validate(Baz bar)
  {
        if(!is_number(bar)) return false;
        return true;
  }

  AssignBar(Baz bar)
  {
        if (!Validate(bar)) throw numberexception();
  }
}

Расскажи:

try
{
  foo.AssignBar(bar);
}
catch(numberexception e)
{
  alert('Not a number!');
}

Просить:

if (foo.Validate(bar)
{
  foo.AssignBar(bar);
}
else
{
  alert('Not a number!');
}

Поэтому AssignBar ожидает строку VALID и выдает исключение, если это не так, но мы также предоставляем метод Validate, который не генерирует исключение.

Я подумал, что это звучит так, как будто "Лучшие практики" и "Методологии проектирования" пошли не так, но теперь это для меня имеет смысл. Рассмотрим этот вариант:

Представьте себе, что валидация выполняется в бизнес-объекте, но "что мне делать, если валидация не проходит" на уровне представления. Это позволило бы нескольким различным уровням представления повторно использовать одну и ту же логику проверки, но обрабатывать ошибки по-разному.

public Foo
{
  Validate(Baz bar)
  {
      if(!is_number(bar)) throw numberexception();
  }

  AssignBar(Baz bar)
  {
      Validate(bar);
  }
}


//...

try
{
  foo.AssignBar(bar);
}
catch(numberexception e)
{
  alert('Not a number!');
}

nb вы можете спорить все, что вы хотите о создании исключений, это было задумано как пример. Верните состояния, bools, все, что вы хотите.

Интересно, является ли это скорее вопросом "разделения интересов", чем "говорите, не спрашивайте". Кто несет ответственность за проверку данных? Возможно, именно эта вещь ответственна за сохранение этого.

Конечно, иногда полезно проверить данные в несколько слоев. Если это относится к вашему приложению, у меня нет проблем с отображением логики проверки на уровне "пользователя". Но я все еще хотел бы это на деловом уровне.

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