Ошибка VBA "Bubble Up" - PullRequest
       27

Ошибка VBA "Bubble Up"

3 голосов
/ 14 сентября 2009

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

Ускоренный курс по программированию в Excel через Google Книги

Но я не уверен, почему он рекомендует это, и он действительно не объясняет.

Может кто-нибудь сказать мне, почему я должен помещать обработку ошибок в КАЖДУЮ процедуру вместо использования "пузыря"? Или, по крайней мере, вы знаете, почему автор говорит, что нет?

Спасибо.

Ответы [ 5 ]

13 голосов
/ 14 сентября 2009

Короткий ответ на ваш первый вопрос: «Вы не должны ставить обработчик ошибок в каждую процедуру».

Сказать, что «каждая процедура должна иметь обработчик ошибок» - это вообще ужасный совет. Недостатки обработки ошибок VBA много обсуждались в других местах. Концептуально, тем не менее, это не так уж и отличается от более стандартной формы обработки исключений, встречающейся в других языках. Применяется большинство лучших практик из этих языков. Вы должны обрабатывать ошибки на самом низком уровне, где их обработка имеет смысл. Иногда это происходит в процедуре, где произошла ошибка, часто нет.

Например, UDF VBA, вызываемый из вашей рабочей таблицы, должен обязательно иметь EH, который гарантирует, что вы возвращаете значение ошибки Excel в вызывающую ячейку (я) вместо того, чтобы перетаскивать пользователя в редактор кода с сообщением об ошибке. Однако код, который вы вызываете из этого UDF, может и не понадобиться. На самом деле, часто самая значимая вещь, которую может сделать внутренняя процедура при возникновении ошибки, - просто позволить ей пройти вверх по стеку, чтобы она могла получить код, который знает, что с ней делать. Это действительно зависит от рутины.

Ответ на ваш второй вопрос заключается в том, что автор, похоже, не очень хорошо понимает обработку исключений. Он признает, что обработка ошибок зависит от контекста, но затем, похоже, предполагает, что каждая процедура должна локально выбирать между «исправить проблему прямо здесь и возобновить выполнение» и «завершить программу». Он пропускает обычно правильный вариант, который гласит: «Убирайся на месте и поднимай проблему наверх». Поэтому процедуры, не требующие локальной очистки, должны просто позволять ошибкам «всплывать».

1 голос
/ 15 сентября 2009

Мои 2 цента: Вы должны поместить обработчики ошибок во все публичные процедуры и события. Это означает, что процедура в нижней части стека вызовов всегда будет иметь обработчик ошибок. Затем добавьте обработчики ошибок в другие процедуры, так как это имеет смысл. Если ошибка возникает в процедуре, которая не имеет обработчика ошибок, она «всплывает» до обработчика ошибок верхнего уровня, где она регистрируется / отображается профессиональным образом. Сценарий, в котором вы можете захотеть добавить обработчик ошибок в частную (низкоуровневую) процедуру: Код должен быть быстрым. У вас есть редкое условие, которого можно избежать, но оно заставит вас выполнить дорогостоящий логический тест внутри цикла (или, что еще хуже, вложенного цикла). Вы можете выполнить логический тест в обработчике ошибок, и если будет сказано «редкий случай», сделать исправление и продолжить. Поскольку условие встречается редко, вы увидите увеличение производительности для большинства условий. Если обработчик ошибок не может выяснить и устранить проблему, повторно поднимите ошибку, чтобы она появилась в стеке.

Очевидно, это всего лишь один сценарий.

0 голосов
/ 14 сентября 2009

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

Sub test()
  On Error GoTo e
  Dim c As Integer
  Dim d As Integer
  c = add(5, 0)
  d = divideWhichManagedItsOwnErrorHandling(5, 0)
  d = divide(5, 0)

  Exit Sub

e:
  MsgBox "error occurred somewhere for which I don't know what to do: " + Err.Description
End Sub

Function add(a As Integer, b As Integer) As Integer
   add = a + b
End Function

Function divide(a As Integer, b As Integer) As Integer
   divide = a / b 'if error occurs, it will "bubble-up" to the caller.
End Function

Function divideWhichManagedItsOwnErrorHandling(a As Integer, b As Integer) As Integer
  On Error Resume Next
  Dim result As Integer
  result = a / b
  If Err.Number = 11 Then 'if divide by zero occurred, user must have passed 0 for b
    result = 0 ' return 0 if the divide by zero occurs. 
  End If
  divideWhichManagedItsOwnErrorHandling = result
End Function
0 голосов
/ 14 сентября 2009

Я не уверен, какова обработка ошибок по умолчанию в VBA, но поскольку его Visual Basic для приложений и эти приложения включают в себя такие вещи, как excel и word, я предполагаю, что появится только диалоговое окно, которое не будет полезным для пользователь.

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

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

0 голосов
/ 14 сентября 2009

Я вижу, по крайней мере, одну причину в его объяснении: потому что это лишает вас выгоды от Резюме (следующее).
Кроме того, вы не будете знать, в каком модуле произошла ошибка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...