Чому обробка винятків погана?


90

Мова Google Go не має винятків як вибір дизайну, і Лінус з Linux називає винятки глупостями. Чому?


2
Творець ZeroMQ пише про те, як, на його думку, було помилкою писати його на C ++ (здебільшого через обробку помилок) 250bpm.com/blog:4
serbaut

Go може не мати винятків, але у нього є "паніка", з якої ви можете "відновитись" (поки відкладені оператори все ще виконуються) і які забезпечують нелокальний потік управління ...
Kerrek SB

Ось приємна стаття lighterra.com/papers/exceptionsharmful (Обробка винятків вважається шкідливою)
masterxilo

Фактично, винятки можуть бути змодельовані в Go зі значним шаблоном , хоча цей момент може бути більш значущим для перетворення з синтаксису цукру, ніж для написання шаблонного шаблону вручну.
Шелбі Мур III

Відповіді:


82

Винятки полегшують написання коду, коли виняток, який викидається, порушить інваріанти і залишить об'єкти в несумісному стані. Вони, по суті, змушують вас пам’ятати, що більшість кожного вашого висловлювання може потенційно кинути і правильно це обробити. Це може бути хитро і протиінтуїтивно.

Розглянемо щось подібне як простий приклад:

class Frobber
{
    int m_NumberOfFrobs;
    FrobManager m_FrobManager;

public:
    void Frob()
    {
        m_NumberOfFrobs++;

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

Якщо припустити , що FrobManagerволя deleteдо FrobObject, це виглядає нормально, НЕ так? А може, ні ... Уявіть тоді, якщо будь-який FrobManager::HandleFrob()або operator newвидасть виняток. У цьому прикладі приріст m_NumberOfFrobsне відкочується. Таким чином, у кожного, хто використовує цей екземпляр Frobber, буде можливий пошкоджений об’єкт.

Цей приклад може здатися дурним (гаразд, мені довелося трохи розтягнутися, щоб побудувати його :-)), але висновок полягає в тому, що якщо програміст постійно не думає про винятки і переконується, що кожна перестановка стану виконується назад, коли є кидки, ви потрапляєте в неприємності таким чином.

Як приклад, ви можете думати про це, як про мьютекси. Усередині критичного розділу ви покладаєтесь на кілька тверджень, щоб переконатися, що структури даних не пошкоджені, а інші потоки не бачать ваших проміжних значень. Якщо якесь із цих тверджень просто випадковим чином не пробігає, ви потрапляєте у світ болю. Тепер забирайте замки і паралелізм і продумуйте кожен метод таким чином. Подумайте про кожен метод як про трансакцію перестановок стану об’єкта, якщо хочете. На початку виклику методу об'єкт повинен мати чистий стан, а в кінці також повинен бути чистий стан. Між ними змінна fooможе суперечитиbar, але ваш код врешті-решт це виправить. Винятки означають те, що будь-яке з ваших тверджень може перервати вас у будь-який час. У кожному окремому методі ви покладаєтеся на те, щоб це правильно зробити і відкотитись, коли це трапиться, або замовити ваші операції, щоб кидки не впливали на стан об’єкта. Якщо ви помиляєтесь (і зробити такий тип помилки легко), то абонент бачить ваші проміжні значення.

Такі методи, як RAII, які програмісти на C ++ люблять згадувати як остаточне рішення цієї проблеми, проходять довгий шлях захисту від цього. Але вони не є срібною кулею. Це гарантує, що ви звільняєте ресурси під час кидка, але не звільняє вас від необхідності думати про пошкодження стану об'єкта та тих, хто викликає, бачачи проміжні значення. Отже, для багатьох людей це легше сказати за стилем кодування, без винятків . Якщо ви обмежуєте тип коду, який ви пишете, важче представити ці помилки. Якщо цього не зробити, помилитися досить просто.

Про кодування в C ++ написано цілі книги. Багато експертів помиляються. Якщо це насправді настільки складно і має стільки нюансів, можливо, це хороший знак, що потрібно ігнорувати цю функцію. :-)


9
Цікава відповідь, однак вона нічого не відображає в моєму досвіді програмування. Тож я думаю, це або специфічна для культури (можливо, більша проблема в Java або C ++, ніж, скажімо, Python), або конкретна для домену.
ddaa,

42
Винятки, написані керованою мовою із використанням шаблону try-catch-konačno, ніколи не повинні залишати недійсний стан, якщо вони написані належним чином; оскільки блок нарешті гарантовано виконується, об'єкти можуть бути там розблоковані. Про решту слід подбати, виходячи за межі змінних та збираючи сміття.
Роберт Харві,

7
@ddaa Проблема, безумовно, можлива в Python. В результаті, як правило, важко відтворити помилку. Можливо, вам було особливо прискіпливо або пощастило. Але тоді ви маєте рацію, що це більше проблема в C ++, де найпоширенішою помилкою від поганого EH є витік пам'яті. Я намагався підкреслити, що витоки не є найсерйознішою проблемою. @Robert GC пом'якшить витоки пам'яті, але я не впевнений, що керований код позбавить вас від помилок програміста. Зокрема, якщо хтось не звертає уваги на безпеку виключень, оскільки не вважає, що це проблема в їх мові, це не є чудовим знаком.
асвейкау

4
@lzprgmr, безумовно, є: винятки дозволяють мати справу з diff. типи помилок при диф. місця в коді. Виправлення помилки підключення може зажадати повторного підключення, але не в середині глибоко вкладеної функції. Ви хочете, щоб це було зроблено до менеджера з’єднань або чогось іншого. Потім робота зі значеннями, що повертаються, змушує вас перевіряти помилки при кожному окремому виклику та переміщувати їх вручну (у випадку помилки скидання з'єднання, наприклад). Крім того, повертаються значення, накопичені у вкладених викликах: func3 може повернути -1, func2 викликає func3, повертає -2 за його помилки, -1 для func3 та ін.
abourget

4
Я голосував проти, але я змінив це, тому що це причина, чому винятки зневажають. Однак, на мій погляд, майже будь-який метод або фрагмент коду може зазнати невдачі. Ви не можете обробити кожну умову помилки, ввівши для неї значення, що повертається. Ви втратите інформацію про помилку. Думка про те, що ви можете приємно синхронізувати все, перевіряючи кожне твердження та виконуючи очищення, призводить до дуже заплутаного коду - виявлення помилок у декількох операторах та очищення одного чи двох ресурсів, які не є GC'ed, набагато чистіший.
Маартен Бодеус

50

Причина того, що Go не має винятків, пояснюється у поширених запитаннях щодо дизайну мови Go:

Винятки - подібна історія. Запропоновано ряд конструкцій для винятків, але кожен додає значну складність мові та часу роботи. За своєю природою винятки охоплюють функції і, можливо, навіть програми; вони мають широкі наслідки. Існує також занепокоєння щодо впливу, який вони мали б на бібліотеки. Вони, за визначенням, є винятковим, але досвід роботи з іншими мовами, які їх підтримують, показує, що вони мають глибокий вплив на специфікацію бібліотеки та інтерфейсу. Було б непогано знайти дизайн, що дозволяє їм бути справді винятковими, не заохочуючи поширені помилки перетворюватися на особливий потік управління, який вимагає від кожного програміста компенсації.

Як і загальні препарати, винятки залишаються відкритим питанням.

Іншими словами, вони ще не з’ясували, як підтримувати винятки в Go таким чином, який, на їхню думку, є задовільним. Вони не говорять, що винятки самі по собі погані ;

ОНОВЛЕННЯ - травень 2012 р

Зараз дизайнери Go зійшли з огорожі. Їхні поширені запитання тепер говорять так:

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

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

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

Детальніше див. У статті Відкласти, панікувати та відновити.

Тож коротка відповідь полягає в тому, що вони можуть робити це по-різному, використовуючи багатозначну віддачу. (І вони в будь-якому випадку мають форму обробки винятків.)


... і Лінус з Linux називав винятки глупостями.

Якщо ви хочете знати, чому Лінус вважає, що винятки - це лайно, найкраще шукати його праці на цю тему. Єдине, що я відстежував дотепер, - це цитата, яка вбудована в пару електронних листів на C ++ :

"Весь процес обробки винятків на C ++ принципово зламаний. Особливо він порушений для ядер."

Ви помітите, що він говорить зокрема про винятки на C ++, а не про винятки загалом. (І винятки на C ++ , мабуть, мають деякі проблеми, через які їх важко використовувати правильно.)

Я прийшов до висновку, що Лінус взагалі не називав винятки (загалом) "лайною"!


30
Я ненавиджу, коли вони приховують інформацію, розміщуючи її в FAQ. :)
brian d foy

7
Зверніть увагу, що Лінус починає цю електронну пошту з "C ++ - це жахлива мова". і продовжує сперечатися про те, наскільки він ненавидить як С ++, так і людей, які вирішили програмувати на ньому. Отже, я не думаю, що його думку про винятки в C ++ можна вважати надійною, враховуючи його дещо необ'єктивну думку щодо C ++.
Pharap

1
@ Hi-Angel - Як сказано в тексті, який я цитував: "Для простої обробки помилок повернення багатозначних даних Go спрощує повідомлення про помилку, не перевантажуючи повернене значення". . Ось як це пов’язано. У будь-якому випадку я цитую обґрунтування дизайнерів Go. Якщо ви хочете сперечатися, сперечайтеся з >> ними <<.
Stephen C

1
@ Привіт-Ангел - я не писав цих абзаців. Я просто цитував їх. Якщо у вас є проблеми з ними, ви, мабуть, повинні розглянути це з авторами. Теоретично я міг надати підручник з мови Go як контекст. Але відверто кажучи, люди, які не розуміють термінологію Go, можуть відвідати веб-сайт Go, щоб з’ясувати, що це все означає.
Stephen C

1
".. приводить до заплутаного коду" Давним-давно я писав програму C з багатьма рядковими операціями. Кожен метод був виділенням пам'яті, а потім перевірка успішного розподілу. Здавалося, що більшість коду просто перевіряла розподіл. Хіба це не спантеличено? C ++ за винятками був для мене чудовим порятунком.
robsosno

29

Винятки непогані самі по собі, але якщо ви знаєте, що вони трапляться багато, вони можуть бути дорогими з точки зору продуктивності.

Основне правило полягає в тому, що винятки повинні позначати виняткові умови, і що ви не повинні використовувати їх для контролю потоку програм.


9
@Robert: "ти не повинен використовувати їх для контролю потоку програм", я не думав про це таким чином, нова перспектива для мене: P +1
okw

2
Це також дійсно залежить від мови. Важко уникнути винятків, якщо ви програмуєте на Java, наприклад.
Charles Salvia

2
@Charles: Я думаю, справа в тому, що винятки доречні в ситуаціях, які вказують на помилку, неправильно налаштовану систему або нерозумні введення. Більшості винятків бібліотеки Java можна уникнути за допомогою коду "звичайного робочого процесу".
Артелій

6
вони не повинні коштувати багато. наприклад, ви можете реалізувати "спробу", яка коштує нульового часу на виконання, і мати "кинути" шукати обробники винятків у таблиці на основі адрес абонента, які він бачить у стеку ... Я б сказав, що найбільші причини не використання винятків взагалі не пов'язане з продуктивністю.
асвейкау

Перефразовано; питання чітко натякає на використання винятків загалом або взагалі на невикористання винятків (вони є лайними або навіть відсутні в мові). Ваша відповідь показує лише, чому винятки погано впливають на продуктивність, коли використовуються для керування програмою.
Маартен Бодеус

26

Я не погоджуюся з "виключенням лише у виняткових ситуаціях". Хоча загалом це правда, це оманливе. Виняток становлять умови помилок (помилки виконання).

Незалежно від мови, якою ви користуєтесь, візьміть копію Рекомендацій щодо розробки Framework : Конвенції, ідіоми та шаблони для багаторазових бібліотек .NET (2-е видання). Розділ про метання винятків - без однолітків. Деякі цитати з першого видання (2-го в моїй роботі):

  • НЕ повертайте коди помилок.
  • Коди помилок можна легко ігнорувати, і часто це відбувається.
  • Винятки є основним засобом повідомлення про помилки в рамках.
  • Хорошим емпіричним правилом є те, що якщо метод не робить того, що підказує його назва, його слід вважати помилковим на рівні методу, що призводить до винятку.
  • НЕ використовуйте винятки для нормального потоку управління, якщо це можливо.

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

Винятки та обробка винятків є НЕ погано. Як і будь-яка інша функція, ними можна зловживати.


4
Я повинен не погодитися з цим. Я не проти винятків, і ця книга повинна бути обов'язковою, однак вона упереджена до розробки .NET та C #.

3
Я знаю, що це давнє, просто хотів прокоментувати, що, схоже, між типом .NET та типом * nix існують загальні розбіжності у стилі. Усі бібліотеки, які я використовував як розробник Linux, використовують коди повернення, а посібники зі стилем * nix, які я прочитав (як, наприклад, моя компанія та Google ), просто говорять "ми не робимо винятків". Тільки подумайте, що це цікаво.
jarvisteve

1
Фреймворки повинні поводитися з винятками інакше, ніж із програмами кінцевих користувачів. Фреймворки не мають способу боротися з помилками, крім створення винятку, як це робить споживча програма.
0x6C38,

11

З точки зору golang, я вважаю, що відсутність обробки винятків робить процес компіляції простим і безпечним.

З точки зору Linus, я розумію, що код ядра - це ВСЕ про кутові випадки. Тож має сенс відмовитись від винятків.

Винятки мають сенс у коді, якщо нормально кинути поточне завдання на поверх, і коли загальний код справи має більше значення, ніж обробка помилок. Але вони вимагають генерації коду від компілятора.

Наприклад, вони чудові в більшості високорівневих кодів, орієнтованих на користувача, таких як веб-код та код настільних програм.


Але те, що справедливо для коду ядра, справедливо і для тривалих процесів власного сервера.
Лотар

11

Самі по собі винятки не є "поганими", це те, що іноді обробляються винятки, як правило, є поганими. Існує кілька вказівок, які можна застосувати під час обробки винятків, щоб полегшити деякі з цих проблем. Деякі з них включають (але, безумовно, не обмежуються):

  1. Не використовуйте винятки для управління програмним потоком - тобто не покладайтесь на оператори "catch" для зміни потоку логіки. Це не тільки приховує різні деталі навколо логіки, це може призвести до поганої роботи.
  2. Не кидайте винятки зсередини функції, коли повернутий "статус" має більше сенсу - викидайте виключення лише у виняткових ситуаціях. Створення винятків - дорога операція, що вимагає великих показників. Наприклад, якщо ви викликаєте метод для відкриття файлу, а цей файл не існує, викиньте виняток "FileNotFound". Якщо ви викликаєте метод, який визначає, чи існує обліковий запис клієнта, поверніть логічне значення, не повертайте виняток "CustomerNotFound".
  3. Визначаючи, чи обробляти виняток, не використовуйте речення "try ... catch", якщо ви не можете зробити щось корисне з цим винятком. Якщо ви не в змозі обробити виняток, вам слід просто дозволити йому спливати в стеці викликів. В іншому випадку обробник може «проковтнути» винятки, і деталі загубляться (якщо ви не поновите виняток).

2
Повернення статусу - справа складна. Я бачив занадто багато коду, який має метод GetCustomer, який повертає сутність Клієнта в разі успіху або нульового значення у випадку відмови. У багатьох випадках телефонний код ніколи не перевіряв результат, але негайно отримував доступ до Клієнта. Це працювало більшу частину часу ...
TrueWill

3
Але якщо GetCustomer видає виняток замість повернення null, клієнтський код все одно повинен обробляти виняток. Незалежно від того, чи перевіряє наявність нуля, чи обробляє винятки, відповідальність лежить на коді клієнта - якщо він не робить те, що відбувається належним чином, рано чи пізно щось вибухне.
Кріс

1
@TrueWill Мови, які підтримують шаблони / дженерики, вирішують це, повертаючи Option<T>замість nullсьогодні. Наприклад, щойно був представлений в Java 8, беручи підказку від Гуави (та інших).
Маартен Бодеус

@owlstead Так. Полюбіть, можливо, монаду. Це хороший спосіб, якщо ваша мова це підтримує та пропонує відповідність шаблону.
TrueWill

@owlstead Знову ж таки, те, що сказав Кріс, все ще є вагомим для цього - користувач повинен пам’ятати про виклик функції .orElse (defaultObject) або будь-якої ідіоми, про яку йде мова. Зрештою, проблемою є здебільшого програмісти, а не метод обробки помилок.
Pharap

9

Типовими аргументами є те, що неможливо визначити, які винятки вийдуть з певної частини коду (залежно від мови), і що вони занадто схожі на gotos, що ускладнює розумове відстеження виконання.

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

З цього питання однозначно немає єдиної думки. Я б сказав, що з точки зору такого твердого програміста на Сі, як Лінус, винятки, безумовно, є поганою ідеєю. Типовий програміст Java, однак, знаходиться в зовсім іншій ситуації.


1
Код С має винятки, просто по-іншому. Вам потрібно обернути кожен виклик нетривіальної функції в ifs, що робить використання цієї мови головним болем!
RCIX

1
Є також setjmp/ longjmpstuff, що досить погано.
Тім Сільвестр

9
Ви дійсно хочете скористатися порадою людини, яка цінує програмісти Duct Tape і яка не вважає, що необхідні модульні тести? joelonsoftware.com/items/2009/09/23.html
TrueWill

4
Це класична помилка (або обман) під час дискусії, де аргументи на цю тему замінюються посиланнями на особистість. Зазвичай це ознака дегенерації дискусії.
Петр Гладких

1
@PetrGladkikh Дискусія розпочалася з ОП, посилаючись на думку Лінуса ... що обман відомий як помилкове звернення до влади. Дискусія може йти лише вгору, і це не "обман", щоб відповісти на питання, чому Лінус не любить винятки, посилаючись на свою особистість.
Джим Балтер,

7

Винятки непогані. Вони добре поєднуються з моделлю RAII на C ++, що є найелегантнішим у C ++. Якщо у вас вже є купа коду, який не є виключенням безпечним, тоді вони погані в цьому контексті. Якщо ви пишете дуже низький рівень програмного забезпечення, наприклад ОС Linux, то вони погані. Якщо вам подобається засмічувати свій код безліччю перевірок повернення помилок, тоді вони не корисні. Якщо у вас немає плану управління ресурсами, коли виникає виняток (який надають деструктори C ++), вони погані.


7
RAII корисний навіть без винятків.
Марк Ренсом,

4
однак, винятки не корисні без RAII (або іншого автоматичного управління ресурсами).
Грег Роджерс

+1 за вказівку на ситуації, коли винятки не є доречними і що винятки за своєю суттю не є поганими.
Pharap

4

Таким чином, чудовим варіантом використання винятків є ....

Скажімо, ви працюєте над проектом, і кожен контролер (близько 20 різних основних) розширює один контролер суперкласу методом дії. Тоді кожен контролер робить купу речей, що відрізняються один від одного, викликаючи об'єкти B, C, D в одному випадку та F, G, D в іншому випадку. Тут на допомогу приходять винятки у багатьох випадках, коли код повернення був безліч, і КОЖНИЙ контролер обробляв це по-різному. Я зламав весь цей код, викинув належний виняток з "D", схопив його в методі дії контролера суперкласу, і тепер усі наші контролери є послідовними. Раніше D повертав null для БАГАТО різних випадків помилок, про які ми хочемо повідомити кінцевому користувачеві, але не змогли, і я не зробив

так, нам слід турбуватися про кожен рівень та будь-яке очищення / витоки ресурсів, але загалом жоден з наших контролерів не мав ресурсів для очищення після.

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


1
+1 Легко один з найкращих аргументів для використання винятків, які я прочитав. Могли б використати більш детальні приклади (тобто діаграму UML, якийсь псевдокод чи якийсь фактичний код), але питання щодо послідовного виконання підкласів є хорошим. Крім того, той факт, що ваші докази є анекдотичними, свідчить про те, що винятки корисні в реальних ситуаціях, а корисність - головна мета будь-якої мовної функції.
Pharap

як додаток, якщо ви перебуваєте в Scala, ви можете замість цього повернути Try [ResponseType], який представляє виняток або фактичну відповідь. Потім ви можете слідувати тій самій схемі, до якої я уникнув вище, без фактичних винятків, крім тих, що їх застосовують у спробі. Тоді, як і кожен ваш метод, повертає 1 + n типів відповідей, які, на мою думку, потрібні. Однак ми в Scala повертаємо Future [відповідь], яка працює так само, як Try, але може допомогти з більш асинхронним програмуванням.
Дін Хіллер

2

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

Але, реальність - це вже інша історія. У нас завжди бувають ситуації, які є "несподіваними". Ось чому нам потрібні винятки.

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

З Go, я думаю, вони запровадять щось, що буде мати справу з "несподіваними" ситуаціями. Я можу здогадуватися, що вони намагатимуться зробити так, щоб це звучало менш згубно як винятки, а більше як логіка програми. Але це лише моє припущення.


2
"Подивіться на функціональні мови, вони не мають побічних ефектів, тому вони практично не мають джерела для надзвичайних ситуацій". Це грубе завищення.
Stephen C

3
Що таке 5/0 в математиці? Арксин (200)? Sqrt (-1)? Математика має безліч виняткових ситуацій.
Роберт Фрейзер,

3
Це не виняткові ситуації ... вони просто не мають сенсу ... і через це можуть бути реалізовані як винятки ... але також можуть бути реалізовані як сукупність передумов .. тому це залежить від технічної реалізації.
Mike Chaliy

3
@MikeChaliy - Вибачте, але це просто софістика. Ви можете застосувати такі міркування, щоб сказати, що НІКОЛИ НІКОГДА немає ситуацій винятків. Насправді математичні вирази, які не мають значення (або не мають певного значення), Є винятковими. Це не означає, що з ними потрібно боротися, кидаючи та ловлячи винятки ... але якщо ви цього не зробите, вам потрібні або спеціальні значення (наприклад, Inf та Nan) або операції, які повертають кілька значень. Коротше кажучи, ці випадки вимагають спеціального лікування.
Stephen C,

1
Комп’ютери - це державні машини. Не ідеальний математичний світ.
Арунав Саньял

1

Парадигма обробки винятків C ++, яка формує часткову основу для Java, і, в свою чергу, .net, вводить деякі хороші концепції, але також має деякі серйозні обмеження. Одним із ключових дизайнерських намірів обробки винятків є надання методам гарантії, що вони або задовольнятимуть свої пост-умови, або викидати виняток, а також гарантувати, що відбудеться будь-яке очищення, яке має відбутися до того, як метод може вийти. На жаль, усі парадигми обробки винятків C ++, Java та .net не забезпечують жодних хороших засобів для обробки ситуації, коли несподівані фактори заважають виконувати очікуване очищення. Це, у свою чергу, означає, що потрібно або ризикувати, що все зупиниться, якщо щось несподіване трапиться (підхід C ++ до обробки винятків виникає під час розмотування стека),

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


1

Я не читав усіх інших відповідей, тому про це вже згадувалося, але одна критика полягає в тому, що вони змушують програми розриватися довгими ланцюгами, ускладнюючи відстеження помилок під час налагодження коду. Наприклад, якщо Foo () викликає Bar (), який викликає Wah (), який викликає ToString (), то випадково виштовхування неправильних даних у ToString () закінчується виглядом помилки у Foo (), майже повністю не пов'язаної функції.


0
  • Виняток, з яким не обробляють, як правило, поганий.
  • Виняток, з яким обробляють погано, це погано (звичайно).
  • "Добрість / поганість" обробки винятків залежить від контексту / обсягу та відповідності, а не задля того, щоб це робити.

0

Гаразд, нудна відповідь тут. Думаю, це залежить від мови насправді. Якщо виняток може залишити виділені ресурси позаду, їх слід уникати. У мовах сценаріїв вони просто дезертирують або перевершують частини потоку програм. Це само по собі неприємно, проте уникнення майже фатальних помилок за винятками є прийнятною ідеєю.

Що стосується сигналізації про помилки, я зазвичай віддаю перевагу сигналам про помилки. Все залежить від API, варіанту використання та серйозності, чи достатньо журналювання. Також я намагаюся перевизначити поведінку і throw Phonebooks()замість цього. Ідея полягає в тому, що "Винятки" часто є тупиковими, але "Телефонна книга" містить корисну інформацію про відновлення помилок або альтернативні шляхи виконання. (Ще не знайдено хорошого варіанту використання, але продовжуйте намагатися.)


0

Для мене питання дуже просте. Багато програмістів використовують обробник винятків неналежним чином. Чим більше мовних ресурсів, тим краще. Бути здатним обробляти винятки - це добре. Одним з прикладів поганого використання є значення, яке повинно бути цілим числом, не перевірятись, або інший вхід, який може ділитися і не перевірятися на ділення нуля ... обробка винятків може бути простим способом уникнути більшої праці та наполегливості, програміст може захотіти зробити брудний ярлик і застосувати обробку винятків ... Твердження: "професійний код НІКОЛИ не підводить" може бути ілюзорним, якщо деякі проблеми, що обробляються алгоритмом, є невизначеними за своєю природою. Можливо, в невідомих ситуаціях від природи добре вступати в справу обробника винятків. Належна практика програмування є предметом дискусій.


Проблема не в тому, (чи не повинно бути), чи може код вийти з ладу - більшою проблемою є ступінь того, наскільки, якщо код все-таки не вдається, хтось піклується про деталі. Якщо хтось намагається завантажити документ, і один із методів «читання даних» зазнає невдачі, його часто насправді не цікавить, який саме, оскільки ефект однаковий незалежно: документ неможливо завантажити. Концептуально обробка винятків повинна бути для цього хорошою. Проблема полягає в тому, що парадигми .NET та Java, які обробляють винятки, не забезпечують жодного приємного способу розрізнити "нудні" винятки, які слід об'єднати, від тих, які цього не повинні робити.
supercat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.