Подтвердить что ты не робот

Обязательны ли предварительные условия ВСЕГДА?

В эти дни я привык проверять каждое предварительное условие для каждой функции, так как я получил привычку от курса программирования ОС обратно в uni.

С другой стороны, на курсе разработки программного обеспечения нас учили, что общее предварительное условие следует проверять только один раз, так, например, если функция делегирует другую функцию, первая функция должна их проверять, но проверять их снова в второй - избыточным.

Я вижу точку избыточности, но я уверен, что безопаснее всегда проверять их, плюс вам не нужно отслеживать, где они были проверены ранее.

Какая самая лучшая практика здесь?

4b9b3361

Ответ 1

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

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

Сэкономленное время может быть реинвестировано в тщательное усовершенствование модулей и интеграционных тестов, чтобы попытаться устранить эти проблемы и поставить инструменты на место, чтобы помочь обеспечить качество утверждений ввода, поскольку оно будет потребляться клиентом, независимо от того, класс под вашим контролем или нет.

Ответ 2

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

  • Проверить входные данные от конечных пользователей
  • Проверьте входы от программных компонентов, написанных другими командами.
  • Доверительные входы, полученные из вашего собственного компонента/внутри вашей собственной команды.

Причиной этого является поддержка и обслуживание (например, исправление ошибок): когда есть отчет об ошибке, вы хотите как можно быстрее узнать, какой компонент виноват, то есть какая команда назначит ошибку.

Ответ 3

если функция делегирует другую функции, первая функция должна проверьте их, но проверьте их снова второй - избыточным.

Что делать, если вы измените способ вызова этих функций друг другу? Или вы вводите новые требования к проверке во второй функции, которую первым делегирует? Я бы сказал, что безопаснее всегда их проверять.

Ответ 4

Я привык к различию между проверкой и утверждением предварительных условий, в зависимости (как указывали люди в комментариях) о том, приходит ли вызов извне (может быть, неконтролируемое исключение) или внутри (assert, shouldn 't бывает).

В идеале, система производства не будет штрафовать за утверждения, и вы могли бы даже использовать механизм "Дизайн по контракту" (TM), чтобы статически ставить свои утверждения.

Ответ 5

По моему опыту, это зависит от вашей инкапсуляции. Если внутренняя функция является частной, вы можете быть уверены, что ее предусловия установлены.

Угадайте все о Законе Деметры, поговорите только с вашими друзьями и т.д.

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

Ответ 6

Я думаю, что лучше всего делать эти проверки только в том случае, если они однажды потерпят неудачу. Если это поможет, выполните следующие действия.

Отладка

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

Однако, если вы откроете публичный API, в один прекрасный день кто-то не выполнит ваше предварительное условие. Чем дальше человек, который поддерживает вызывающий модуль от вас (в организационной структуре и в физическом местоположении), тем вероятнее, что это произойдет. И когда это произойдет, четкое выражение о неудаче предварительного условия со спецификацией, где это произошло, может сэкономить часы отладки. Закон мертвых абстракций по-прежнему верен...

QA

Сбой предварительного условия помогает QA отлаживать свои тесты. Если unit тест для модуля приводит к тому, что модуль выполняет предисловие, это означает, что тест неверен, а не ваш код. (Или, что ваша проверка предварительного условия неверна, но это менее вероятно).

Если одним из способов выполнения QA является статический анализ, то также будут проверяться предварительные условия, если они имеют определенную нотацию (например, только эти проверки используют макрос assert_precondition). В статическом анализе очень важно различать неправильные ошибки ввода и исходного кода.

Documentation

Если у вас не так много времени для создания документации, вы можете сделать код полезным для текста, который сопровождает его. Четкие и видимые предварительные проверки, которые воспринимаются отдельно от остальной части реализации, "документируют" возможные вложения в некоторой степени. (Другой способ документировать ваш код таким образом - писать модульные тесты).

Ответ 7

Как и во всем, оцените свои требования, чтобы найти оптимальное решение для каждой ситуации.

Если предварительные условия легче проверить ( "указатель не является нулевым" ), вы также можете это делать часто. Предварительные условия, которые трудно проверить ( "указывает на допустимую строку с нулевым завершением" ) или являются дорогостоящими по времени, памяти или другим ресурсам, могут обрабатываться по-другому. Используйте принцип Парето и собирайте низко висящие фрукты.

// C, C++:
void example(char const* s) {
  // precondition: s points to a valid null-terminated string
  assert(s); // tests that s is non-null, which is required for it to point to
  // a valid null-terminated string.  the real test is nearly impossible from
  // within this function
}

Гарантирование предусловий является обязанностью вызывающего. Из-за этого на нескольких языках предлагается конструкция "assert", которая может быть необязательно пропущена (например, определение NDEBUG для C/С++, командной строки для Python), чтобы вы могли более активно тестировать предварительные условия в специальных сборках, не влияя на конечную производительность. Однако, как использовать assert, может быть жаркая дискуссия, опять же, выяснить ваши требования и быть последовательными.

Ответ 8

Это немного старый вопрос, но нет, предварительные условия не нужно проверять каждый раз. Это действительно зависит.

Например, что, если у вас есть бинарный поиск по вектору. Предварительное условие сортируется по вектору. Теперь, если вы проверяете каждый раз, если вектор отсортирован, это занимает линейное время (для каждого вектора), поэтому оно неэффективно. Клиент должен знать о предварительном условии и быть уверенным в его соблюдении.

Ответ 9

Лучшая практика - всегда проверять их.