При включенном мониторинге пока утверждения выполняются никакого видимого эффекта на процесс вычислений они не оказывают, если не считать затрат процессорного времени. Но если одно из утверждений принимает значение
Failure: object: O2 class: YOUR_CLASS routine: your_routine
Cause: precondition violation, clause: not_too_small
Called by: object: O2 class: YOUR_CLASS routine: his_routine
Called by: object: O1 class: HER_CLASS routine: her_routine
...
Это дает нам цепочку вызовов, начинающуюся программой, вызвавшей исключение, с указанием всех объектов и их классов - клиентов, в конечном счете, вызвавших эту программу. Показанная здесь форма является только наброском; обсуждение исключений в следующей лекции даст более полный пример таблицы истории исключения.
Возможные метки, допускаемые в утверждениях, такие как
your_routine (x: INTEGER) is
require
not_too_small: x >= Minimum_value
...
перечисляются при трассировке исключения, что помогает идентифицировать, что же именно пошло не так.
Каков оптимальный уровень мониторинга?
Какой уровень трассировки следует включать? Ответ вырабатывается в результате компромисса, с учетом следующих факторов: уровня доверия к корректности ПО, насколько критичны потери эффективности, насколько серьезны последствия не обнаруженных ошибок в период выполнения.
В экстремальных ситуациях все ясно:
[x]. При тестировании системы или очередной ее версии следует включать на самом высоком уровне мониторинг классов (для используемых библиотек это не обязательно). Эта возможность - один из принципиальных вкладов метода, представленного в этой книге. Мало кто из людей осознавал мощь этих идей, и как основательно они влияют на практику разработки ПО. Перелом наступил, когда фактически был получен опыт тестирования больших систем с утверждениями, включающих механизм мониторинга, описанный в этом разделе.
[x]. Для системы с полной степенью доверия в приложениях, критичных по времени выполнения, где каждая микросекунда на счету, - следует полностью удалять мониторинг.
Последний совет парадоксален, при отсутствии формальных доказательств корректности говорить о "полной степени доверия" вряд ли возможно. Стоит привести красноречивое высказывание C. A. Hoare:
| Абсурдно выполнять проверку в период отладки, когда не требуется доверие к получаемым результатам, и отключать ее в рабочем состоянии, когда ошибочный результат может стоить дорого или вообще катастрофичен. Что бы вы подумали о любителе плавания, который надевает спас-жилет во время тренировок на берегу и снимает его, бросаясь в море [Hoare 1973]. |
Интересную возможность дает параметр, включающий проверку предусловий. В рабочем режиме, когда отладка завершена и даны гарантии качества, крайне важно избежать катастроф в результате необнаруженных вызовов программ вне области их применения. Эта проверка обходится намного дешевле, чем проверка постусловий и инвариантов. Инварианты, в частности, особенно дороги, поскольку они проверяются на входе и выходе каждого квалифицированного вызова, и, что более важно, они всегда сложны, поскольку включают условия согласованности компонент класса.
Проверка предусловий - это параметр, устанавливаемый по умолчанию в Ace файле. Его появление в примере не было необходимым.
Этот параметр особенно интересен для библиотек. Вспомните, о чем говорит основное правило нарушения утверждений. За ошибку выполнения предусловия отвечает клиент. Если вы используете повторно используемые библиотеки, предположительно высокого качества, то обычно мониторинг их постусловий и инвариантов нежелателен, хотя ошибки в библиотеках, конечно, возможны, но априорно ошибки в клиентском ПО более вероятны. Но даже для совершенных во всех отношениях библиотек следует включать проверку предусловий с единственной целью - найти ошибки клиентов.