Як ефективно обробляти помилки в додатках Access, MS Office, Програмні керівництва, статті

 

Як всім вам добре відомо, програм без помилок не буває. Навіть такі монстри, як Microsoft регулярно публікують списки офіційних багів, патчі і.т.д. У додатках на основі Access, що розробляються одним-двома програмістами ймовірність появи помилок (Run-Time errors) на стадії експлуатації дорівнює 100%. Наша задача таким чином, полягає не тільки в тому, щоб виключити помилки на стадії програмування і тестування, а й ефективно виявити і усунути неполадки в процесі роботи. Тут виникає 2 проблеми:


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


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


Зіткнувшись в процесі роботи з цими проблемами, я дозволю собі запропонувати один з варіантів рішення. Буду радий його обговорити, поліпшити, вислухати альтернативи. Також я буду радий, якщо мій досвід комусь допоможе


Компоненти рішення


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


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


Отже, для отримання повної картини події нам допоможе наступна інформація:


1) Ім’я машини, на якій виникла проблема і ім’я користувача домену


Для того, щоб визначити ім’я робочої станції, на якій виконується Access, достатньо прочитати значення змінної оточення ENVIRON (“COMPUTERNAME”), і ім’я пользвователя – ENVIRON (“USERNAME”), проте в ряді випадків (наприклад якщо у вас Win Me робочі станції з UNIX PDC) це може не спрацювати. Є більш надійний спосіб, заснований на API виклики – в доданому файлі ви знайдете Class Module SystemInfo в якому реалізовані функції. Так чи інакше, нам знадобляться функції GetUserName () і GetCompName ()







Public Function GetUserName()


    Dim si As New SystemInfo


    GetUserName = si.UserName


End Function


Public Function GetCompName()


    Dim si As New SystemInfo


    GetCompName = si.ComputerName


End Function


2) Шлях до бази та ім’я користувача MS Access


Легко визначаються вбудованими функціями:







CurrentDB.Name


Application.CurrentUser


3) Ім’я бібліотеки, що викликала помилку, номер та опис помилки


Вбудований об’єкт Err при виникненні помилки заповнюється аттрібутом помилки. Вважати їх просто:







Err.Source


Err.Number


Err.Description


4) Дата і час виникнення


Вставляємо поточну дату і час: Now ()


Однак більш корисно вставляти не тільки текущаю дату / час на машині користувача, а й те, що в цей час на сервері, так як часто помилка буває викликана неузгодженістю цих величин. Якщо вставляти час користувача і додатково час сервера (наприклад мати поле TimeStamp) то можна проводити додатковий аналіз узгодженості годин користувача з сервером


5) Ім’я активної форми / звіту, Ім’я активного елементу управління, попереднього елемента управління та його батька


Для цієї мети скористаємося маловідомим об’єктом Screen:







Function collectActiveControls(ByRef AC As String, ByRef AR As String, ByRef AF As String, ByRef pc As String, ByRef PCP As String)


On Error Resume Next


AC = Nz(Screen.ActiveControl.Name, “”)


AR = Nz(Screen.ActiveReport.Name, “”)


AF = Nz(Screen.ActiveForm.Name, “”)


pc = Nz(Screen.PreviousControl.Name, “”)


PCP = Nz(Screen.PreviousControl.Parent.Name, “”)


End Function


Я виніс визначення цих величин в окрему функцію, так як воно саме по собі може викликати помилки (наприклад, якщо активний звіт відсутній), однак якщо визначати їх у функції ReportError, то значення Err.Description, Err.Number і Err.Source в разі помилки виявляться скинутими і заміненими на помилку визначення активних елементів управління. Тому я спершу зчитую параметри об’єкта Err в змінні, а потім запускаю collectActiveControls


6) Ім’я процедури VBA, в якій сталася помилка


Це найбільш морочлива частину, так як в VBA немає засобу, що дозволяє коду дізнатися, яка процедура виконується в даний момент. Єдиний спосіб це зробити, – заздалегідь записати в обробник помилки ім’я процедури. Ні вам ні мені цього робити, природно, не хочеться. На щастя, цю роботу можна автоматизувати. З цим справляється Error Handler, що поставляється з Microsoft Office Developer Edition, проте ODE птах рідкісна, тому я віддаю перевагу Error Handler Builder від Zada ​​Solutions, благо вільне, завантажити його можна тут: www.zada.com.au/accessaddins.htm


Що ж уміє цей софт? Ви можете створити шаблон обробника помилок і потім переробити за його зразком виділену процедуру (або всі процедури).


Шаблон виглядає приблизно так:







“Error-handler inserted on [DATE] at [TIME] by [AUTH]


“[NOTE]


On Error GoTo Whoops


[BODY]


Goon:


Exit [PRTY]


Whoops:


ReportError “[FUPN]”


Resume Next



Все, що в квадратних дужках замінюється на конкретні значення. Як це працює? Зустрічаючи помилку ми переходимо до мітці Whoops, викликаємо функцію ReportError, c ім’ям модуля і функції в якості аргументу. Функція збирає всю інформацію, пише її в прілінкованную серверну табличку, далі в залежності від режиму повідомляє про помилку користувачеві і продовжує роботу. Тут можливі два варіанти:


1) Робота триває з наступного рядка (Resume Next) – я віддаю перевагу саме цей варіант, тому що мій досвід підказує, що більшість помилок не фатальні, і можна продовжувати працювати


2) Варіант, коли в разі помилки необхідно вийти з функції, не здійснюючи більш ніяких дій – просто замініть Resume Next на Resume Goon


Приклад функції, обробленої Error Handler:







Function ErrorGenerator()


“Error-handler inserted on 20.07.2003 at 16:06 by Andrew



On Error GoTo Whoops


   


    MsgBox 1 / 0


   


Goon:


Exit Function


Whoops:


ReportError “mdService_ErrorGenerator”


Resume Next


End Function



Нарешті функція ReportError:







Function ReportError(Optional PName As String)


“Pname – ім’я процедури


Dim Q As String


Dim AC$, AR$, AF$, pc$, PCP$, ES$, ED$, EN$


Q = Chr(34)


“Код помилки, бібліотека та опис


EN = Err.Number


ES = Err.Source


ED = Err.Description


“Збираємо інформацію про елементи керування


Call collectActiveControls(AC, AR, AF, pc, PCP)


“Відключаємо попередження про вставлення даних у таблицю


DoCmd.SetWarnings False


“Вставляємо в таблицю зібрані дані:


        CurrentDb.Execute “INSERT INTO Bugs (Machine, User, AccessUser, MDate, ErrNumber, ErrDescription, ErrSource, ActiveForm, ActiveControl, ActiveReport, PreviousControl, PCParent, [Procedure]) VALUES ” _


    & “(“” & GetCompName() & “”,”” & GetUserName() & “”,”” & Application.CurrentUser & “”,”” & Now() & “”,” & EN & “,” & Q & ED & Q & “,”” & ES & “”,”” & AF & “”,”” & AC & “”,”” & AR & “”,”” & pc & “”,”” & PCP & “”,”” & PName & “”);”


DoCmd.SetWarnings True


“Тут вирішуємо – чи ставити до відома користувача


    Select Case DebugMode


    Case 0


“Режим відладки – для себе


        Stop


    Case 1


“MsgBox користувачеві. Не рекомендується


MsgBox “Виникла непередбачена помилка. Якщо подібна помилка буде виникати надалі, будь ласка зверніться до розробника”, vbOKOnly & vbExclamation, “Не хотілося б вас турбувати, але …”


    Case 2


“Виводимо текст опису помилки в рядок стану, чекаємо 1 секунду (мені особисто достатньо) і очищаємо рядок.


        SysCmd acSysCmdSetStatus, ED


        pause (1)


        SysCmd acSysCmdClearStatus


    Case 3


“Не робимо взагалі нічого


    End Select


End Function



В принципі все повинно бути зрозуміло – збираємо інформацію і записуємо в таблицю. Цікаве тут наприкінці: залежно від DebugMode







Function DebugMode()



    DebugMode = 2


“0 – Stop


“1 – MsgBox


“2 – текст у рядок стану


“3 – мовчки


End Function



-Пригнічується повідомлення користувачу, або блимає на секунду в рядку стану, так, щоб встигли помітити ви (якщо не встигаєте, замініть pause (1) на pause (x) – кількість секунд. Функція pause (параметр hg – відображати чи пісочний годинник):







Function pause(seconds As Long, Optional hg As Boolean = True)


Dim t As Double


If hg Then


    DoCmd.Hourglass True


End If


t = Now


While DateDiff(“s”, t, Now()) < seconds


“DoEvents


Wend


If hg Then


    DoCmd.Hourglass False


End If


End Function



Як цим насолоджуватися?


Тут можна завантажити файл з макетом таблиці і всіма процедурами – їх потрібно вставити у вашу базу. Якщо у вас клієнт / сервер, таблицю bugs краще експортувати на сервер і прілінковать. Якщо ні – раджу зробити окрему “адмінських” базу, закинути таблицю туди і прілінковать до всіх клієнтських.


Далі слід завантажити та встановити Error Handler Builder –www.zada.com.au/accessaddins.htm Написати і зберегти макет обробника помилок. Прогнати його по всіх процедур і функцій, попередньо видаливши ті обробники, що там є. Звертаю увагу на те, що на самі функції обробки помилок обробники вставляти не треба.


Готово.


Всі помилки сипляться в табличку. Вам залишається сидіти і спостерігати. Можна написати форму з таймером, повісити Алерт адміну, ітд. Зверніть увагу, що якщо ви вибрали DebugMode 2 або 3 то користувач помилок не помітить, тому стежте за ними самі. У табличці Bugs передбачено поле Solution, куди рекомендую записувати з’ясування причин і метод рішення, – потім при виникненні аналогічної помилки (або послідовності) буде легше знайти рішення.


Література по темі:


1) Литвин, Гетц, Гілберт. Access 2000 Керівництво розробника т. 2. Київ, BHV 2001


2) В.І. Король. Visual Basic.Net, Visual Basic 6.0, Visual Basic for Applications 6.0, М.: Кудіц-Образ 2002


3) М.Теллес, Ю.Хсіх. Наука налагодження. М.: Кудіц-Образ 2003



 

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*