2009-07-21 4 views
5

Является ли хорошей практикой использовать исключение для управления случаями, которые не являются ошибками?с использованием исключений для целей без ошибок

Как в JavaScript и Python, которые управляют случаем StopIteration в генераторах (ключевое слово yield).

+0

должен быть wiki сообщества. – SilentGhost

+0

По-видимому, никакой ответ не затрагивает использование JavaScript и Python исключений, чтобы разорвать поток выполнения. –

ответ

8

Это зависит от языка. Каждый язык имеет свой собственный дизайн и идиомы. Для большинства языков исключения должны быть исключительными.

В таких языках, как C++, Java и C#, это очень плохая форма использования исключений для чего-либо еще.

В Python исключения используются чаще для таких вещей, как конец итерации. Существует гораздо больше моделей для того, чтобы делать то, что вы хотите, и обрабатывать исключения позже, а не проверять ввод («Легче просить прощения, чем разрешения»). Например, если вы хотите открыть файл, на Java вы можете проверить, существует ли он сначала, а затем открыть его и проверить, есть ли у вас действительный поток. В Python вы откроете его и используйте. Если это не удается, вы обрабатываете исключение.

Из wikipedia статьи:

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

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

11

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

+4

Иногда бывает не так просто отличить исключительные и обычные случаи. –

+0

Упомяните пример? – tomfanning

+0

@Suobok Я в недоумении относительно того, когда различие было бы трудным. Можете ли вы привести пример случая, были ли размыты линии между обычным случаем и исключительным случаем? –

10

Не обычно, нет. ASP.NET использует это для Response.Redirect - фактически прерывает поток, а затем перехватывает исключение и перезагружает его. Это очень неприятно, но это делает, позволяя вам в принципе «выходить» с запросом без всякого уровня стека, осознавая, что ему нужно немедленно вернуться.

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

+1

Возможно, иногда бросание исключения яснее, что много вложенных «возвратных» заявлений? –

+0

@Soubok: Хм ... Очень редко. Честно говоря, это была бы довольно «исключительная» ситуация. Я бы постарался избежать этого во всех нормальных ситуациях. –

+0

Downvoter: Уход за причину? –

3

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

2

No.

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

  • «Э-э, я не могу найти этот файл». - Исключение!
  • «Э-э, я не могу разделить на 0.» - Исключение!
  • «У меня нет памяти». Исключение!
  • «Результат не 2,5.» - не исключение
+2

Иногда не удается найти файл. Особенно, если файл введен пользователем. Теперь, если это файл, который вам нужен, и если его нет в одном месте, это признак проблем, это исключение. –

+0

Глубоко в недрах вашего приложения это все же исключение, конечно, вы должны украсить его, прежде чем показывать его пользователю. – Bombe

1

No.

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

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

+0

Просто обратите внимание, что Python и JavaScript используют исключение StopIteration для управления концом генератора, потому что он дешевле вызова метода на каждой итерации, чтобы узнать, является ли это концом. –

+0

«Вообще» могут иметь исключения (каламбур). – Richard

+1

... и что разработчики платформы могут работать с разными правилами (ведь они могут модифицировать динамику платформы в соответствии с решением). – Richard

2

Это очень д неустойчивая практика. Если вы считаете, что это лучше всего для вашей ситуации, независимо от того, не забудьте документировать и прокомментировать это, чтобы сохранить ваш WTF/m.

1

Я считаю, что иногда исключения полезны для строительства DSL s. Я знаю, это звучит странно, но так как на многих языках нет функций Ruby (ключевое слово return является необязательным, потому что результат последнего оцененного выражения возвращается), мы используем то, что можем.

К примеру, недавно я пытался построить небольшую базу тестирования JavaScript, и я хотел способ для каркасные пользователей, чтобы иметь возможность сказать:

skip(); 
pending("pending message"); 
fail("failure message"); 

вместо:

return skip(); 
return pending("pending message"); 
return fail("failure message"); 

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

Это пример использования Исключения для потока управления.

Вот небольшой пример:

$.it("should offer means to explicitly mark a spec as failed", function() { 
    $.fail("this spec must fail"); 
}); 
2

В Sudoku Solver я написал, генерируется исключение в случае загадка решена.

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

Что-то вроде этого является известной идиомой на Схеме, используя call/cc. Я имитировал это в своей программе на C++.

Я был бы рад услышать про кого-то мнение или мнение относительно этого подхода.

Смежные вопросы