Основы объектно-ориентированного программирования
Шрифт:
По этой причине я пытался в моей собственной работе избегать детального разбора случаев причины исключений, стараясь показать, что обработка исключений лишь фиксирует ситуацию, если может, а затем либо fail, либо retry.
Этот стиль, вероятно, слишком строг, и некоторые разработчики предпочитают менее ограниченную схему, используя в полной мере механизм запросов класса EXCEPTIONS, позволяющий в тоже время оставаться дисциплинированным. Если вы хотите придерживаться такой схемы, то в классе EXCEPTIONS найдете все, что для этого нужно. Но всегда помните о следующем принципе:
Принцип Простоты Исключения
Вся обработка, выполняемая в предложении rescue, должна оставаться простой и фокусироваться на единственной цели - возвратить объект получателя в стабильное состояние, допуская повторение, если это возможно.
Исключения разработчика
Все исключения, изучаемые до сих пор, были результатом событий внешних по отношению к ПО (сигналы операционной системы) или принудительных следствий его работы (нарушение утверждений). В некоторых приложениях полезно, чтобы исключения возникали по воле разработчика в определенных ситуациях.
Такие исключения называются исключениями разработчика. Они характеризуются как целочисленным кодом, отличающимся от системных кодов, так и именем (строкой), которые могут быть использованы, например, в сообщениях об ошибке. Можно использовать следующие свойства для возбуждения исключения разработчика и для анализа его свойств в предложении rescue.
Иногда полезно связать с исключением разработчика контекст - произвольный объект, структура которого может быть полезной при обработке исключения разработчика:
Эти свойства позволяют использовать стиль программирования, в котором обработка исключений представляет часть общего процесса работы с программными элементами. Авторы одного из трансляторов при разборе текстов предпочитали выбрасывать исключения при появлении особых случаев, после чего вызывать для их анализа специальные программы. Это не мой стиль работы, но по сути, ничего ошибочного в нем нет, так что механизм исключений разработчика для тех, кому нравится так работать.
Обсуждение
Мы закончили проектирование механизма исключений, совместимого с применяемым ОО-подходом, и следующего идеям Проектирования по Контракту. Благодаря инструкции retry, механизм получился более мощным, чем во многих языках программирования. В то же время он может казаться более строгим из-за акцента на сдержанность при определении точных причин исключения.
Давайте рассмотрим несколько альтернативных идей проектирования, которым можно было бы следовать, и обсудим, почему они были опущены.
Дисциплинированные исключения
Исключения, как они были введены, дают способ справиться с аномалиями, возникающими в процессе выполнения: нарушениями утверждений, сигналами аппаратуры, попытками получить доступ к void ссылкам.
Исследуемый нами подход основан на метафоре контракта, - ни при каких обстоятельствах программа не должна претендовать на успешность, когда фактически имеет место отказ в достижении цели. Программа может быть либо успешной (возможно, после исправления ситуации и нескольких попыток retry), либо приводить к отказу.
Исключения в языках Ada, CLU, PL/1 не следуют этой модели. В языке Ada ее инструкция
прервет выполнение программы и возвратит управление вызывающей программе, которая может обработать исключение в специальном обработчике, или вернет управление на уровень выше. Но здесь нет правила, ограничивающего действия обработчика. Следовательно, полностью возможно игнорировать исключение или вернуть альтернативный результат. Это объясняет, почему некоторые разработчики смотрят на механизм исключений просто как на средство обработки специальных случаев, не включенных в основной алгоритм. Такие приложения исключения рассматривают фактически raise как goto, что, очевидно, опасно, так как позволяет передавать управление за границы программы. По моему мнению, они злоупотребляют механизмом.
Традиционно есть две точки зрения на исключения. Первая признает исключения необходимым свойством. Она присуща большинству практикующих программистов, знающих как важно сохранить управление во время выполнения программы при возникновении ненормальных условий - аппаратных или программных ошибок. Вторая точка зрения присуща ученым, озабоченным корректностью и систематическим конструированием программ. Они с подозрением относятся к исключениям, рассматривая их как нечто нечистое, старающееся обойти стандартные правила управления программными структурами. Надеюсь, выше разработанный механизм способен примирить обе стороны.
Должны ли исключения быть объектами?
Фанатики объектной ориентации (многие ли из тех, кто открыл красоту этого подхода, не рискуют стать его фанатиками?) могут критиковать представленный механизм за то, что исключения не являются гражданами первого сорта в программном сообществе. Почему исключения не являются объектами?
В ОО-расширении Pascal в среде Delphi исключения действительно представлены объектами.
Не очень понятны преимущества такого решения. Некоторое обоснование можно будет найти в лекции 4 курса "Основы объектно-ориентированного проектирования", посвященной ответу на вопрос, каким должен быть класс. Объект является экземпляром абстрактно определенного типа данных, характеризуемого его компонентами. Исключение, конечно, как мы видели в классе EXCEPTIONS, имеет компоненты, заданные целочисленным кодом, текстовым сообщением. Но эти компоненты являются запросами, в то время, как истинные объекты имеют команды, изменяющие состояние объекта. Исключения не находятся под управлением программной системы; они результат событий, находящихся вне пределов ее достижимости.