|
Программирование >> Проектирование интерфейса пользователя
Листинг 17.4. Пример процедуры верификации с условной директивой компилятора 1: #Const DebuggingOn = Tru ли False 2: Sub Assert (ByVal Test As Boolean, 3: ByVal FileName As String, ByVal AssertNumber As Long) ttlf DebuggingOn Then 5: Debug.Assert Test 6: #End If 7: End Sub Анализ Недостаток - впрочем, единственный - этого метода заключается в том, что для определения места кода, вызвавшего приостановку программы верификатором Assert, придется анализировать стек вызовов процедур либо значения параметров FileName и AssertNumber. Но это все равно гораздо проще, нежели окружать каждое отладочное выражение парой условных директив. Процедуры верификации хорошо развиты в языках С и C++, поскольку конструкция Assert реализована в них в виде макроса. Ее код автоматически включается компилятором в те места текста программы, в которых выполняется обращение к Assert. VBA такой возможностью не обладает. (В данном случае речь не идет об обычных макросах Access - говорится о макросах как о механизме развития директив компилятора.) Чтобы увидеть содержимое стека вызовов (напомним, что программа в случае неудачной верификации приостанавливает свое выполнение в строке, содержащей Debug. Assert), обратитесь к команде меню ViewCall Stack окна редактора VBA. Второй сверху элемент списка, отображаемого в диалоговом окне Call Stack, указывает на строку кода, вызвавшую приостановку в момент верификации. Рис. 17.1 соответствует ситуации, когда процедура Assert вызывается из некоторой процедуры SomeCode-ToTest при условии, что в качестве аргумента Test передавалось значение False. C !t Stack j[[661717]].Mtxhil;l.A>s t Рис Диалоговое окно Call Stack позволя- ет увидеть содержимое стека вызовов и быстро перейти к строке кода, содержащей обращение к процедуре или функции Главная особенность структуры данных, называемой стеком, состоит в том, что данные поступают в нее в одном порядке, а извлекаются в обратном, т.е. последний вошедший элемент первым же и выйдет . Информация о последовательности обращений к функциям и процедурам сохраняется в так называемом стеке вызовов. Всякий раз, когда одна функция или подпрограмма вызывает другую, стек пополняется, а при завершении последней вызванной функции (процедуры) элемент, располо- женный на вершине стека, удаляется из него. Если щелкнуть на элементе списка, иллюстрирующего стек вызовов, а затем на кнопке Show диалогового окна Call Stack (см. рис. 17.1), текстовый курсор в окне редактора перейдет на строку, содержащую вызов. Так, например, щелчок на элемента ule1 .SomeCodeToTest в представленном на рисунке примере приведет к переходу курсора на строку, в которой содержится обращение к процедуре Assert. Теперь, умея обращаться с условными директивами компиляции, вы можете не беспокоиться о принудительном удалении отладочного кода. Если такой код написан, оставьте его в покое. Возложите обязанности по его сохранению или изъятию на компилятор. Для этого достаточно изменить значение единственной константы и перекомпилировать приложение. Не нужно обрамлять условными директивами компиляции каждый вызов отладочной процедуры или функции - лучше разместить их внутри самой процедуры (функции). Другое немаловажное преимущество подобного подхода заключается в том, что отладочный код остается на месте - он всегда доступен для повторного использования и выполняет информативную, документирующую функцию. Впоследствии вы сами легко сможете определить, что именно тестировалось и каким образом. Листинг 17.5 представляет текст модуле од.has, содержащего полный набор отладочных процедур, которые мы рассмотрели в ходе этого занятия. Листинг 17.5 д.bas - набор отладочных процедур Option Compare Database 2: Option Explicit 3: iConst DebuggingOn = True 4: Private Sub DoTrap(ByVal FileName As String, ByVal TrapNumber As Dong) 5-.; Debug.Print Ловушка: & FileName & ( & TrapNumber & ) Si Stop 7: End Sub 3: Sub Trap (ByVal FileName As String, ByVal TrapNumber As Long) 9 #If DebuggingOn Then 10: Call DoTrap( FileName, TrapNumber ) 11: #End If 12:End Sub 13:Private Sub DoTrace ( ByVal FileName As String, 14: ByVal TraceNumber As Long, ByVal TraceMessage As Variant) 15: Bim Output As String 16: Output = Трассировка: & FileName & ( & 17: TraceNumber & ) в & Now & vbCrLf & 18: TraceMessage & vbCrLf 19: Debug.Print Output 20:End Sub 21:SubTrace( ByVal FileName As String, ByVal TraceMessage As String, ByVal TraceNumber As Long) 22: #If DebuggingOn Then 23: Call DoTrace(FileName, TraceMessage, TraceNumber) 24: #End If 25:End Sub 26:Private Sub DoAssert(ByVal Test As Boolean, ByVal FileName As String, ByVal AssertNumber As Long) 27: Debug.Assert Test 28:End Sub 29: Sub Assert (ByVal Test As Boolean, ByVal FileName As String, ByVal AssertNumber As Long) 30: 31: 32: ttlf DebuggingOn Then Call DoAssert(rest, #End If FileName, AssertNumber) 33:End Sub Как уже неоднократно отмечалось, предпочтительно писать короткие процедуры и функции. Просмотрев листинг 17.5, вы не увидите процедур длиннее трех-пяти строк. Функциональная часть (скажем, DoAssert) отделена от условно-директивной (Assert). Встречаются программисты, которые буквально в штыки принимают подобный стиль работы. Я же мотивирую свои действия удобством и универсальностью подхода -и-властвуй - мы уже говорили о нем: дели проблему на мелкие обозримые части, и ее решение упростится. В листинге функциональная часть кода отладочных процедур отде-I лена от условных конструкций компилятора. В этом случае можно воспользоваться процедурами тестирования даже тогда, когда отладочный режим отключен (т.е. константа DebuggingOn равна False). Эти процедуры, в названия которгх введен префикс Do, объявлены посредством служебного штификатора Private, предотвращающего возможность их случайного использования за пределами родного модуля. (Подробнее о применении подобных средств см. главу 21-й час. Основы программирования классов .) Отладочн1й код - только для чтения Отладочный код - это код только для чтения. Другими словами, наличие отладочных процедур в тексте программы не должно сказываться на результатах ее работы. Также недопустимо, чтобы Поведение программы менялось в зависимости от того, срабатывают условные директивы компилятора или нет. Программа должна работать одинаково в обоих случаях - с отладочным кодом и без такового. Различные типы кода обработки ошибок Конструкции, обрабатывающие ошибки периода разработки программы, дают вам, автору, возможность выявить спорные ситуации на самой ранней стадии работы над проектом. Код обработки ошибок во время применения приложения пользователями должен гарантировать, что программа будет работать с различными наборами исходных данных и в любых ситуациях. Чаще всего целесообразно наряду с отладочными выражениями использовать и конструкции обработки ошибок, служащие неотъемлемой частью кода приложения. Например, если файл должен существовать (это условие гарантирует возможность его дальнейшего открытия), можно применить верификатор, позволяющий протестировать код во время разработки, а также включить в текст постоянную конструкцию, проверяющую факт существования файла: Call Assert ( FileExists ( FileName ), ModuleName , 1 ) If (FileExists ( FileName ) Then Какой-то код
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |