В защитном программировании главная идея в том, что если методу передаются некорректные данные, то его работа не нарушится, даже если эти данные испорчены по вине другой программы (с. 182)
Программы необходимо защищать от мусорных данных следующим образом:
- проверять все данные из внешних источников,
- проверять значения входных параметров метода,
- решить, как будут обрабатываться неправильные данные.
Для проверки правильности работы программы (в том числе предположений программы о входных данных) обычно используются утверждения (assertions). Обычно утверждения используют при разработке и удаляют в production-версии.
- Используйте утверждения для событий, которые не должны происходить, и обработки ошибок (иключений) для ожидаемых неполадок
- Не помещайте выполняемый код в утверждение, лучше используйте в утверждении результат выполнения кода
- Используйте утверждения для документирования и проверки предусловий (обязательств кода перед методом, который он вызывает) и постусловий (обязательств метода или класс перед кодом, который их использует)
- Обрабатывайте ошибки даже после проверки увтерждений
Приём | Комментарий |
---|---|
Заменить следующим корректным блоком данных | Если вы считываете показание термометра 100 раз в секунду, можно без вреда для программы пропустить одно некорректное измерение |
Вернуть тот же результат, что и в предыдущий раз | В случае с термометром можно не только пропустить некорректное значение, но и заменить его предыдущим или средним |
Подставить ближайшее допустимое значение | Допустим, термометр измеряет температуру от 0 до 100 градусов: значения ниже нуля можно приравнять к 0, а выше 100 — к 100 |
Вернуть нейтральное значение | Метод для изменения цвета кнопки может устанавливать цвет по-умолчанию, если получил некорректное значение, и сообщать об ошибке через журнал или интерфейс программы |
Вернуть код ошибки | Вы можете решить, что метод должен лишь сообщать об ошибке (вернуть определённый код, выбросить исключение и так далее), а обрабатываться ошибка будет на более высоком уровне иерархии вызовов |
Вызвать обработчик ошибок | Вы можете решить, что все ошибки будут обрабатываться одним глобальным объектом и делегировать всю обработку ошибок ему |
Приостановить выполнение | Если сбой произошёл в ПО рентгеновского аппарата, наилучшим способом обработать ошибку будет остановка выполнения программы |
Записать сообщение об ошибке в журнал | Этот способ скорее следует использовать в сочетании с другими, а не как самостоятельное решение |
Подходящий способ обработки ошибок зависит от приложения, в котором эта ошибка происходит. Выбирая способ, нужно решить, что для приложения важнее: корректность (лучше ничего не вернуть, чем вернуть неточное значение) или устойчивость (лучше вернуть неточное значение, чем приостановить работу программы). Приняв это решение, нужно придерживаться его во всей программе.
Выбор общего подхода к работе с некорректными данными — это вопрос архитектуры и высокоуровневого проектирования, и он должен быть рассмотрен на одном из этих этапов разработки системы. Выбрав подход придерживайтесь его неукоснительно (с. 192)
Исключения позволяют сигнализировать о возникающих ошибках или исключительных ситуациях.
Если код в некотором методе втречает неожиданную ситуацию и не знает, как её обработать, то он генерируется исключение, т.е. фактически умывает руки со словами: «Я не знаю, что с этим делать, надеюсь, кто-нибудь другой знает, как на это реагировать» (с. 193)
Принципы:
- Используйте исключения только для действительно исключительных ситуаций, для оповещения других частей программы об ошибках, которые нельзя игнорировать,
- Если ошибку можно обработать локально, так и сделайте,
- Избегайте использования исключений в конструкторах и деструкторах, если вы не перехватываете их позднее,
- Генерируемые исключение — это часть интерфейса, помните, что они должны быть согласованы с основной абстракцией класса,
- Убедитесь, что исключение содержит достаточно информации для понимания его причины,
- Избегайте пустых блоков
catch
, - Выясните, какие исключения генерируют используемые вами библиотеки,
- Рассмотрите вопрос о централизованном выводе информации об исключениях, в том числе с помощью готовых средств мониторинга, таких как APM (Elastic APM, Datadog APM, Sentry и так далее),
- Стандартизируйте использование исключений на проекте, что сохранять процесс интеллектуально управляемым.
Изоляция повреждений — это приём, суть которого заключаетсяв разделении кода на две части: одна часть кода работает с непроверенными данными, а другая — с проверенными. Входные данные необходимо проверять и приводить к нужной форме как можно раньше.
Если данные были проверены публичными методами класса, закрытые методы могут считать, что данные безопасны (с. 199)