Я долго думал об этой проблеме, и мне было бы интересно узнать мнение других разработчиков.
Я склонен придерживаться очень оборонительного стиля программирования. Мой типичный блок или метод выглядит так:
T foo(par1, par2, par3, ...)
{
// Check that all parameters are correct, return undefined (null)
// or throw exception if this is not the case.
// Compute and (possibly) return result.
}
Кроме того, во время вычислений я проверяю все указатели перед разыменованием их. Моя идея состоит в том, что, если есть какая-то ошибка и где-то должен появиться указатель NULL, моя программа должна хорошо это обработать и просто отказаться от продолжения вычислений. Конечно, он может уведомить о проблеме с сообщением об ошибке в журнале или каким-либо другим механизмом.
Чтобы выразить это более абстрактно, мой подход
if all input is OK --> compute result
else --> do not compute result, notify problem
Другие разработчики, в том числе некоторые мои коллеги, используют другую стратегию. Например, они не проверяют указатели. Они предполагают, что часть кода должна быть правильно введена, и она не должна нести ответственность за то, что происходит, если ввод неправильный. Кроме того, если исключение NULL-указателя приводит к сбою программы, ошибка будет обнаружена легче во время тестирования и у нее больше шансов быть исправленной.
Мой ответ на это обычно: но что, если ошибка не обнаружена во время тестирования и появляется, когда продукт уже используется клиентом? Каков предпочтительный способ проявления ошибки? Должна ли это быть программа, которая не выполняет определенного действия, но все еще может продолжать работать, или программа, которая аварийно завершает работу и требует перезапуска?
Подведение итогов
Какой из двух подходов к обработке неправильного ввода вы бы посоветовали?
Inconsistent input --> no action + notification
или
Inconsistent input --> undefined behaviour or crash
редактировать
Спасибо за ответы и предложения. Я тоже фанат дизайна по контракту. Но даже если я доверяю человеку, который написал код, вызывающий мои методы (возможно, это я), все равно могут быть ошибки, приводящие к неправильному вводу. Поэтому мой подход заключается в том, чтобы никогда не предполагать, что метод передан корректно.
Кроме того, я бы использовал механизм, чтобы поймать проблему и уведомить об этом. В системе разработки, например, откроется диалоговое окно для уведомления пользователя. В производственной системе он просто записывает некоторую информацию в журнал. Я не думаю, что дополнительные проверки могут привести к проблемам с производительностью. Я не уверен, достаточно ли утверждений, если они отключены в производственной системе: возможно, возникнет какая-то ситуация в производстве, которая не возникла во время тестирования.
В любом случае, я был очень удивлен, что многие люди придерживаются противоположного подхода: они позволяют приложениям аварийно завершать работу «нарочно», поскольку утверждают, что это облегчит поиск ошибок во время тестирования.