Когда имеет смысл ставить "on Error Resume Next"

  • Автор темы Omh
  • Дата начала
O

Omh

Доброго дня разработчикам!

Как известно, у нормального лотусного программиста функция выглядит так:
Код:
Function Function_name
On Error Goto Errh
'Тело функции
Exit Function
Errh:
Call ErrHandler
Exit Function
End Function
Сам errorhandler может немного отличаться, я про саму конструкцию.

Но при этом внутри ф-ии иногда используется конструкция вида
Код:
On Error Resume Next
'Потенциально опасная операция
On Error Goto Errh
Хотел поинтересоваться, кто и когда использует вторую конструкцию и вообще стоит ли её использовать.

Что бы не быть голословным приведу примеры, что зачастую ставлю внутрь "On Error Resume Next":
1. Set doc = db.GetDocumentByID/UNID(ID) (ну это у меня вынесено в отдельную ф-ию)
2. Call Dc.AddDocument(doc)
3. MkDir
4. Kill
5. RmDir
6. Dir

Иногда использую такую конструкцию (может кому пригодиться):
Код:
On Error Resume Next
Error 1001
'Потенциально опасная операция
On Error Goto Errh
If Err <> 1001 Then 'Потенцально опасная операция таки вывалилась :)

Вообщем, вопрос таков: кто для чего испрользует эти конструкции, стоит ли вообще их использовать и где кончается нормальная практика и начинается злоупотребление? :)
Спасибо!
 
A

Akupaka

не ну взял и все наиболее употр*цензура*емые варианты перечислил...
например, NotesDatabase.Open()...
в общем, в любом случае, когда нужно получить результат некоторой операции и пойти дальше, а не париться с обработкой...
 
O

Omh

Кстати db.Open я раньше тоже иногда ставил в такой обработчик.
Сейчас юзаю конструкцию, которая пока что работает железно:
Код:
dim db as New notesDatabase("", "")
Call db.Open(Some_Server, Some_Path)
if db.IsOpen then
'Всё в поряде
else
'Скорее всего ошибка в Some_Server/Some_Path
End if

Я к чему спросил-то?
Тут услышал из уст коллеги, что On Error Resume Next не надо использовать никогда.
Вот и решил узнать, один ли я столь убог, что юзаю On Error Resume Next
 

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
Я редко использую, т.к. в случае ошибки часто нельзя выполнять следующую строку.
Например:
Код:
Set doc = db.GetDocumentByID/UNID(ID)
Call doc.ReplaceItemValue("", "")

Обычно я использую следующую конструкцию:
Код:
Function Function_name
On Error Goto Errh
'Тело функции
Process:
'Тело функции
Exit Function
Errh:
'обрабатываем ошибку, если надо
Resume Process
End Function
 
A

Akupaka

Тут услышал из уст коллеги, что On Error Resume Next не надо использовать никогда.
дай ему под коленку, скажи, что убогие программеры кодебая передают привет! :)
а чем он это аргументировал? или он какой-то явист или ему подобный, лихо использующий try {} catch {}? :)
 
O

oshmianski

мои 5 копеек.
вообще у нас принято в обязательном порядке использовать обработчик ошибок вида

function f_name (params) as boolean
On Error Goto ErrorHandler
f_name = false
'код
f_name = true
Ex:
Exit Function
ErrorHandler:
'обработка ошибки
Resume Ex
End Function

что касается Resume Next, то часто использую в связке с db.GetDocumentByUNID

on error 4091 resume next
Set doc = db.GetDocumentByUNID (unid)

if (doc is Nothing) then

ну и так далее.

использовать же

On Error Goto ErrorHandler
On Error Resume Next
'код для проверки
On Error Goto ErrorHandler

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

olegber

Как мне кажется все ошибки должны обрабатываться в одном месте:

sub Test
on error goto ErrEx:

exit sub

ErrEx:
Select Case Err
Case 1001:print "User Error 1001"
Case 1002:print "User Error 1002"
Case 1003:print "User Error 1003"
Case 1004:print "User Error 1004"
Case 4091: resume Next
Case Else
print cstr(Er)
End Select
exit sub
end sub
 
A

Akupaka

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

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
472
как и везде кетч эксепшн и продолжение выполнения, происходит в местах, где использование кода (часто не тобой написанного) может вызвать исключение, но оно ситуативно некритично и решение нужно вынести в др. месте программы (а здесь - отметить ситуацию)

как пример - файловые операции типа удаления и создание каталога, файлов
файл удален уже или не был создан, каталог уже существует (а доп. проверка - тот же код)

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

abbatik

Вот еще всплыл случай необходимости использования.

Во время работы ночного агента пришлось поставить обработчик, т.к. проблема с 32к при сохранении.

On Error Resume Next
Err = 0
mdoc.Save True, False
If Err Then
Print {...}
End If
On Error Goto errorproc
 
A

Akupaka

ага, я на сохранение дока тож вешаю, но иначе
Код:
On Error Resume Next
if not(mdoc.Save(True, False)) then
If Err <> 0 Then
...
end if
end if
On Error Goto errorproc
потому как ошибка бывает не только на 32К, а и прав может не хватить и вообще, сохранение штука вредная
правда, если док не новый, и фактически не был изменен, то Save вернет False, поэтому дополнительная проверка на код ошибки не мешает...
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
На собственном опыте убедился, что если можно (а оно можно, если постараться), то лучше обойтись без On Error Resume Next.
Был в шоке, когда в вызываемой процедуре для GetDocumentByUNID указал On Error Resume Next, но обработчик ошибок вызывающей процедуры выдал мне Err = 4091! Это было... точно не помню, вроде в фоновых агентах. Стали ставить принудительно Err = 0, но в некоторых особо хитрых случаях (не помню - здесь вы мне можете или верить или не верить) не работало и это!
Пришли к тому, что лучше использовать культурный метод для обнуления ошибки On Error Goto 0.
Применительно к GetDocumentByUNID это выглядит так:
Код:
Function GetNDbyUNID(NDB As NotesDatabase, UNID As String, ND_Result As NotesDocument) As Boolean
Set ND_Result = Nothing
If NDB Is Nothing Then Exit Function

On Error 4091 Goto Err4091
Set ND_Result = NDB.GetDocumentByUNID(UNID)
If Not ND_Result Is Nothing Then
GetNDbyUNID = IsDocAccessed(ND_Result, True)	'Где-то здесь уже выкладывал эту функцию
Else
On Error Goto 0								'Собственно оно и есть
End If

Exit Function

Err4091:
Resume Next										'"Финт ушами"
End Function
Но это если мы хотим использовать одну и ту же функцию в любых случаях.
Если не запариваться на повторность кода, то можно писать что хочешь и как хочешь, - копипастить и в каждом случае производить отладку заново...
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
Тут услышал из уст коллеги, что On Error Resume Next не надо использовать никогда.
Вот и решил узнать, один ли я столь убог, что юзаю On Error Resume Next
горячо поддерживаю твоих коллег :)

Обьясню, уже достаточно давно всё дроблю на мелкие функции, которые обязательно возвращают True если доходят до конца
а основное ядро просто глядит на возврат функции тем самым лавируя по логике
в мелких же функция никогда не юзается Resume Next там или выход или обход конкретной ошибке
 
A

Akupaka

горячо поддерживаю твоих коллег
и тебе тоже под коленку, ага

Стали ставить принудительно Err = 0, но в некоторых особо хитрых случаях (не помню - здесь вы мне можете или верить или не верить) не работало и это!
очень интересно, что не срабатывало О.о еще было бы лучше знать наверняка глюк ли это нотеса/домино или в коде недочет...
тоже сбрасываю ошибку с пом Err = 0.

Пришли к тому, что лучше использовать культурный метод для обнуления ошибки On Error Goto 0.
эм... а где написано, что эта конструкция сбрасывает ошибку?.. надо потестить, но вроде как только Resume сбрасывает код ошибки.

вообще, на очень интересный момент ты указал. спасибо :)
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
очень интересно, что не срабатывало О.о еще было бы лучше знать наверняка глюк ли это нотеса/домино или в коде недочет...
тоже сбрасываю ошибку с пом Err = 0.
Точно недочёт кода не мог быть! Так и было раньше написано в функции Err = 0, от того столько недоумения и вызывает иногда то, что отказывается работать, что столько лет пропахало без проблем..

эм... а где написано, что эта конструкция сбрасывает ошибку?.. надо потестить
<!--QuoteBegin-"Help"+-->
<span class="vbquote">("Help")</span><!--QuoteEBegin-->GoTo 0
If errNumber is specified, specifies that when the error occurs, the error should be handled by the most recent general On Error statement that specifies no error number.
If errNumber is omitted, no errors are handled in the current procedure.[/quote]Или здесь:
И чуток ниже там есть "How does On Error work?".
Но эту штуку я первый раз увидел не в хелпе, а на форуме Интертраста несколько лет назад:


, но вроде как только Resume сбрасывает код ошибки.
Это верно.
Что советуют, например, здесь:
не работает. Нужно сначала уйти на метку (у меня это Err4091 (отредактировал)), а с неё уже Resume Next, а потом чтобы перед выходом из функции обязательно On Error Goto 0, - тогда всё тип-топ! :)

вообще, на очень интересный момент ты указал. спасибо :)
Не за что; всегда рад ;)
 
A

Akupaka

VladSh
проверил, можешь и сам проверить :)

Код:
	On Error Resume next
Error 1000, "Error 1"
On Error GoTo 0
If Err <> 0 Then
MsgBox "Error: " & Error & " = " & CStr(err)
End If

или я не так понял? :)

Добавлено:
If errNumber is omitted, no errors are handled in the current procedure.
это означает лишь, что все ошибки передаются в вызывающую процедуру, или в стандартный обработчик Notes, если стек вызовов пуст (надеюсь понятно выразился, бо может фраза и не совсем корректна)
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
Akupaka, не, так не будет работать я чуть выше на этом специально остановился.

Добавлено:
это означает лишь, что все ошибки передаются в вызывающую процедуру, или в стандартный обработчик Notes, если стек вызовов пуст (надеюсь понятно выразился, бо может фраза и не совсем корректна)
В том-то и дело, что у меня при Err = 0 ошибки в некоторых случаях передавались вверх, а после On Error Goto 0 перестали.
 
A

Akupaka

ага, вероятно, что я таки не так понял
не работает. Нужно сначала уйти на метку (у меня это ErrH), а с неё уже Resume Next, а потом чтобы перед выходом из функции обязательно On Error Goto 0, - тогда всё тип-топ! smile.gif

напиши, пож, свой пример полной обработки кода, чтобы можно было оценить наглядно, а не догадками? :)


Добавлено:
В том-то и дело, что у меня при Err = 0 ошибки в некоторых случаях передавались вверх
О.О интересно, никогда не встречал, и не слышал
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
Akupaka, дык вот жи он: коммент 12.

Добавлено:
После
Код:
Err4091:
Resume Next
Err уже = 0 (поэтому я там на Nothing проверяю), но если не поставить там On Error Goto 0, то в вызывающей проце обработчик в каких-то специфических случаях казал эту ошибку, т.е. On Error Goto 0 обязателен для корректного "подавления" :)
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!