|
Программирование >> Полиморфизм без виртуальных функций в с++
оставлять флаги в глобальных переменных и т.д. Как ни странно, на практике это редко становилось проблемой. Однако исключения дают общее решение: FilePtr::FilePtr(const char* n, const char* a) { if ((p = fopen(n,a)) == 0) { 0Й! файл не открылся throw Open failed(n,a); Механизм же обработки исключений в С++ гарантирует, что частично сконструированные объекты корректно уничтожаются, то есть полностью сконструированные подобъекты разрушаются, а те подобъекты, которые остались нескон-струированными, - нет. Это позволяет автору конструктора сосредоточиться на обработке ошибки в том объекте, в котором она обнаружена. Подробнее см. [2nd, §9.4.1]. 16.6. Возобновление или завершение? При проектировании механизма обработки исключений наиболее спорным оказался вопрос, следует ли поддержать семантику возобновления или прекращения исполнения. Иными словами, может ли обработчик исключения потребовать возобновления исполнения с того момента, где было возбуждено исключение? Например, было бы хорошо, если бы подпрограмма, вызванная для обработки ошибки нехватки памяти, могла найти дополнительную память и вернуть управление? Или если бы подпрограмма, вызванная для обработки деления на нуль, вернула некоторое определенное пользователем значение? А если бы подпрограмма, вызванная потому, что в дисководе нет гибкого диска, могла попросить пользователя вставить диск, а затем продолжила выполнение? Поначалу я думал так: Почему бы и нет? Ведь сразу видно несколько ситуаций, в которых я мог бы воспользоваться возобновлением . Но в последующие четыре года моя точка зрения некоторым образом изменилась, и потому механизм обработки исключений в языке С++ поддерживает так называемую модель с завершением. Главные споры по поводу возобновления и завершения разгорелись в комитете ANSI С++. Вопрос обсуждался и на заседаниях всего комитета, и в рабочей Фуппе по расширениям, и на вечерних технических обсуждениях, и в списках для рассылки по электронной почте. Споры продолжались с декабря 1989 г., когда был сформирован комитет ANSI С++, до ноября 1990 г. Тема вызвала большой интерес и у всего сообщества пользователей С++. В комитете семантику возобновления отстаивали преимущественно Мартин ОРиордан и Майк Миллер. Эндрю Кениг, Майк Вило, Тед Голдстейн, Дэг Брюк, Дмитрий Ленков и я высказывались за семантику завершения. Являясь председателем рабочей группы по расширениям, я направлял дискуссию. Результат был таков: 22 человека против одного за семантику завершения. Достичь результата удалось после долгого заседания, на котором представители компаний DEC, Sun, Texas 1п51гишеп18 и IBM демонстрировали экспериментальные данные. Затем последовало одобрение этого предложения на заседании всего комитета (4 человека из 30 против, остальные - за), в таком виде, то есть с семантикой завершения, оно и опубликовано в ARM. После длительных дебатов на встрече в Сиэтле, состоявшейся в июле 1990 г., я свел воедино все доводы в пользу семантики возобновления: □ более обший механизм (более мошный, включает и семантику завершения); □ унифицирует сходные концепции и реализации; □ необходим для очень сложных динамичных систем (например, для OS/2); □ ненамного более сложен и расточителен при реализации; □ если механизма, включающего семантику возобновления нет, его приходится имитировать; □ дает простое решение проблемы истошения ресурсов. Аналогично я обобщил доводы, высказанные в пользу семантики завершения: □ более простой, концептуально чистый и дешевый способ; □ позволяет строить системы, более легкие в управлении; □ обладает достаточной мощностью для решения любых задач; □ позволяет избежать неудачных или не очень законных программных приемов; □ противостоит негативному опыту, накопленному при работе с семантикой возобновления. В обоих перечнях намного упрощена суть споров, основательных и изобилующих техническими деталями. Иногда полемика носила весьма эмоциональный характер. Менее сдержанные участники кричали, что сторонники семантики завершения хотят навязать произвольные ограничения на приемы программирования. Очевидно, что вопрос о возобновлении и завершении затрагивает глубинные принципы проектирования программного обеспечения. Число сторонников той и другой точек зрения никогда не было одинаковым, однако на любой встрече отстаивающих семантику завершения было примерно в четыре раза больше. Среди аргументов в пользу возобновления чаще других повторялись такие: □ поскольку возобновление - более общий механизм, чем завершение, именно его и следует принять, даже если есть сомнения в его полезности; □ есть важные случаи, когда подпрограмма оказывается блокированной из-за отсутствия ресурса (например, памяти или гибкого диска в накопителе). В такой ситуации семантика возобновления позволила бы подпрограмме возбудить исключение, дождаться, пока обработчик найдет ресурс, а затем продолжить выполнение, как если бы ресурс был доступен в самом начале. А вот как вьп-лядели наиболее популярные и убедительные аргументы в пользу завершения: □ семантика завершения намного проще семантики возобновления. Фактически для возобновления нужны базовые механизмы продолжения и вложенных функций, но никакой другой пользы из этих механизмов не извлекается; □ методика восстановления в случае нехватки ресурсов, предлагаемая во втором доводе в пользу возобновления, неудачна в принципе. Она порождает тесные связи между библиотечным и пользовательским кодами, которые трудны для понимания и могут приводить к ошибка.м; □ во многих предметных областях написаны весьма крупные системы, в которых применялась именно семантика завершения, так что возобновление просто необязательно. Последний довод был подкреплен еше и теоретическим рассуждением Флавия Кристиана (Flavin Cristian), который доказал, что при наличии завершения семантика возобновления не нужна [Cristian, 1989]. Потратив два года на споры, я вынес впечатление, что можно привести убедительные логические доводы в пользу любой точки зрения. Они имелись даже в специальной работе [Goodenough, 1975] по обработке исключений. Мы оказались в положении все тех же античных философов, которые так яростно и умно спорили о природе Вселенной, что как-то забыли о ее изучении. Поэтому я просил любого, кто имел реальный опыт работы с большими системами, представить конкретные факты. На стороне семантики возобновления оказался Мартин ОРиордан, сообщивший, что компания Microsoft накопила м1юголетний позитивный опыт при.менения обработки исключений с возобновлением работы . Но у ОРиордана не было конкретных примеров; также весьма сомнительно, что первая версия операционной системы OS/2 по-настоящему ценна. Опыт применения ловушек ON в языке PL/I приводился в качестве как аргумента за , так и аргумента против семантики возобновления. Затем, на заседании в Пало Альто в ноябре 1991 г. .мы услышали блестящий доклад Джима Митчелла (Jiш Mitchell), работавшего в компании Sun, а перед этим - в Xerox PARC. Доклад содержал доводы в пользу семантики завершения, подкрепленные личным опытом и фактическими данными. На протяжешш 20 лет Митчелл пользовался обработкой исключений в разных языках и на первых порах отстаивал семантику возобновления в качестве одного из главных проектировщиков и разработчиков системы Cedar/Mesa от ко.мпании Xerox. Его вывод звучал так: Завершение следует предпочесть возобновлению. Это вопрос не вкусо, а многолетней практики. Возобновление выглядит соблазнительно, но это порочный метод . Свое утверждение Митчелл подкрепил рассказом о работе над несколькими операционными системами. Самым главным был пример системы Cedar/Mesa, которую написали профаммисты, любившие и умевшие пользоваться семантикой возобновления. Однако через десять лет в системе из полумиллиона строк остался лишь один случай использования возобновления - в запросе контекста. Поскольку и в данной ситуации оно фактически было не нужно, .механизм возобновления исключили полностью, после чего скорость работы этой части системы значительно возросла. Во всех тех случаях, когда применялась операция возобновления (а это более десяти лет эксплуатации), появлялись определенные проблемы и приходилось искать более подходящий механизм. По сути дела, все
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |