Основы объектно-ориентированного программирования
Шрифт:
Предполагается, что включающий класс имеет булев атрибут integer_was_read.
Вызывающая программа должна использовать эту программу следующим образом, пытаясь введенное целое присвоить сущности n:
Восстановление при исключениях, сгенерированных операционной системой
Среди событий, включающих исключения, есть сигналы, посылаемые операционной системой, некоторые из которых являются следствием аппаратных прерываний. Примеры: арифметическое переполнение сверху и снизу, невозможные операции ввода-вывода, запрещенные команды, обращение к недоступной памяти, прерывания от пользователя (например, нажата клавиша break).
Теоретически можно рассматривать такие условия, как нарушение утверждений. Если a+b приводит к переполнению, то это означает, что вызов не удовлетворяет неявному предусловию функции + для целых или вещественных чисел, устанавливающее, что сумма двух чисел должна быть представима в компьютере. Подобное неявное предусловие задается при создании новых объектов (создание копии) - памяти должно быть достаточно. Отказы встречаются из-за того, что окружение - файлы, устройства, пользователи - не отвечают условиям применимости. Но в таких случаях непрактично или невозможно задавать утверждения, допуская их независимую проверку. Единственное решение - пытаться выполнить операцию, и, если аппаратура или операционная система выдает сигнал о ненормальном состоянии, рассматривать его как исключение.
Рассмотрим проблему написания функции quasi_inverse, возвращающей для каждого вещественного x обратную величину 1/x или 0, если x слишком мало.
Подобные задачи по существу нельзя реализовать, не используя механизм исключений. Единственный практичный способ узнать, можно ли для данного x получить обратную величину, это выполнить деление. Но деление может спровоцировать переполнение, и если нет механизма управления исключениями, то программа завершится отказом, и будет слишком поздно возвращать 0 в качестве результата.
| На некоторых платформах можно написать функцию invertible, такую что invertible(x) равна true, если и только если обратная величина может быть вычислена. Тогда можно написать и quasi_inverse. Но это решение не будет переносимым, и может приводить к потере производительности при интенсивном использовании этой функции. |
Механизм rescue-retry позволяет просто решить эту проблему, по крайней мере, на платформе, включающей сигнал при арифметическом переполнении:
Правила инициализации устанавливают значение false для division_tried в начале каждого вызова. В теле не нужно предложение else, поскольку инициализация установит Result равным 0.
Повторение программы, толерантной к неисправностям
Предположим, вы написали текстовый редактор, и к вашему стыду нет уверенности, что он полностью свободен от жучков. Но вам хочется передать эту версию некоторым пользователям для получения обратной связи. Нашлись смельчаки, готовые принять систему с оставшимися ошибками, понимая, что могут возникать ситуации, когда их запросы не будут выполнены. Но они не будут тестировать ваш редактор на серьезных текстах, (а именно это вам и требуется), если будут бояться, что отказы могут привести к катастрофе, например грубый выход с потерей текста, над которым шла работа последние полчаса. Используя механизм повторения, можно обеспечить защиту от такого поведения.
Предположим, что редактор, как это обычно бывает для подобных систем, содержит основной цикл, выполняющий команды редактора:
где тело программы execute_one_command имеет вид:
Инструкция "Выполнить ..." выбирает нужную программу (например, удалить строку, заменить слово и так далее). Мы увидим в последующих лекциях, как техника наследования и динамическое связывание дает простые, элегантные структуры для подобных ветвящихся решений.
Будем исходить из того, что не все эти программы являются безопасными. Некоторые из них могут отказать в непредсказуемое время. Вы можете обеспечить примитивную, но эффективную защиту против таких событий, написав программу следующим образом:
Эта схема предполагает на практике, что поддерживаемые запросы пользователя включают: "сохранить текущее состояние работы", "завершить работу". Оба последних запроса должны работать корректно. Пользователь, получивший сообщение "Извините...", несомненно, захочет сохранить работу и выйти как можно скорее. Некоторые из программ, реализующих команды редактора, могут иметь собственные предложения rescue, хотя и приводящие к отказу, но предварительно выдающие более информативные сообщения.