Я думал, что добавлю еще четыре случая, когда Debug.Assert может быть правильным выбором.
1) Что-то, что я не видел, упоминалось здесь, это дополнительное концептуальное покрытие, которое Asserts может обеспечить во время автоматизированного тестирования . В качестве простого примера:
Когда автор вызова, который считает, что они расширили область действия кода для обработки дополнительных сценариев, изменяет некоторых вызывающих абонентов более высокого уровня, в идеале (!) Они будут писать модульные тесты, чтобы охватить это новое условие. Тогда может оказаться, что полностью интегрированный код работает нормально.
Однако на самом деле был выявлен тонкий дефект, но он не обнаружен в результатах испытаний. Вызываемый стал недетерминированным в этом случае, и только происходит чтобы обеспечить ожидаемый результат. Или, возможно, это привело к ошибке округления, которая была незамеченной. Или вызвал ошибку, которая была одинаково смещена в другом месте. Или предоставляется не только запрошенный доступ, но и дополнительные привилегии, которые не должны предоставляться. И т.п.
На этом этапе операторы Debug.Assert (), содержащиеся в вызываемом объекте, вместе с новым регистром (или граничным регистром), инициируемым модульными тестами, могут предоставить неоценимое уведомление во время теста о том, что исходные предположения автора были признаны недействительными, и код не должен быть выпущенным без дополнительного рассмотрения. Активы с юнит-тестами являются идеальными партнерами.
2) Кроме того, некоторые тесты просты в написании, но дорогостоящи и не нужны, учитывая первоначальные предположения . Например:
Если доступ к объекту возможен только из определенной защищенной точки входа, следует ли выполнить дополнительный запрос к базе данных сетевых прав из каждого метода объекта, чтобы убедиться, что у вызывающего пользователя есть разрешения? Конечно нет. Возможно, идеальное решение включает в себя кэширование или какое-то другое расширение функций, но дизайн не требует этого. Debug.Assert () немедленно покажет, когда объект был присоединен к небезопасной точке входа.
3) Далее, в некоторых случаях ваш продукт может не иметь полезного диагностического взаимодействия для всех или части его операций при развертывании в режиме выпуска . Например:
Предположим, это встроенное устройство реального времени. Бросать исключения и перезапускать при обнаружении некорректного пакета нецелесообразно. Вместо этого устройство может извлечь выгоду из работы с максимальным усилием, даже до точки рендеринга шума на его выходе. Он также может не иметь человеческого интерфейса, регистрирующего устройства или даже быть физически недоступным для человека вообще при развертывании в режиме выпуска, и понимание ошибок лучше всего обеспечить путем оценки того же результата. В этом случае либеральные утверждения и тщательное предварительное тестирование более ценны, чем исключения.
4) Наконец, некоторые тесты являются ненужными только потому, что вызываемый абонент воспринимается как чрезвычайно надежный . В большинстве случаев, чем больше повторного использования кода, тем больше усилий было приложено, чтобы сделать его надежным. Следовательно, для исключения характерны непредвиденные параметры от вызывающих абонентов, а для ожидаемых результатов от вызывающих - обычное явление. Например:
Если основная String.Find
операция заявляет, что она вернет, -1
когда критерии поиска не найдены, вы можете безопасно выполнить одну операцию, а не три. Однако, если это действительно вернулось -2
, у вас может не быть разумных действий. Было бы бесполезно заменять более простой расчет на тот, который проверяет отдельно -1
значение, и в большинстве сред выпуска нецелесообразно засорять ваш код тестами, гарантирующими, что основные библиотеки работают должным образом. В этом случае утверждения идеальны.