Почему обработка исключений плохо?

Если Вы хотите что-то простое, не имея необходимость делать Ваше собственное платформа , все еще не будучи все включено (django), Вы могли бы хотеть попробовать CherryPy. Это может использовать почти любой диспетчер (Обработчик страниц / система маршрутизации URL). Необходимо было бы также выбрать собственный механизм шаблонной обработки, , Genshi является моим фаворитом.

87
задан Trott 21 September 2011 в 03:23
поделиться

10 ответов

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

Рассмотрим что-то вроде этого в качестве простого примера:

class Frobber
{
    int m_NumberOfFrobs;
    FrobManager m_FrobManager;

public:
    void Frob()
    {
        m_NumberOfFrobs++;

        m_FrobManager.HandleFrob(new FrobObject());
    }
};

Предполагается, что FrobManager удалит FrobObject , это выглядит нормально, правда? Или, может быть, нет ... Представьте, что либо FrobManager :: HandleFrob () , либо оператор new выдает исключение. В этом примере приращение m_NumberOfFrobs не откатывается. Таким образом, любой, кто использует этот экземпляр Frobber , будет иметь возможно поврежденный объект.

Этот пример может показаться глупым (хорошо, мне пришлось немного растянуться, чтобы построить его :-)), но Вывод состоит в том, что если программист не думает постоянно об исключениях и не следит за тем, чтобы каждая перестановка состояния откатывалась назад всякий раз, когда происходят выбросы, у вас возникают проблемы.

В качестве примера вы можете думать об этом как вы думаете о мьютексах. Внутри критического раздела вы полагаетесь на несколько операторов, чтобы убедиться, что структуры данных не повреждены и другие потоки не могут видеть ваши промежуточные значения. Если какое-либо из этих утверждений случайно не выполняется, вы попадаете в мир боли. Теперь уберите блокировки и параллелизм и подумайте о каждом подобном методе. Думайте о каждом методе как о транзакции перестановок состояния объекта, если хотите. В начале вызова метода объект должен иметь чистое состояние, а в конце также должно быть чистое состояние. Между тем, переменная foo может несовместима с bar , но ваш код со временем исправит это. Что означают исключения, так это то, что любое из ваших утверждений может прервать вас в любой момент. В каждом отдельном методе ответственность лежит на вас, чтобы исправить это и откатиться, когда это произойдет, или упорядочить свои операции, чтобы выбросы не влияли на состояние объекта. Если вы ошиблись (а допустить такую ​​ошибку легко), то вызывающий в конечном итоге увидит ваши промежуточные значения.

Такие методы, как RAII, которые программисты C ++ любят упоминать как окончательное решение этой проблемы, долгий путь защиты от этого. Но они не серебряная пуля. Это гарантирует, что вы высвобождаете ресурсы сразу, но не избавляет вас от необходимости думать о повреждении состояния объекта и о том, что вызывающие абоненты видят промежуточные значения. Так что для многих людей проще сказать, определяя стиль кодирования, без исключений . Если вы ограничиваете тип кода, который пишете, эти ошибки труднее вносить. Если вы этого не сделаете, довольно легко ошибиться.

О безопасном кодировании на C ++ написаны целые книги. Многие эксперты ошиблись. Если это действительно так сложно и имеет так много нюансов, возможно, это хороший знак, что вам нужно игнорировать эту функцию. : -)

t избавляет вас от необходимости думать о повреждении состояния объекта и о том, что вызывающие объекты видят промежуточные значения. Таким образом, для многих людей проще сказать по стилю кодирования без исключений . Если вы ограничиваете тип кода, который пишете, эти ошибки труднее вносить. Если вы этого не сделаете, довольно легко ошибиться.

О безопасном кодировании на C ++ написаны целые книги. Многие эксперты ошиблись. Если это действительно так сложно и имеет так много нюансов, возможно, это хороший знак, что вам нужно игнорировать эту функцию. : -)

t избавляет вас от необходимости думать о повреждении состояния объекта и о том, что вызывающие объекты видят промежуточные значения. Так что для многих людей проще сказать, определяя стиль кодирования, без исключений . Если вы ограничиваете тип кода, который пишете, эти ошибки труднее вносить. Если вы этого не сделаете, довольно легко ошибиться.

О безопасном кодировании на C ++ написаны целые книги. Многие эксперты ошиблись. Если это действительно так сложно и имеет так много нюансов, возможно, это хороший знак, что вам нужно игнорировать эту функцию. : -)

ошибиться довольно легко.

О безопасном кодировании на C ++ написаны целые книги. Многие эксперты ошиблись. Если это действительно так сложно и имеет так много нюансов, возможно, это хороший знак, что вам нужно игнорировать эту функцию. : -)

ошибиться довольно легко.

О безопасном кодировании на C ++ написаны целые книги. Многие эксперты ошиблись. Если это действительно так сложно и имеет так много нюансов, возможно, это хороший знак, что вам нужно игнорировать эту функцию. : -)

75
ответ дан 24 November 2019 в 07:43
поделиться
  • Необработанное исключение обычно плохо.
  • Неправильная обработка исключений - это плохо (конечно).
  • «Хорошие / плохие качества» обработки исключений зависят от контекста / области действия и уместности, а не ради этого.
0
ответ дан 24 November 2019 в 07:43
поделиться

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

Но реальность - это совсем другая история. У нас всегда бывают «неожиданные» ситуации. Вот почему нам нужны исключения.

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

Я думаю, что в Go они представят кое-что, что будет иметь дело с "неожиданными" ситуациями. Я могу предположить, что они попытаются сделать так, чтобы это звучало менее деструктивно, как исключения, и больше как логика приложения. Но это только мое предположение.

2
ответ дан 24 November 2019 в 07:43
поделиться

Типичные аргументы заключаются в том, что невозможно определить, какие исключения будут исходить из определенного фрагмента кода (в зависимости от языка), и что они слишком похожи на goto s , что затрудняет мысленное отслеживание исполнения.

http://www.joelonsoftware.com/items/2003/10/13.html

Определенно нет единого мнения по этому вопросу. Я бы сказал, что с точки зрения жесткого программиста на C, такого как Линус, исключения - определенно плохая идея. Однако типичный Java-программист находится в совершенно другой ситуации.

9
ответ дан 24 November 2019 в 07:43
поделиться

Исключения сами по себе не являются "плохими", это способ обработки исключений иногда бывает плохим. Есть несколько рекомендаций, которые можно применить при обработке исключений, чтобы облегчить некоторые из этих проблем. Некоторые из них включают (но, разумеется, не ограничиваются ими):

  1. Не используйте исключения для управления потоком программы - т.е. не полагайтесь на операторы «catch» для изменения потока логики. Это не только скрывает различные детали, связанные с логикой, но и может привести к снижению производительности.
  2. Не генерируйте исключения внутри функции, если возвращаемый «статус» имеет больше смысла - создавайте исключения только в исключительной ситуации. Создание исключений - дорогостоящая и требовательная к производительности операция. Например, если вы вызываете метод открытия файла, но этот файл не существует, генерируйте исключение FileNotFound. Если вы вызываете метод, который определяет, существует ли учетная запись клиента, возвращайте логическое значение, не возвращайте исключение «CustomerNotFound».
  3. При определении, обрабатывать ли исключение или нет, не используйте команду «try ... catch» ", если вы не можете сделать что-то полезное за исключением. Если вы не можете обработать исключение, просто позвольте ему подняться в стеке вызовов. В противном случае исключения могут быть «проглочены» обработчиком, и детали будут потеряны (если вы не повторно выбросите исключение).
11
ответ дан 24 November 2019 в 07:43
поделиться

С точки зрения golang, я полагаю, что отсутствие обработки исключений делает процесс компиляции простым и безопасным.

С точки зрения Линуса, я понимаю, что код ядра ВСЕ касается угловых случаев. Таким образом, имеет смысл отказываться от исключений.

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

Например, они подходят для большинства высокоуровневых кодов, ориентированных на пользователя, таких как код веб-приложений и приложений для настольных компьютеров.

11
ответ дан 24 November 2019 в 07:43
поделиться

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

Независимо от используемого вами языка, возьмите копию Руководства по разработке структуры : условные обозначения, идиомы и шаблоны для повторного использования. NET-библиотеки (2-е издание). Глава о генерировании исключений не имеет равных. Некоторые цитаты из первого издания (2-е в моей работе):

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

Есть страницы примечаний о преимуществах исключений (согласованность API, выбор местоположения кода обработки ошибок, повышенная надежность и т. Д. ) Есть раздел о производительности, который включает несколько шаблонов (Tester-Doer, Try-Parse).

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

25
ответ дан 24 November 2019 в 07:43
поделиться

Исключения сами по себе неплохи, но если вы знаете, что они будут происходить часто, они могут быть дорогими с точки зрения производительности.

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

29
ответ дан 24 November 2019 в 07:43
поделиться

Исключения неплохие. Они хорошо вписываются в модель RAII C ++, которая является самой элегантной особенностью C ++. Если у вас уже есть код, небезопасный в отношении исключений, то он плох в этом контексте. Если вы пишете действительно низкоуровневое программное обеспечение, такое как ОС Linux, тогда оно плохое. Если вам нравится засорять свой код кучей проверок возврата ошибок, то они бесполезны. Если у вас нет плана управления ресурсами при возникновении исключения (которое предоставляют деструкторы C ++), то они плохие.

7
ответ дан 24 November 2019 в 07:43
поделиться

Причина отсутствия исключений в Go объяснена в FAQ по языковому дизайну Go:

Исключения - похожая история. А количество дизайнов исключений были предложены, но каждый добавляет значительная сложность языка и время выполнения. По своей природе исключения охватывают функции и, возможно, даже горутины; у них есть широкомасштабные последствия. Есть также озабочены эффектом, который они пришлось бы по библиотекам. Они есть, по определению, исключительный, но опыт работы с другими языками, которые поддержать их показать, что у них есть глубокие влияние на библиотеку и интерфейс Спецификация. Было бы неплохо найти дизайн, который позволяет им быть действительно исключительный, не обнадеживающий общие ошибки превратить в особые поток управления, требующий каждого программист для компенсации.

Как и дженерики, исключения остаются открытый вопрос.

Другими словами, они еще не выяснили, как поддерживать исключения в Go таким образом, который они считают удовлетворительным. Они не говорят, что исключения плохи сами по себе ;

ОБНОВЛЕНИЕ - май 2012 г.

Дизайнеры Go теперь слезли с заборов. В их FAQ теперь говорится следующее:

Мы считаем, что привязка исключений к управляющей структуре, как в идиоме try-catch-finally, приводит к запутанному коду. Это также побуждает программистов отмечать слишком много обычных ошибок, таких как невозможность открытия файла, как исключительные.

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

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

См. подробности в статье Defer, Panic и Recover.

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


... и Линус, известный в Linux, назвал исключения чушью.

Если вы хотите знать, почему Линус считает исключения чушью, лучше всего посмотреть за его работы по этой теме. Единственное, что я Я до сих пор отследил эту цитату, которая встроена в пару писем на C ++ :

«Вся обработка исключений в C ++ в корне нарушена. Это особенно не работает для ядер»

Вы Замечу, что он говорит об исключениях C ++ в частности, а не об исключениях в целом. (И исключения C ++ действительно , по-видимому, имеют некоторые проблемы, из-за которых их сложно использовать правильно.)

Я пришел к выводу, что Линус вообще не называл исключения (в общем) «чушью»!

и не исключения вообще. (И исключения C ++ действительно , по-видимому, имеют некоторые проблемы, из-за которых их сложно правильно использовать.)

Я пришел к выводу, что Линус вообще не называл исключения (в общем) «чушью»!

и не исключения вообще. (И исключения C ++ действительно , по-видимому, имеют некоторые проблемы, из-за которых их сложно использовать правильно.)

Я пришел к выводу, что Линус вообще не называл исключения (в общем) «чушью»!

49
ответ дан 24 November 2019 в 07:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: