Исключения, как правило, должны быть для исключительных случаев, а не для обработки чего-то, что обычно может происходить во время нормального выполнения вашей программы. Для этого есть много веских причин - вот некоторые, с которыми я довольно часто сталкиваюсь:
- Проблемы с производительностью. Исключениями являются, как правило, довольно дорогие операции - если их регулярно генерировать, ваша производительность может пострадать.
- Работа с неисследованными исключениями проверки - в случае, если вам случится использовать свой код, не имея дело с исключением, вы увидите ошибку проверки до «желтого экрана» или обработчика сбоя - вероятно, не самый лучший пользовательский опыт.
- Исключения не структурированы таким образом, чтобы обеспечить хорошую информацию для пользователя. Взгляните на класс исключений - там не так много настроек, обеспечивающих хорошую информацию для пользователя, то, что вам понадобится для передачи информации обратно пользователю. Каждый раз, когда я пытался использовать исключения таким образом, я получал целый ряд подклассов со свойствами, которые не имеют особого смысла в принадлежности к исключению.
Один из подходов, который мне обычно нравится использовать, - это предоставить открытый метод Validate, который возвращает список ошибок (но никогда не генерирует само исключение), а затем метод Save, который вызывает Validate () и выдает исключение, если есть какие-либо ошибки. Вы переключаете поведение с «throw, если модель недействительна» на «throw, если код пытается сохранить, пока модель находится в недопустимом состоянии».
Чтобы ответить на комментарий ниже относительно производительности бросков в Validate vs. Save - бросок в Save () будет иметь точно такое же снижение производительности как и бросок в Validate (). Однако ключевое отличие состоит в том, что этого никогда не должно происходить - вы защищаетесь от того, что разработчик неправильно использует ваши классы, а не использует исключения в качестве метода проверки. Правильно написанный код, вызывающий метод save, должен выглядеть примерно так:
ValidationResult result = obj.Validate();
if (result.IsValid) {
obj.Save();
} else {
// display errors to the user
}
Исключение выдается, только если разработчик забыл проверить состояние проверки перед сохранением. Это имеет то преимущество, что позволяет проводить проверку без использования исключений, а также защищать базу данных, не позволяя сохранять недействительные объекты. В идеале вы бы вообще не уловили исключение в контроллере и позволили бы с ним справиться в общих процедурах обработки ошибок, поскольку проблема больше не в пользовательском вводе, а в ошибке разработчика.