Пользователи часто неправильно вводят пароли, это не исключительный случай.
Да и нет. Выбрасывать ли исключение или нет, зависит от вопроса, который вы задаете. И во время входа пользователя в систему, как правило, возникает довольно много вопросов, прежде чем вы придете к выводу, может ли пользователь войти в систему или нет. Чем больше вы разбиваете код на специализированные части, тем больше может иметь смысл выдавать исключения в некоторых из этих частей.
Допустим, вы задали процедуру входа следующим образом в контексте HTTP:
- Получить имя пользователя * и пароль * из запроса.
- Получить запись пользователя * по имени пользователя из базы данных *.
- Проверьте, равен ли пароль записи * введенному паролю.
- Если да, начать сеанс.
- Если какой-либо из вышеперечисленных шагов не завершился успешно, выведите соответствующее сообщение об ошибке.
Любой из предметов, отмеченных звездочкой выше , может потерпеть неудачу :
- Запрос не может содержать имя пользователя или пароль.
- Возможно, для этого имени пользователя нет записи пользователя или база данных не работает.
- По какой-то причине запись может не иметь пароля и / или быть повреждена. По любой причине сохраненный пароль может использовать неподдерживаемый алгоритм хеширования и, следовательно, не может сравниваться.
Должно быть довольно очевидно, что в этом процессе есть любое количество случаев, которые идеально подходят для реализации в качестве исключения. Реальная функция, которая проверяет пароль, вероятно, должна , а не выдавать исключение в случае, если пароль просто ложный; это должно быть логическое возвращаемое значение. Но это все еще может вызвать исключение по любой другой причине. Если вы правильно используете исключения, вы получите код, который выглядит примерно так (псевдопсевдокод):
try {
username = request.get('username')
password = request.get('password')
user = db.get(username=username)
if (user.password.matches(password)) {
session.start()
} else {
print 'Nope, try again'
}
} catch (RequestDoesNotHaveThisDataException) {
logger.info('Invalid request')
response.status(400)
} catch (UserRecordNotFoundException) {
print 'Nope, try again'
} catch (UnsupportedHashingAlgorithmException, PasswordIsNullException) {
logger.error('Invalid password hash for user ' + user.id)
response.status(500)
print 'Sorry, please contact our support staff'
} catch (DatabaseDownException e) {
// mostly for illustration purposes,
// this exception should probably not even be caught here
logger.exception('SEND HALP!')
throw e
}
Так что, да, это очень простой процесс, но буквально на каждом шагу пути есть один или несколько исключительных случаев . Вы задаете вопрос «какое имя пользователя отправил пользователь в запросе?» , и если на этот вопрос нет ответа, поскольку пользователь не отправил имя пользователя, у вас исключительный случай. Исключения здесь значительно упрощают поток управления, в отличие от попытки охватить каждый из этих случаев if..else
.
Это НЕ исключение, если имя пользователя неверно или пароль неверен.
(из ответа, который вы цитируете.)
Как видите, мы проверяем, является ли имя пользователя «действительным» или нет, пытаясь извлечь его запись из базы данных. Если у нас есть функция, целью которой является получение записей о пользователях из базы данных, а таких записей нет, то исключением является полностью допустимый ответ. Если мы определили эту функцию для проверки , существует ли такая запись, и null
или false
является допустимым возвращаемым значением ... отлично. Но в этом случае мы не писали это так, и, честно говоря, это приводит к более простому потоку управления, который я нахожу.
Теперь, только сама проверка пароля не использует исключение, поскольку задаваемый вопрос: "соответствует ли этот пароль этому паролю?" , на что ответ может однозначно быть да или нет . Опять же, только если появится что-то исключительное, например, неподдерживаемый алгоритм хеширования, не может быть ответа на этот вопрос, и исключение полностью оправдано.
Сказав все это, вы можете заметить, что большинство этих случаев, за исключением действительно фатального с базой данных, внешне не приводит к исключению.Компонент здесь ожидает и обрабатывает определенные случаи, которые его подкомпоненты считают исключительными.Этот код здесь задает вопросы и готов обработать Mu в качестве ответа на некоторые из них.То есть общее правило, гласящее, что «исключения не должны использоваться в процессе X, Y или Z, потому что оно не является достаточно исключительным», слишком догматично.От цели каждого отдельного фрагмента кода зависит, является ли исключение оправданным или нет.
Сказав все это, вы спрашиваете о какой-то проверке формы.Приведенный выше код демонстрирует случай, когда два фрагмента данных могут быть недействительными, и в нем используются исключения, которые в конце все равно приводят к ответу «да» или «нет».Вы, конечно, можете заключить это в объект, подобный следующему:
val = new LoginFormValidator()
val.setDataFromRequest(request)
val.validate()
if (val.isValid) {
print 'Hurray'
} else {
print 'You have errors:'
for (error in val.errors) {
print error.fieldName + ': ' + error.reason
}
}
Независимо от того, использует ли этот валидатор внутренние исключения, вам не нужно заботиться об этом, но в конце он сохраняет их все как "Да "или" Нет "результат его внутренних свойств, откуда вы можете взять их в виде совокупности (val.isValid
) или по отдельности (for (error in val.errors)
).