Есть ли теория исключений в иерархиях?

18

Я знаком с дюжиной языков программирования, которые в некотором роде имеют исключения, но я стал свидетелем двух «патологических» тенденций.

  1. Кажется, что не существует общего шаблона или иерархии исключений. Каждый язык в основном катит свою собственную версию, и если исключения делают это стандартом, то исключения, которые можно найти в стандарте, были бы довольно произвольными (в основном те, которые были реализованы при создании языковых инструментов, таких как чтение исходного кода из строка или исключение для вызова отладчика, или то, что происходит, когда файл не может быть найден и т. д.)

  2. Исключения, определенные языком, очень редко используются пользовательскими программами. Обычно бывают одно или два популярных исключения (например, «не реализовано»). Хотя в большинстве случаев программисты создают свои собственные исключения. (Сравните это, например, с созданием новых числовых типов или новых типов коллекций).

Это выглядит как ужасное упущение для меня. Почему никто не знает, какие ошибки будут нужны в пользовательских программах? Я надеялся, что будет какая-то хорошая иерархия, похожая на числовые типы, коллекции, объектную систему и т. Д.

Что еще хуже, Goolge и Wikipedia предоставляют очень небольшую помощь по этому вопросу. Пока что я нашел только статью о функциональном исключении, которая открывается в отрывке:

В этой статье утверждается, что ленивое функциональное программирование не только делает ненужным встроенный механизм обработки исключений, но и предоставляет мощный инструмент для разработки и преобразования программ, использующих исключения

(Функциональная теория исключений, Майк Спиви, 1988)

Но я думаю, что исключения хороши. Я не хочу трансформировать программы, использующие исключения, напротив, я хочу сделать использование исключений менее хаотичным.

Вопрос:

Есть ли теория исключений? Если так, то как это называется? Каковы, если таковые имеются, краеугольный камень работы с изложением основы этого?

wvxvw
источник
Исключением является довольно новое изобретение, возможно, менее чем ~ 20 лет, возникающее в некоторой степени из "longjmp" Си. они в основном связаны с ООП. кажется, что идеальное использование / теория / лучшие практики все еще находятся в стадии разработки. У Java есть одна из более сложных моделей. как вы заметили, существует множество «антипаттернов», касающихся исключений. Отчасти это связано с теорией «отказоустойчивых вычислений», которая в целом также находится в зачаточном состоянии.
13
Вы можете рассматривать исключения как подмножество теории продолжения. См en.wikipedia.org/wiki/Continuation
jmite
@jmite Исключения и продолжения очень разные. Исключения динамически связываются с их обработчиками, а продолжения - статически. В общем, сами по себе продолжения не могут использоваться для реализации исключений, по крайней мере, при наличии типов, см., Например, Типизированные исключения и продолжения не могут макроэкспрессировать друг друга .
Мартин Бергер
«Исключения, определяемые языком, очень редко используются пользовательскими программами». Это так верно! Определение пользовательских исключений очень редко необходимо. Например, python и его stdlib определяют что-то вроде 160 исключений. Вероятность того, что исключение, о котором вы думаете, не определена, очень мала. Некоторые (большинство?) Из этих исключений широко не известны. Например, LookupErrorон прекрасно подойдет для каждого пользовательского контейнера, но многие люди даже не знают, что он существует.
Бакуриу
1
@jmite Еще одна встреча, с которой я столкнулся за исключением этой темы, была из книги Бенджамина С. Пирса «Типы и языки программирования». Где он упоминает ошибки в контексте определения типа функции. Т.е. с его точки зрения ошибки - это просто еще одно значение, возвращаемое функциями (и вместе с другим аргументом они образуют целый тип, если мне позволено так говорить).
wvxvw

Ответы:

8

Существует большое количество публикаций об исключениях, и довольно много теоретических исследований. Вот неструктурированный и далеко не полный список с некоторыми примерами. Извините, у меня нет времени для более сфокусированного ответа.

  • Б. Рэнделл, Структура системы для отказоустойчивости программного обеспечения.
  • Дж. Б. Гуденоф. Обработка исключений: проблемы и предлагаемые обозначения.
  • Дж. Б. Гуденоф. Структурная обработка исключений.
  • Б. Г. Райдер, М. Л. Соффа, Влияние на дизайн обработки исключений.
  • Д. Теллер, А. Спивак, Т. Вароко, поймай меня, если сможешь: На пути к безопасному типу, иерархическому, легкому, полиморфному и эффективному управлению ошибками в OCaml.
  • X. Leroy, F. Pessaux, Основанный на типе анализ необученных исключений.
  • Р. Миллер, А. Трипати, Проблемы обработки исключений в объектно-ориентированных системах.
  • С. Дрю, К.Дж. Гоф, Дж. Ледерманн, Реализация обработки исключений с нулевыми накладными расходами.
  • Б. Страуструп, Исключительная безопасность: концепции и методы.
  • D. Malayeri, J. Aldrich, Спецификации практических исключений.
  • Х. Накано, Конструктивная формализация механизма ловли и броска.
  • А. Наневский, Модальное исчисление для обработки исключений.
  • П. де Гроот, Простое исчисление обработки исключений.
  • H. Thielecke, Об исключениях и продолжениях в присутствии государства.
  • JG Riecke, H. Thielecke, Типизированные исключения и продолжения не могут макроэкспрессировать друг друга.
  • M. van Dooren, E. Steegmans. Объединение надежности проверяемых исключений с гибкостью непроверенных исключений с помощью объявлений привязанных исключений.
  • JA Vaughan, Логическая интерпретация исключений в стиле Java.
  • С. Марлоу, С. Пейтон Джонс, А. Моран, Асинхронные исключения в Хаскелле.
  • B. Jacobs, F. Piessens, Failboxes: Обеспечиваемая безопасная обработка исключений.
Мартин Бергер
источник
Вау, спасибо большое! Мне понадобится несколько месяцев (если не больше), чтобы вернуться с положительным ответом :) Теперь я разрываюсь между несколькими книгами, не зная, с чего начать!
wvxvw
2
Многие из этих статей посвящены реализации или моделированию исключений в языках программирования, а не о том, как проектировать иерархии исключений. Не могли бы вы урезать список до соответствующих документов?
Жиль "ТАК - перестань быть злым"
@ Жиль Оригинальный вопрос был немного неясным. Я считаю, что то, что считается соответствующими исключениями, зависит в основном от приложения. Единственная реальная теоретическая проблема с исключениями - это компромисс между (1) связыванием несвязанных модулей через исключения (именно поэтому ни один язык после Java не имеет обязательных спецификаций исключений), (2) предоставление пользователю модуля некоторого указания, какие ошибки следует ожидать и (3) помощь компилятора в обработке ошибок. Насколько я могу судить, по-настоящему убедительного решения этой головоломки пока не найдено.
Мартин Бергер,
6

Я не знаю, есть ли теория, но может появиться прагматическая экспериментальная наука.

Лучший источник, о котором я могу думать, это Бьярн Страуструп, «Дизайн и эволюция C ++», Addison-Wesley, 1994 . Если я правильно помню (это очень хорошая книга, и люди продолжают заимствовать ее у меня, а не возвращают, поэтому у меня нет копии в данный момент), есть глава об исключениях. Комитет C ++ при Страуструпе потребовал много эмпирических доказательств того, что предложенная функция была необходима, прежде чем они захотели добавить ее в определение языка. На странице Википедии об исключениях есть следующая цитата из этой книги:

На совещании в Пало-Альто [стандартизация C ++] в ноябре 1991 года мы услышали блестящее резюме аргументов в пользу семантики терминации, основанных как на личном опыте, так и на данных Джима Митчелла (из Sun, ранее из Xerox PARC). Джим использовал обработку исключений на полдюжине языков в течение 20 лет и был одним из первых сторонников семантики возобновления в качестве одного из главных разработчиков и разработчиков системы Xerox Cedar / Mesa. Его сообщение было прекращение предпочтительнее возобновления; это не вопрос мнения, а вопрос многолетнего опыта. Возобновление соблазнительно, но не актуально. Он подкрепил это утверждение опытом из нескольких операционных систем. Ключевым примером был Cedar / Mesa: он был написан людьми, которые любили и использовали возобновление, но после десяти лет использования, в системе с полмиллиона строк было только одно использование возобновления - и это был контекстный запрос. Поскольку возобновление фактически не было необходимо для такого контекстного запроса, они удалили его и обнаружили значительное увеличение скорости в этой части системы. В каждом случае, когда возобновление было использовано, оно - в течение десяти лет - становилось проблемой, и его заменял более подходящий дизайн. По сути, каждое использование возобновления представляло собой неспособность разделить отдельные уровни абстракции. В каждом случае, когда возобновление было использовано, оно - в течение десяти лет - становилось проблемой, и его заменял более подходящий дизайн. По сути, каждое использование возобновления представляло собой неспособность разделить отдельные уровни абстракции. В каждом случае, когда возобновление было использовано, оно - в течение десяти лет - становилось проблемой, и его заменял более подходящий дизайн. По сути, каждое использование возобновления представляло собой неспособность разделить отдельные уровни абстракции.

В C ++ реальным выигрышем является RAII , который значительно облегчает обработку освобождения ресурсов во время ошибок. (Это не избавляет от необходимости throwи try- catch, но это означает, что вам не нужно finally.)

Я думаю, что то, что убедило их в том, что им нужны исключения, - это общие контейнеры: средство записи контейнеров ничего не знает о видах ошибок, которые должны возвращаться содержащимися объектами (тем более о том, как их обрабатывать), но о коде, который вставил эти объекты в Контейнер должен знать что-то об интерфейсе этих объектов. Но поскольку мы ничего не знаем о том, какие ошибки могут генерировать содержащиеся объекты, мы не можем стандартизировать типы исключений. (Контрапозитивно: если бы мы могли стандартизировать типы исключений, то нам не понадобились бы исключения.)

Другая вещь, которую люди, кажется, усвоили за эти годы, состоит в том, что спецификации исключений трудно правильно вставить в язык. См. Например это: http://www.gotw.ca/publications/mill22.htm или это: http://www.gotw.ca/gotw/082.htm . (И это не только C ++, Java-программисты также имеют длинные аргументы о своем опыте с проверенными и непроверенными исключениями .)

Немного об истории исключений. Классическая статья: Джон Б. Гуденоф: «Обработка исключений: проблемы и предлагаемые обозначения», Commun. ACM 18 (12): 683-696, 1975. Но исключения были известны до этого. Они были у Месы примерно в 1974 году, и, возможно, они были у PL / I. У Ады был механизм исключений до 1980 года. Я полагаю, что на исключения C ++ больше всего повлиял опыт работы с языком программирования CLU Барбары Лисков примерно с 1976 года. Барбара Лисков: «История CLU», « История языков программирования» - II , Томас Дж. Бергин-младший и Ричард Г. Гибсон-младший (ред.). С. 471-510, ACM, 1996 .

Блуждающая логика
источник
Это интересно, и мне придется больше исследовать, чтобы лучше ответить. Но на данный момент: я знаю, что есть очень сильное возражение против использования исключений в C ++ (возможно, анекдот, но в правилах кодирования Google iirc раньше запрещалось использование исключений). Проверенные исключения Java, безусловно, являются уникальным и, следовательно, интересным экспериментом, но эта функция заработала столько плохих кредитов за свою историю ... большинство людей просто перебрасывают их во время выполнения (хотя это может быть связано только с синтаксисом).
wvxvw
Я более знаком с классификацией исключений Common Lisp, где они пытались (хотя и с небольшим успехом) разделить их в соответствии с уровнем угрозы, которую они представляют для программирования. например , serious-conditionпротив simple-condition. Я также сейчас читаю Дж. Л. Остинга, где он классифицирует ошибки (не связанные с программированием) по группам, основываясь на том, как система не смогла выполнить задачу (например, использовались неподходящие детали против неискренних намерений). Что не сразу применимо к программированию, но может быть после некоторой доработки.
wvxvw
@ Блуждающая логика Я высказал свое мнение, потому что вы объяснили, почему C ++ - это sux и что грамотное включение функций может разрушить язык.
Val
@wvxvw very strong objectionПротив исключения в C ++ вытекает два факта: нет finallyконструкции, и никто больше не использует исключения. Первая проблема также усугубляет вторую. То есть, когда у вас нет finally, вы не можете закрыть ресурс, когда происходит исключение. Поскольку никто не использует исключения, все функции / API избегают их, вы должны вложить большие средства в перестройку всей традиционной инфраструктуры C ++, обернув все функции вашими исключениями, чтобы начать получать преимущества от них в своем коде. Но отсутствие finallyделает этот подход невозможным.
Val
@wvxvw: соглашения Google запрещают выбрасывать исключения через границы модуля (.so). Это связано с тем, что исключения в C ++ используют информацию о типах во время выполнения (RTTI), а Linux не справляется с реализацией типизации во время выполнения. В Linux вы можете надежно передавать типы времени выполнения между модулями только в том случае, если вы скомпилировали модули с одинаковой версией того же компилятора и соединились с идентичной версией libstdc ++. На самом деле это отказ от C ++ в целом сообществом Linux, а не отказ от исключений.
Блуждающая логика
3

Позвольте мне просто указать, что исключения являются случаем вычислительного эффекта . Другими вычислительными эффектами являются изменяемое состояние, ввод-вывод, недетерминизм, продолжения и многие другие. Таким образом, ваш вопрос можно задать более широко: как мы формируем иерархии вычислительных эффектов, как мы их организуем, и почему у нас есть те, которые у нас есть, а не другие, и т. Д.

Андрей Бауэр
источник
1
Я думаю, что это совершенно не имеет значения. Вопрос не в том, чтобы смоделировать понятие исключений, а в том, чтобы сопоставить его с ошибками - я думаю, что правильным способом описать его с точки зрения PLT была бы теория иерархий исключений.
Жиль "ТАК - перестань быть злым"
Хм, ты прав. Я исправил ответ, чтобы указать на это, но я думаю, что нет необходимости удалять его. Как вы думаете?
Андрей Бауэр