- •1.Розробка системи оперативної довідки
- •1.1.Меню Help
- •1.2. Малюнок 1. Вікно довідки. Кнопка Help в екранній формі
- •1.4.Виклик контекстно-залежної довідки кнопкою What's This?
- •1.5. Малюнок 2. Екранна форма, у якій установлена кнопка виклику контекстної довідки. Використання html Help Workshop
- •1.5.1.Створення проекту системи оперативної довідки
- •Малюнок 3. Діалогове вікно New.
- •Малюнок 4. Діалогове вікно Existing Files.
- •1.5.2.Таблиця змісту
- •Малюнок 5. Вікно щойно створеного проекту.
- •Малюнок 6. Заповнення таблиці змісту.
- •1.5.3.Предметний покажчик
- •Малюнок 7. Заповнення контекстного вказівника.
- •1.5.4.Додавання в проект html-файлів розділів довідки
- •1.5.5. Малюнок 8. Заготівля html-файлу, оформлена html Help Workshop. Зв'язки між файлами розділів і url
- •1.6.Додавання і видалення файлів розділів довідки
- •Малюнок 9. Діалогове вікно Topіc Fіles.
- •1.7.Компіляція системи оперативної довідки
- •1.8.Контекстно-залежні розділи довідки
- •Малюнок 10. Діалогове вікно Options.
- •Малюнок 11. Wizard Selection
- •Малюнок 12. Вікно Application Builder.
- •1.8.1.Включення файлу відображення в проект системи оперативної довідки
- •1.8.2. Малюнок 13. Включення файлу відображення в проект системи оперативної довідки. Зв'язування HelpContextіD з html — файлами розділів довідки
- •1.8.3. Малюнок 14. Діалогове вікно для організації зв'язування файлів розділів довідки і HelpContextі у додатку. Розділи довідки, що викликаються кнопкою What's This?
- •Малюнок 15 Екранна форма Visual FoxPro, налаштована на використання довідки What's This?
- •1.9.Поширення готової системи оперативної довідки
- •2.Пошук і обробка помилок, тестування проекту
- •2.1.Проблема помилок у програмному продукті
- •2.2.Пошук помилок у програмному коді
- •2.2.1.Синтаксичні помилки
- •2.2.2.Логічні помилки
- •2.2.3.Виключення
- •2.3.Розбивка коду на модулі для мінімізації помилок
- •2.4.Помилки при передачі параметрів
- •2.5.Використання команд exіt і return
- •2.6.Обробка ушкоджених файлів
- •2.7.Тестування та налагодження додатків
- •2.7.1.Технологія тестування
- •2.7.2.Створення середовища для тестування
- •2.7.3.Створення тестових наборів даних, що забезпечують повноту накриття додатка
- •2.7.4.Документування тестових наборів
- •2.8.Методика перехоплення помилок
- •2.9.Налагоджувальник
- •Малюнок 16. Налагоджувальник Visual FoxPro.
- •2.9.1.Використання вікна Trace
- •Малюнок 17. Панель інструментів налагодження
- •Малюнок 18 Діалогове вікно Breakpoints
- •2.9.2.Використання вікна Locals
- •Малюнок 19. Діалогове вікно Locals
- •2.9.3.Використання вікна Watch
- •Малюнок 20. Діалогове вікно Watch.
- •2.9.4.Діалогове вікно Call Stack
- •2.9.5.Використання вікна Debug Output
- •2.9.6.Діалогове вікно Event Tracking
- •Малюнок 21. Діалогове вікно Event Tracking.
- •2.10.Використання Coverage Profiler
- •Малюнок 22. Додаток Coverage Profiler у режимі відображення покриття.
- •2.11. Малюнок 23. Додаток Coverage Profiler у режимі відображення профілю. Використання процедур обробки помилок
- •2.11.1.Використання методів обробки події error в об'єктах
- •3.Література
- •4.Перелік ілюстрацій
2.4.Помилки при передачі параметрів
Дуже поширені помилки при передачі параметрів у процедури і функції. Часто кажуть, що може відбутися як запланована, так і незапланована передача параметрів. Що таке “незапланована” передача параметрів? У Visual FoxPro будь-яка перемінна, оголошена з кваліфікаторами PUBLІC і PRІVATE, автоматично стає доступною й у викликаній підпрограмі. Таким чином, можна ненавмисно перевизначити однойменну перемінну у викликуваній підпрограмі. При цьому Visual FoxPro не кваліфікує таке перевизначення як помилку і відповідно ніяк на нього не реагує. Очевидно, вважається, що розроблювач саме так і задумав.
Візьміть собі за правило не використовувати імена які повторюються в різних модулях програми, що викликають один одного в процесі виконання. Якщо у процедурі що викликується потрібно використовувати перемінну, передайте параметр за значенням і привласніть його локальної перемінний у викликуваній процедурі. Випадкове перевизначення перемінних відноситься до тих помилок, відшукати які буває важче, ніж голку в стозі сіна.
Якщо ви не упевнені, чи використовується однойменна перемінна у програмі, що визивала, убезпечте себе дуже простим прийомом. Кваліфікатори перемінних LOCAL і PRІVATE роблять їх доступними тільки в межах викликаної функції чи процедури.
Для передачі значень параметрів у локальні перемінні використовуйте оператор
LPARAMETERS, а не PARAMETERS.
Ще один нюанс у механізмі передачі параметрів, на якому має сенс зупинитися, — як їх передавати: за значенням чи по посиланню? Коли параметр передається по посиланню, то викликана процедура використовує саме ту перемінну програми що визиває, на яку вказує посилання. Якщо в процедурі значення параметра змінюється, то ця зміна торкнеться і програму що визиває. З іншого боку, якщо передавати параметр за значенням, то в процедурі буде створена нова локальна перемінна для збереження значення параметра. Ця локальна перемінна ніяк не вплине на програму що визиває.
За замовчуванням при виклику процедури в команді DO Visual FoxPro передає параметри8 по посиланню, якщо тільки параметр в операторі виклику не укладений у дужки. А от при виклику функції за замовчуванням параметр передається за значенням (у вираженні виклику функції список параметрів вміщують в круглі дужки). Для того щоб передати у функцію параметри по посиланню, можна використовувати два способи.
Установити SET UDFPARMS TO REFERENCE.
Перед ідентифікатором параметра в списку вставити символ @.
Якщо виникає потреба передати масив у процедуру чи функцію, передавайте його по посиланню. При спробі передати його за значенням у підпрограму потрапить тільки перший елемент.
2.5.Використання команд exіt і return
Програмістів, що працюють у середовищі Visual FoxPro, підстерігає спокуса — використовувати безліч команд EXІT для виходу із циклу і RETURN для виходу з підпрограми (процедури чи функції).
Ніякої гострої необхідності в подібній практиці немає. Усе, що потрібно, — це небагато подумати і скорегувати логіку виконання циклу. Розглянемо наступний приклад:
PROCEDURE GetProdID
IF EMPTY (m.lcProdlD)
RETURN
ELSE
<Код перевірки IcProdID наявності у PRODUCT. DBF>
RETURN
ENDIF
USE
RETURN
У цій процедурі є три оператори виходу з підпрограми. Переглянута версія буде виглядати значно елегантніше:
PROCEDURE GetProdID
IF! EMPTY (m. lcProdlD)
< Код перевірки IcProdID наявності у PRODUCT. DBF >
ENDIF
USE
RETURN
Чому необхідно звернути увагу на небажаність численних точок виходу? По-перше, у такій програмі складніше розібратися, уловити по тексту програми хід її виконання. Але набагато важливіше те, що при наявності безлічі точок виходу розроблювачу важко устежити, чи завжди в процесі виконання реалізуються всі необхідні етапи обробки. Наприклад, чи повинна процедура в приведеному вище фрагменті перед виходом закривати поточну таблицю (це виконується командою USE)? У першому варіанті поточна таблиця не закривається ніколи, а в другому — закривається перед виходом при будь-яких умовах.
У цих же прикладах видна ще одна небезпека безлічі команд EXІT і RETURN. Дуже легко при цьому одержати фрагменти коду, що ні при яких умовах не виконуються. У першому варіанті оператор RETURN є в обох гілках умовної конструкції ІF… ELSE…ENDIF. Тому команда USE ніколи не буде виконана.
По команді EXІT відбувається вихід з конструкцій типу DO… ENDDO, FOR…ENDFOR і SCAN… ENDSCAN до завершення повного циклу. Наприклад, у приведеному нижче фрагменті коду в циклі проглядаються записи для того, щоб визначити серійний номер виробу, що усе ще знаходиться на складі. Оператор SEEK знаходить запис, що відповідає заданому ідентифікатору. Потім у циклі SCAN… ENDSCAN проглядаються всі записи для цього виробу доти, поки не буде виявлена перший з них, що вказує на наявність виробу на складі.
USE RentProd ORDER ProdID
pcSerial = SPACE(4)
SEEK m. pcFindProdID
SCAN WHILE m.pcFindProdID = cProdID
IF linstock
pcSerial = cSerial
EXIT
ENDIF
ENDSCAN
У цьому фрагменті є два варіанти завершення циклу SCAN… ENDSCAN. Якщо буде знайдено хоча б один запис із установленим значенням у поле linstock, відповідний серійний номер буде зафіксований у перемінної pcSerial і цикл завершиться без перегляду інших записів. У противному випадку перегляд буде продовжуватися доти, поки в таблиці ще будуть залишатися записи з тим же значенням ідентифікатора виробу в поле cProdі.
Існує можливість уникнути цього додаткового оператора EXІT. Слід зазначити, що його не можна просто викреслити з програми, оскільки в цьому випадку буде продовжуватися перегляд записів і після того, як буде знайдено необхідний запис. У результаті не тільки витратиться зайвий час (хоч і дрібниця, але шкода), але головне — буде повернутий не той серійний номер. Цю проблему удалося вирішити в приведеному нижче варіанті коду.
USE RentProd ORDER ProdID
pcSerial = SPACE(4)
SEEK m. pcFindProdID
SCAN WHILE EMPTY(pcSerial) AND m.pcFindProdID = cProdID
IF linstock
pcSerial = cSerial
ENDIF
ENDSCAN
Тепер у команді SCAN перевіряється не тільки рівність кодів ідентифікаторів, але і стан перемінної pcSerіal — чи записаний у неї вже запис ні. Якщо перемінна заповнена яким-небудь значенням, виходить, запис був знайдений і цикл припиняється. Відбувається це “природним” образом — з ініціативи SCAN, а не “штучно” через EXІT.