Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.03.02;
Скачать: [xml.tar.bz2];

Вниз

Exceptions considered harmful ?   Найти похожие ветки 

 
isasa ©   (2008-01-26 12:48) [80]

ЗЫ. Я хотел сказать, что в рамках проекта желательно иметь однообразие. Но не более. Вот и все.


 
Kolan ©   (2008-01-26 13:05) [81]

> У тебя есть механизм. Что с ним делать, решается в данном
> конкретном случае, руководствуясь принятыми правилами для
> данного случая, местности, времени &#133

То есть
 «Всякий овощ приносит пользу, будучи употреблен надлежащим образом в надлежащее время :)» © Игорь Шевченко

:)


 
Sandman25   (2008-01-26 13:24) [82]

isasa ©   (26.01.08 12:47) [79]

В Java генерируемые исключения описываются в сигнатуре метода. Если хочешь, чтобы кто-то что-то обрабатывал, так и пишешь в сигнатуре. И без обработки соответствующего исключения никто ничего даже не вызовет. а не как в Delphi: вызвал, код забыл проанализировать и пошел использовать неверные данные. Может, поэтому access violation в Java нету? :)


 
Kolan ©   (2008-01-26 13:34) [83]

> 4. Очень помогает вложенность Exception, то есть я могу
> получить от сервера один Exception, внутри которого находится
> другой, внутри него третий и т.д. Например, невозможно получить
> данные, потому что не найден объект, потому что произошла
> ошибка БД, потому что неверно указано наименование таблицы.

А как это? Я незнал. Где прочесть?


 
Sandman25   (2008-01-26 13:58) [84]

Kolan ©   (26.01.08 13:34) [83]

Если речь про Delphi, то нужно самому реализовывать: добавить класс TNestingException, у которого будет поле nestedException: TNestingException, а уже от этого класса наследоваться


 
Игорь Шевченко ©   (2008-01-26 14:04) [85]

Sandman25   (26.01.08 13:58) [84]

Не совсем понял, зачем такое ? Вот например есть Exception EDBEngineError, внутре которого находится вполне себе подробная информация о том, какая именно задница стряслась. Я к тому, что никто не мешает создать наследник класса Exception с необходимыми подробностями.

Или я чего-то не понял ?


 
Kolan ©   (2008-01-26 14:10) [86]

> то нужно самому реализовывать

А, я подумал есть стандартное что-то, хелп читать стал.


 
guav ©   (2008-01-26 14:19) [87]

Ветка не совсем бестолковая. Я убедился, что мнения сильно отличаются, и есть согласные с тем, что при  potential logic or user input errors, such as the overflow of an array boundary не следует кидать исключения. Поэтому  решил последовать рекомендациям не использовать исклюение для необычной, но ожидаемой ситуации.


 
Sandman25   (2008-01-26 14:20) [88]

Игорь Шевченко ©   (26.01.08 14:04) [85]

Композиция позволяет решить "проблему" отсутствия множетсвенного наследования. Например, причиной отказа распределенной транзакции может быть ошибка сервера приложений, ошибка авторизации, ошибка БД и т.д. Эти классы не наследуются один от другого, поэтому и нельзя использовать наследников.


 
guav ©   (2008-01-26 14:28) [89]

> [85] Игорь Шевченко ©   (26.01.08 14:04)
> Или я чего-то не понял ?

Видимо, речь идёт о Java подходе, где если TStream.Read может бросать только EReadError, то наследник TStream, читающий из БД, может кинуть только EReadError, но в этот EReadError может быть вложен и EDBEngineError.


 
Kolan ©   (2008-01-26 14:34) [90]

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

Хорошо, есть свойство FileName и операция DoSmth.

procedure DoSmth;
begin
 if FileExists(FFileName) then
   &#133
 else
   raise ERequiredFileNotFoundException.Create();
end;


Как поступишь?

А. Если пишешь програму.
Б. Если пишешь компонент.


 
Sandman25   (2008-01-26 14:39) [91]

Kolan ©   (26.01.08 14:34) [90]

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


 
Игорь Шевченко ©   (2008-01-26 14:39) [92]

Sandman25   (26.01.08 14:20) [88]

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


 
Игорь Шевченко ©   (2008-01-26 14:41) [93]

Kolan ©   (26.01.08 14:34) [90]

Я не советую писать такой компонент. Это неверно в общем случае.


 
Sandman25   (2008-01-26 14:50) [94]

Игорь Шевченко ©   (26.01.08 14:39) [92]

Как потом по этому reason узнать, что явилось причиной причины?

А множественное наследование при том, что если наследовать EDistrinuteTransactionException от EDBEngineError, то непонятно, что делать в случае ESocketError


 
Kolan ©   (2008-01-26 14:53) [95]

> Я не советую писать такой компонент. Это неверно в общем
> случае.

А программу?


 
guav ©   (2008-01-26 14:56) [96]

> [90] Kolan ©   (26.01.08 14:34)
> if FileExists(FFileName) then

Ну так я не делаю. В if файл может существовать, в then уже нет, это пример race condition в многозадачной среде. Можно, конечно, считать что такое редко бывает, но не в моём случае.
Если файл надо открыть, то сразу его и открыват.
Т.е.
выбор между
TFileStream.Create(FFileName, ...)
и
Handle := CreateFile(FFileName, ...)
if Handle = INVAID_HANDLE_VALUE
TFileStream.Create(Handle)

Пишу программу.


 
Kolan ©   (2008-01-26 15:04) [97]

> 96] guav ©   (26.01.08 14:56)

Ладно, не спорю, а где код ошибки или как ты о ошибке уведомляешь(о чем собссно и ветка)?


 
Игорь Шевченко ©   (2008-01-26 15:27) [98]

Sandman25   (26.01.08 14:50) [94]


> Как потом по этому reason узнать, что явилось причиной причины?


Это как ?

Причина - возбуждение исключения EDistributedTransactionException, причина его возбуждения - значение поля Reason.

Какие еще причины причин нужны ?


 
Sandman25   (2008-01-26 15:33) [99]

Игорь Шевченко ©   (26.01.08 15:27) [98]

То есть Вы ограничиваетесь 1 уровнем вложенности. А если я захочу узнать, в чем причина причины?

EDistributedTransactionException имел причиной EAuthorizationError, а тот имел причиной EDBEngineError. Грубо говоря - при попытке проведения транзакции не удалось проверить доступ, потому что не удалось подключиться к БД.
Парадигма простая - у любого Exception может быть причина. А может и не быть :)


 
Игорь Шевченко ©   (2008-01-26 15:47) [100]

Sandman25   (26.01.08 15:33) [99]


> А если я захочу узнать, в чем причина причины?


А какой в этом смысл ? Нарушается принцип объектно-ориентированного программирования: от устройства объекта не должно зависеть поведение более высоких уровней. В твоем случае у класса EDistributedTransactionException должен быть метод get_Reason, который уже сам обрабатывает всю внутреннюю кухню, но в интерфейсе этого класса тебе доступен только этот метод.


 
Sandman25   (2008-01-26 15:55) [101]

Игорь Шевченко ©   (26.01.08 15:47) [100]

А я и не призываю это правило нарушать.

Есть контракт, его нельзя изменять. Не должны бросаться исключения, специфичные для реализации класса. Грубо говоря, клиенту не должны бросаться EDBEngineError , потому что завтра мы начнем хранить данные в файлах и у нас вместо EDBEngineError будут бросаться EFileNotFoundError. Этого можно добиться, заворачивая низкоуровневые исключения в высокоуровневые. То есть и клиента не надо переписывать, и никакая специфическая информация не потеряна.


 
Игорь Шевченко ©   (2008-01-26 16:05) [102]

Sandman25   (26.01.08 15:55) [101]

Не знаю, как в Java, но в Delphi вполне себе возможно выстроить иерархию классов исключений :) При этом клиент и не узнает, что на самом деле он обрабатывает исключение EStupidUserError, а будет обрабатывать Exception и пользоваться его методами. И знать о том, что именно EStupidUserError он может обрабатывать, ему вовсе необязательно. Все в рамках контракта.


 
Sandman25   (2008-01-26 16:11) [103]

Игорь Шевченко ©   (26.01.08 16:05) [102]

В Java тоже никто не мешает объявить в контракте throws Exception и работать как в Delphi :) Но это редко будет хорошей идеей.


 
guav ©   (2008-01-26 17:17) [104]

> [97] Kolan ©   (26.01.08 15:04)
> а где код ошибки или как ты о ошибке уведомляешь(о чем собссно
> и ветка)?

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

Кстати, почему мне не нравится кидать исключения из GetLastError() кодов:
Допустим мы действительно хотим  программно обработать некоторые коды, алгоритм предусматривает это.
Например, при ERROR_MORE_DATA мы удваиваем буфер и повторяем попытку, ну и допустим при ERROR_NO_ACCESS мы пытаемся получить этот самый Access.
вот код без исключений

IoCallSucceeded := DeviceIoControl(... );
if not IoCallSucceeded then
 case GetLaseError() of
   ERROR_MORE_DATA:
     begin
       ...
     end;
   ERROR_NO_ACCESS:
     begin
       ...
     end;
 else
   RaiseLastOSError();
 end;
end;

с исключениями вроде бы логично ему выглядеть так:
try
 Win32Check(DeviceIoControl(... ));
except
 on EMoreData do
   begin
     ...
   end;
 on EAccessDenied do
   begin
     ...
   end;
end;

но на самом деле коды ошибки всё равно предстоит обработать:
try
 Win32Check(DeviceIoControl(... ));
except
 on E: EOSError do
 case E.ErrorCode of
   ERROR_MORE_DATA:
     begin
       ...
     end;
   ERROR_NO_ACCESS:
     begin
       ...
     end;
 else
   raise;
 end;
end;

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


 
ketmar ©   (2008-01-26 21:16) [105]

>[75] isasa ©(26.01.08 11:04)
а ты и вовсе не о том говоришь.
а за ловлю всех исключений надо кастрировать тупой пилой.

>[82] Sandman25 (26.01.08 13:24)
нет. AV там нет потому, что нет указателей. а вот падение жабового софта с воплем «unhandled exception» — ситуация вполне частонаблюдаемая.


 
Игорь Шевченко ©   (2008-01-26 21:35) [106]

guav ©   (26.01.08 17:17) [104]


> с исключениями вроде бы логично ему выглядеть так:
> try
>  Win32Check(DeviceIoControl(... ));
> except
>  on EMoreData do
>    begin
>      ...
>    end;
>  on EAccessDenied do
>    begin
>      ...
>    end;
> end;


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


 
Kolan ©   (2008-01-26 21:39) [107]

> Именно что-то подобное я и имел в виду

Такой еод и мне ненравится&#133


 
Игорь Шевченко ©   (2008-01-26 21:41) [108]

Kolan ©   (26.01.08 21:39) [107]


> Такой еод и мне ненравится…


Чем и почему ?


 
Kolan ©   (2008-01-26 21:54) [109]

> Чем и почему ?

Нечитается. Однако в коде с оброботкой кодов, эксепшен все равно есть&#133


 
Черный Шаман   (2008-01-26 22:27) [110]


> ketmar ©   (26.01.08 21:16) [105]
>
> >[75] isasa ©(26.01.08 11:04)
> а ты и вовсе не о том говоришь.
> а за ловлю всех исключений надо кастрировать тупой пилой.


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


 
ketmar ©   (2008-01-26 23:25) [111]

>[110] Черный Шаман (26.01.08 22:27)
если я пишу программу, то обычно до «верхнего уровня» никто не доползает, ибо ловится там, где полагается. а если что-то доползло — делается post mortem дамп и всё схлопывается. ибо это fatal error.


 
Черный Шаман   (2008-01-27 17:46) [112]


> ketmar ©   (26.01.08 23:25) [111]
>
> >[110] Черный Шаман (26.01.08 22:27)
> если я пишу программу, то обычно до «верхнего уровня» никто
> не доползает, ибо ловится там, где полагается. а если что-
> то доползло — делается post mortem дамп и всё схлопывается.
>  ибо это fatal error.


Если бы все так писали, то до сих пор сидели бы на DOS 10.х, но зато вылизанном и стабильном.

PS
Узнайте как часто в устройствах используется watch dog - при зависании устройства(отсутствии обращения к устройству х секунд) микросхема просто перегружает устройство.

PS2
Представим что вы пищете программу для ядерной энергетики, но тут ваш напарник в коде прописал исключение
if time then raise Exception.create("Пасхальное яйцо");
Программа упала при вытянутых стержнях - реактор рванул, вместо того чтобы залогировать ошибку и продолжить работу, пусть хоть и в аварийном режиме.


 
Loginov Dmitry ©   (2008-01-27 18:17) [113]

> Представим что вы пищете программу для ядерной энергетики,
> но тут ваш напарник в коде прописал исключение
> if time then raise Exception.create("Пасхальное яйцо");
> Программа упала при вытянутых стержнях - реактор рванул,
> вместо того чтобы залогировать ошибку и продолжить работу,
> пусть хоть и в аварийном режиме.


А если напарник сделает
if time then TerminateProcess(DWORD(-1), 0)
тоже будешь пытаться залоггировать? ))


 
DiamondShark ©   (2008-01-27 21:32) [114]


> вот код без исключений
>
> IoCallSucceeded := DeviceIoControl(... );
> if not IoCallSucceeded then
>  case GetLaseError() of
>    ERROR_MORE_DATA:
>      begin
>        ...
>      end;
>    ERROR_NO_ACCESS:
>      begin
>        ...
>      end;
>  else
>    RaiseLastOSError();
>  end;
> end;

Который катастрофически некорректный.


 
ketmar ©   (2008-01-27 22:41) [115]

>[112] Черный Шаман (27.01.08 17:46)
>Если бы все так писали
мне плевать, как пишут «все». многие «все» восхищаются сишарпом и вротнетом, например. я, что ли, этих недоучек наплодил?

>Узнайте как часто в устройствах используется watch dog
узнай, что мой подход никак не отменяет возможности использовать watchdog — в отличие от твоего. при этом у меня есть вся информация, чтобы разобраться, отчего оно рухнуло, а у тебя — куцый лог, по которому можно отпределить только среднюю температуру по больнице.

>Представим что вы пищете программу для ядерной энергетики
представь, что софт подобного уровня на Delphi не пишут — слишком сложный язык.
к тому же твой пример — идиотский.


 
guav ©   (2008-01-28 09:30) [116]

> [114] DiamondShark ©   (27.01.08 21:32)
> Который катастрофически некорректный.

Где ошибка ?


 
DiamondShark ©   (2008-01-28 11:41) [117]


> guav ©   (28.01.08 09:30) [116]
> > [114] DiamondShark ©   (27.01.08 21:32)
> > Который катастрофически некорректный.
>
> Где ошибка ?

В ДНК.
Каков результат RaiseLastOSError после вызова GetLastError?


 
DiamondShark ©   (2008-01-28 11:41) [118]


> guav ©   (28.01.08 09:30) [116]
> > [114] DiamondShark ©   (27.01.08 21:32)
> > Который катастрофически некорректный.
>
> Где ошибка ?

В ДНК.
Каков результат RaiseLastOSError после вызова GetLastError?


 
ketmar ©   (2008-01-28 12:01) [119]

>[117] DiamondShark ©(28.01.08 11:41)
нормальный. GetLastError() не сбрасывает переменную с кодом ошибки.


 
guav ©   (2008-01-28 12:45) [120]

> [117] DiamondShark ©   (28.01.08 11:41)

Не вижу проблемы, даже в некоторых примерах MSDN GetLastError() опрашиваентся несколько раз.



Страницы: 1 2 3 вся ветка

Форум: "Прочее";
Текущий архив: 2008.03.02;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.69 MB
Время: 0.043 c
15-1201444871
Черный Шаман
2008-01-27 17:41
2008.03.02
Delphi типы исключений.


2-1202118155
mephisto
2008-02-04 12:42
2008.03.02
Прочитать ячейку в памяти


2-1201887318
Dimo444ka
2008-02-01 20:35
2008.03.02
Как сделать распознавание строки?


2-1202148905
аа2
2008-02-04 21:15
2008.03.02
TDateTime


2-1202395681
andreoman
2008-02-07 17:48
2008.03.02
как найти узел впри помощи SimpleXML





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский