Технологія розробки додатків: практичний приклад на VB

Ми будуємо свої системи так само,
як брати Райт будували свої літаки:
створюємо всю систему цілком, запускаємо її
– Нехай вона розвалиться! – І починаємо все спочатку.
Проф. Грехем, збірник Software Engineering, 1970 р.

У цій статті на простому прикладі …

У цій статті на простому прикладі проілюстровані ключові тези про стиль розробки програм, які спростовують твердження, наведене як епіграф. Більше того, цей матеріал підготовлений в якості практичного прикладу реалізації ідей, висловлених в циклі статтею "Поговоримо про програмування. Роздуми колишнього програміста". Загальний сенс сучасного підходу до розробки додатків полягає у переході від послідовного виконання трьох основних етапів розробки (проектування, кодування і налагодження) до паралельного.

Точніше, принцип цієї технології полягає в покрокової реалізації проекту, що спирається на такі основні положення:


  1. Використання методики "снісходящіе проектування" (інші назви: "покрокове вдосконалення", "ієрархічне") – від компонентів додатка верхнього рівня до компонентів нижнього рівня.
  2. Покрокова розробка. На кожному кроці виконується тестування створеного програмного фрагмента. Частковий перевіряється не тільки в рамках роботи всієї програми, а й у разі необхідності – з використанням спеціальних текстових конструкцій. Останнє необхідно, якщо функціональність створеного коду не повністю задіяна в рамках даної конкретної програми.
  3. Роблячи крок, потрібно мати на увазі наступний, а може бути і ще один. Так само як, проходячи трасу слалому, гірськолижник повинен бачити відразу кілька воріт вперед і думати, як він пройде друге (краще треті), а не перші ворота.
  4. Одна з ключових ідей – максимально швидке створення працюючого варіанту програми, що виконує хоча б одну корисну для користувача функцію. Далі нарощуйте функціональність програми виходячи з міркувань практичної потреби в них і швидкості реалізації.
  5. Якісне оформлення програми по ходу роботи (привласнення найменувань змінним, коментарі, відступи і т.д.).
  6. Оперативне виділення в ході розробки категорії "повторно використовуваних" компонентів, формування набору таких компонентів (це питання ми будемо розглядати в другій частині статті).

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

Тут ми будемо говорити про розробку локального, невеликого додатки. Зрозуміло, для створення навіть середніх систем етап "паперової" промальовування проекту є необхідним, і його якість у вирішальній мірі визначає майбутній результат. Однак при уважному вивченні питання легко побачити, що багато наведені вище положення цілком годяться і для створення великих проектів. Просто там під "кроком" будуть матися на увазі не десять рядків коду, а інші, більш об'ємні компоненти проекту.


Постановка завдання

Завдання пов'язана з процедурою підтримки (оновлення) мого персонального Web-вузла. Хотілося б відразу попередити, що я – досить недосвідчений Web-майстер і тому, цілком імовірно, навіть не здогадуюся про існування готових засобів вирішення завдань, про які піде мова далі. Але, по-перше, в даному випадку ми обговорюємо питання технології розробки програм, а не інструменти роботи з Web. А по-друге, навіть якщо ми "винайдемо велосипед ", створене нами програма може виявитися корисним для реалізації аналогічних завдань.

Працюю я зі своїм Web-сервером наступним чином: його розробку я веду на персональному комп'ютері в каталозі MySourceWebSite, а користувачі Інтернету мають справу з його копією, що знаходиться на якомусь віддаленому сервері з ім'ям Vusial2000. Періодично проводиться оновлення вмісту сервера: спочатку я виконую всі операції з файлами в каталозі MySourceWebSite, а потім переписую поновлення на Visual2000 за допомогою FTP-клієнта.

Проблема перезапису полягає в тому, що на локальному комп'ютері я працюю з файлами в кодуванні Windows-1251, а на Web-сервері вони повинні існувати в кодуванні KOI-8 (зберігаючи при цьому рядок <Meta charset = windows-1251>). Це виглядає досить дивно, однак такі були вказівки Web-провайдера, а проведені мною різні експерименти підтвердили їх правильність.

Оскільки мій FTP-клієнт не вміє перекодувати файли у момент перезапису, я змушений тримати у себе також копію Web-сайту в кодуванні KOI-8 в підкаталозі MyKoi8WebSite. У результаті процедура перезапису оновлень може бути представлена у вигляді наступних кроків:


  1. У першу чергу визначаю список файлів, які потрібно переписати на Web-вузол. Це виконується за допомогою операції Find в Windows Explorer з пошуком за датою. Звичайно число оновлених файлів становить 10-20. Читати цей список з екрана не дуже зручно, тому я вручну переписую його на лист паперу (я не знайшов можливості імпорту списку у вигляді файлу або виведення на друк, хоча, утиліти, які можуть це робити, безумовно, є).
  2. Відкривши два вікна Windows Explorer, виконую копіювання файлів з MySourceWebSite в MyKOI8WebSite.
  3. За допомогою утиліти Coder перекодируют (за переписаному мною списком) файли в MyKOI8WebSite з Windows-1251в KOI-8.
  4. Поєднуюся з Web-сервером і за допомогою FTP-клієнта копіюю туди файли з MyKOI8WebSite.

Оскільки за один сеанс (а це відбувається в середньому два рази на місяць) оновлюється 10-20 файлів, операція перезапису займає не більше 10 хвилин (не рахуючи, природно, часу перекачування через модем, яке не завжди передбачувано). Звичайно, це незрівнянно з витратами на створення і корекцію HTML-файлів, які для такого обсягу можуть легко зайняти весь робочий день.

І тим не менш процедуру перезапису було б непогано автоматизувати, оскільки при її виконанні потрібно напружити увагу (не ті файли переписали, якісь забули, невірно перекодували тощо), а роблю я це зазвичай в кінці робочого дня.

Думаю, набагато краще виглядав би наступний варіант: викликав утиліту, вказав у віконці дату початку оновлення та натиснув кнопку "Переписати файли з MySourceWebSite". І потім тільки дивися, як утиліта з'єдналася з віддаленим FTP-сервером, провела авторизацію, почала копіювати тільки потрібні файли, одночасно виконуючи їх перекодування, і в кінці видала звіт про виконану роботу.

Ось і спробуємо створити такий додаток. Чесно кажучи, не впевнений, що мені вдасться реалізувати цей план до кінця, хоча б тому, що я ніколи не мав справу з програмуванням FTP-доступу.

Звертаю увагу читачів на такий момент: цей текст буде точно відображати весь хід реалізації проекту. У момент написання цієї фрази в мене немає ніяких заготовок, і тому ми почнемо з запуску VB 6.0 і вибору опції New File. Етап 1: копіювання і перекодування файлів по заданому списку

Зауваження 1. Перед початком роботи переконайтеся, що в середовищі VB (вікно Options) у вас встановлені режими Require Variable Definition (Обов'язкове оголошення змінних) і Save Changes (Збереження зміни проекту при кожному запуску). Якщо ви все ж хочете мати можливість відкоту до якихось попереднім версіями проекту, варто подумати про використання системи управління версіями, наприклад Visual SourceSafe. Раджу також скинути прапорець Compile on Demand.

Відразу збережіть проект, щоб вказати місце розташування його файлів. Це повинен бути каталог, відмінний від того, де знаходиться Visual Basic. Використовуйте режим Require Variable Definition (Обов'язкове оголошення змінних) і Save Changes (Збереження зміни проекту при кожному запуску).

Крок 1. Створюємо новий проект Standard Exe. Відразу ж міняємо стандартні імена Project1 і Form1 на будь-які осмислені назви, в даному випадку CopyKoi8 і frmCopy8. Встановлюємо властивість Caption форми як "Перетворення з Win в KOI8 ". Запустіть створений проект на виконання і запишіть його модулі у відповідний каталог.

Зауваження 2. Перший запуск з "порожнім" проектом потрібен для того, щоб визначитися з місцем, де він буде зберігатися. За замовчуванням буде запропоновано каталог, в якому знаходиться сам VB. Ні в якому разі не записуйте туди свій проект! Для зберігання своїх проектів і даних заведіть окремий каталог (а для кожного проекту – підкаталог). Окремий каталог потрібно зробити для зберігання компонентів багаторазового використання.

Правильніше за все розбити жорсткий диск на два (чи більше) логічних диска. Один диск (С:) можна використовувати для зберігання операційної системи, інший (D:) – для записуваних додатків (Office, VB і пр.), третій – для зберігання створюваних вами файлів (проектів, документів, листів та ін.) За рахунок цього істотно підвищується надійність зберігання інформації. Зрозуміло, що резервна копія буде делатьcя простим копіюванням тільки диска E:, так як в разі краху системи і систему, і додатки можна відновити з дистрибутивів. Найцінніша інформація – створена саме вами.

Зауваження 3. У разі застосування для форм і елементів управління якихось осмислених імен (властивість Name) замість стандартних (що дуже рекомендується), їх потрібно встановлювати відразу після створення відповідних об'єктів і бажано не змінювати в подальшому. Справа в тому, що при заміні імені об'єкта, наприклад з Text1 на txtFileName, імена всіх створених раніше подієвих процедур Text1_ХХХ. і посилання на Text1 потрібно міняти вручну. Якщо вам все ж доведеться коригувати імена вже задіяних об'єктів і змінних, варто скористатися командою Replace для перегляду всіх модулів проекту.

Крок 2. Тепер розмістимо елементи управління, які потрібні нам для початку роботи. Поки представляється необхідним мати елементи, розміщення яких на формі наведено на рис. 1:

Рис. 1.











































Тип елемента  Властивість Name  Примітка 
Label lblFrom Ім'я головного каталогу, звідки будуть копіюватися файли
Label lblTo Ім'я головного каталогу, куди будуть копіюватися файли
Label lblCopy Число файлів, скопійованих без перекодування
Label lblConv Число файлів, скопійованих з перекодуванням
Label lblReplace Число змінених файлів (раніше існували)
Command cmdCopy Команда на виконання копіювання (необхідність перекодування буде визначатися автоматично по розширенню файлу.)
Command cmdExit Команда на завершення утиліти
DirListBox dirList Вікно для вибору каталогу
FileListBox filList Список файлів вибраного каталогу

Два примітки:


  1. Поки будемо працювати з жорстко заданими іменами каталогів (звідки і куди копіюються файли). Особисто мені цього цілком достатньо. Потім реалізуємо можливість вибору каталогів.
  2. Для зручності орієнтації на формі встановимо для міток Caption = Name (при запуску програми потрібні значення встановлюються програмно).

Тепер сформуємо програмний код для даного кроку відладки:

 Dim PathFrom $, PathTo $ "імена каталогів ЗВІДКИ і КУДИ
"Лічильники скопійованих, перекодувати і замінених файлів
Dim CopyCount&, ConvCount&, ReplaceCount&

Private Sub Form_Load()
"Початкове налаштування
"Імена каталогів Звідки і Куда
PathFrom = “d:my-sitesvisualmy”
PathTo = “e:dreamwearvisual”
"Установка властивостей
lblFrom.Caption = "Звідки:" + PathFrom
lblTo.Caption = "Куди:" + PathTo
"Обнулення лічильників
CopyCount = 0: ConvCount = 0: ReplaceCount = 0
Call CountCaption "назви міток з лічильниками
"Початкова установка каталогу ЗВІДКИ
dirList.Path = PathFrom$
filList.Path = dirList.Path
filList.Pattern = "*.*" "всі файли в каталозі
End Sub
Public Sub CountCaption()
"Висновок вмісту лічильників
lblCopy.Caption = "Скопійовано файлів =" & CopyCount
lblConv.Caption = "перекодувати файли =" & ConvCount
lblReplace.Caption = "Замінено файлів =" & ReplaceCount
End Sub

Private Sub cmdExit_Click()
Unload Me "завершити роботу
End Sub

Private Sub Form_Unload(Cancel As Integer)
MsgBox "Кінець роботи"
End Sub


Кілька приміток:


  1. Зараз досить часто не проводять початкової установки змінних, вважаючи, що ця операція вже виконана в момент компіляції. Тим не менш програмне обнуління лічильників я зробив, так як це сприяє кращому сприйняттю програми і гарантує від можливих неприємностей. А раптом ви потім захочете оголосити змінні статичними і використовувати форму у вигляді компонента іншої програми?
  2. Я відразу виділив установку міток зі значеннями лічильників в окрему процедуру, оскільки очевидно, що така операція знадобиться згодом і при перезапису файлів.
  3. Процедура Form_Unload містить не дуже потрібний в даний момент виведення повідомлення. Цим я хочу підкреслити, що дана процедура нам знадобиться надалі: код, який потрібно буде виконати при завершенні утиліти (а він, скоріше за все з'явиться), необхідно записати саме тут, а не в cmdExit_Click. Адже закрити форму можна й шляхом натискання кнопки системної Close.
  4. По ходу налагодження утиліти ми будемо використовувати висновок інформації за допомогою MsgBox. Після перевірки фрагментів коду будемо виключати їх, перетворюючи в коментарі. Не варто відразу видаляти ці рядки – вони можуть стати в нагоді в майбутньому, до того ж вони добре показують хід налагодження програми.

Запустіть проект і переконайтеся, що всі назви міток сфоміровани вірно.

Крок 3. Займемося елементом управління dirList (DirListBox – вибір каталогу). Для початку перевіримо, в якому вигляді видається ім'я каталогу. Напишемо такий код:

Private Sub dirList_Change()
MsgBox dirList.Path
End Sub

Запустіть проект і подивіться, що видається для кореневого каталогу та підкаталогів.

Зауваження 4. При роботі з іменами каталогів слід враховувати можливості їх двоякого позначення: як з зворотною косою межею в кінці імені, так і без неї, що створює певну плутанину і може стати причиною помилок. Розглянемо це на прикладі елемента управління DirListBox:

 Print DirListBox.Path "для кореневого каталогу риса завжди
"Видається (C:), для всіх інших – ні (C: TMP).
DirListBox.Path = “C:TMP”
DirListBox.Path = "C: TMP" "правильно працюють обидва варіанти

DirListBox.Path = "C:" "буде встановлено каталог C:
DirListBox.Path = "C:" "буде встановлено ПОТОЧНИЙ каталог
"Диска C: (наприклад, C: Winodws)


Отже, ми побачили, що:


Увага! Щоб уникнути проблем з формуванням повних імен файлів, завжди будемо задавати в змінних PathFrom і PathTo ідентифікатори з косою межею в кінці.

Тепер змінимо код наступним чином:

Private Sub dirList_Change()
“MsgBox dirList.Path
"Перевірка на допустимість імені каталогу
If InStr (dirList.Path, Left (PathFrom, Len (PathFrom) – 1)) <> 1 Then
MsgBox "Вийшли за межі заданого каталогу!"
dirList.Path = PathFrom "примусова установка
End If
filList.Path = dirList.Path "поточний каталог для списку файлів
End Sub

Пересуватися від заданого головного каталогу можна вниз по дереву, але догори потрапляти не можна. Для цього потрібна реалізована вище перевірка.

Запустіть проект і переконайтеся, що створена перевірка дійсно правильно працює. Переконайтеся, що зміна списку каталогів в елементі filList виконується вірно.

Крок 4. Тепер приступимо до реалізації процедури копіювання перекодування файлу. Вона буде виконуватися або натисканням кнопки "Копіювати + Перекодувати", або подвійним клацанням по імені файлу в списку. Для початку напишемо такий код:

Private Sub filList_DblClick()
Call cmdCopy_Click
End Sub

Private Sub cmdCopy_Click()
"Копіювання і перекодування файлу

Dim FileFrom $, FileTo $ "імена вихідного і результуючого файлів

MsgBox filList.FileName "в якому вигляді видається ім'я файлу?
FileFrom = filList.FileName
If FileFrom = “” Then
MsgBox "Не обраний файл!": Exit Sub
End If
"Далі піде код подальшої обробки
End Sub


Кілька приміток:


  1. Ми поставили MsgBox, щоб перевірити, в якому вигляді видається ім'я файлу. Під ім'ям файлу можна мати на увазі як ідентифікатор всередині каталогу, так і ідентифікатор, що включає повний шлях до файлу. Деякі елементи управління мають властивості для обох варіантів, FileListBox працює лише з цим.
  2. Далі слід перевірка на той випадок, коли в списку немає виділення, а користувач клацне кнопку.

Запустіть проект, подивіться, в якому вигляді видається ім'я файлу, і переконайтеся, що перевірка відсутності виділення працює правильно.

Крок 5. Далі ми будемо дописувати процедуру cmdCopy_Click, щоб виконати операції копіювання та перекодування файлу. Допишемо внизу такий код для формування повного імені вихідного і результуючого файлів:

Dim a$, i%
If Right(filList.Path, 1) <> “” Then a$ = “” Else a$ = “”
FileFrom = filList.Path + a$ + FileFrom
FileTo = PathTo + Mid$(FileFrom, Len(PathFrom) + 1)
MsgBox FileFrom & vbCrLf & FileTo

Тут ми підстрахувалися на випадок, якщо хто-то в якості вихідного каталогу буде задавати кореневої.

Увага! У нашій утиліті ми не передбачаємо випадки, коли в каталозі КУДИ потрібно створювати нові підкаталоги. У майбутньому таку можливість можна реалізувати, причому це легко зробити вручну, оскільки нові розділи Web-вузла створюються досить рідко.

Запустіть проект для різних значень PathFrom і PathTo. Введені раніше значення можна закоментувати і спробувати різні поєднання імен типу C: і C: TMP. Переконайтеся, що імена файлів завжди формуються правильно.

Крок 6. Слід розрізняти дві ситуації: створення нового результуючого файлу і заміна вже існуючого. Для цього допишемо далі наступний код:

Dim sReplace$
If Dir (FileTo) <> "" Then "результуючий файл вже існує
If vbYes = MsgBox ("Видалити існуючий файл" & FileTo & "?", _
vbYesNo, "Видалити?") Then "видалити
Kill FileTo: sReplace = "Заміна"
ReplaceCount = ReplaceCount + 1 "лічильник замінених файлів
Else: Exit Sub
End If
Else: sReplace = "Новий"
End If

Кілька приміток:


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

Увага! Тепер починаємо експериментувати з процедурами видалення та копіювання файлів у каталозі КУДИ.

Для цього створимо тимчасовий файл для тестування, наприклад E: MyTest, і це ім'я поки запишемо для установки змінної PathTo. Скопіюємо туди декілька файлів з вихідного каталогу. Запустіть проект і переконайтеся, що програма правильно визначає наявність вже існуючих файлів і при відповідному відповіді користувача видаляє його.

Крок 7. Тепер напишемо код для копіювання файлів в кінець процедури cmdCopy_Click:

Dim FileExt$, sCopy$, lnFrom%, lnTo%

FileExt $ = Right $ (FileFrom, 4) "розширення файлу
If FileExt $ = "****" Then "така умова ніколи не виконається
” If FileExt$ = “.txt” Or FileExt$ = “.htm” Then
"Перекодування + копіювання
ConvCount = ConvCount + 1
sCopy = "перекодований Win -> KOI8"
Else "тільки копіювання
"Відкрити файли
lnFrom = FreeFile: Open FileFrom For Binary As #lnFrom
lnTo = FreeFile: Open FileTo For Binary As #lnTo
"Копіювання вмісту
ReDim Buffer(1 To LOF(lnFrom)) As Byte
Get # lnFrom,, Buffer () "читаємо повністю
Put # lnTo,, Buffer () "записуємо повністю
CopyCount = CopyCount + 1 "лічильник скопійованих
sCopy = "Копіювати"
End If
Close #lnFrom: Close #lnTo
"Оновлення лічильників на формі
Call CountCaption


Кілька приміток:


  1. Щоб не займатися контролем за розподілом номерів для різних операцій, використовуємо динамічне визначення логічних номерів файлів (це не останні файли, з якими буде працювати наша програма). Зверніть увагу, що отримання вільного логічного номери повинно виконуватися безпосередньо перед операцією відкриття файлу. Наступна конструкція буде непрацездатною:
    lnFrom = FreeFile: lnTo = FreeFile
    "Обидві змінні отримали однакове значення!
    Open FileFrom For Binary As #lnFrom
    Open FileTo For Binary As #lnTo

  2. Поки продовжуємо розвиток нашої утиліти тільки для випадку простого копіювання файлів. Проте вже зараз ми вставили конструкцію If … Then … Else … End If, щоб підкреслити, що є якийсь загальний код для обох випадків і що потрібно виконувати деякі парні операції (наприклад, змінювати лічильники і формувати змінну sCopy). Хоча в частину "перекодувати" ми зараз не потрапляємо, тим не менш у коментарі вже вказали, що операція буде виконуватися для TXT-і HTM-файлів.

Запустіть проект і переконайтеся, що програма правильно виробляє копіювання файлів, попереджаючи про вже існуючих файлах і вірно змінюючи лічильники. Спробуйте скопіювати файл з підкаталогу, якого немає в каталозі КУДИ, – повинна з'явитися помилка з повідомленням "Path not found" ("Не знайдено шлях").

Така ситуація буде зустрічатися рідко, але краще її обробити програмним шляхом, без аварійного завершення утиліти. На початок процедури cmdCopy_Click запишемо:

On Error GoTo RathNotFound

а в самий її кінець:

  Exit Sub
RathNotFound: "обробка помилки
MyError = Err
If MyError = 76 Then
If MsgBox ("Не можна створити файл" & FileTo, _
vbRetryCancel, "Немає такого каталогу!") _
= VbRetry Then Resume "повторити спробу
Else "якась інша помилка
MsgBox "Помилка =" & MyError
End If

Ми вирішили програмно не створювати неіснуючі каталоги, оскільки подібна необхідність з'являється досить рідко. Але варто звернути увагу на те, що в момент отримання такого попередження користувач може, не перериваючи виконання утиліти, створити каталог за допомогою провідника, а потім повторити спробу запису файлу, натиснувши кнопку Retry.

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


Підведення проміжних підсумків

Отже, ми створили корисну утиліту CopyKoi8, яка дозволяє копіювати довільні файли з одного каталогу в інший, зберігаючи структуру внутрішніх подкаталогов.Такім чином, ми суттєво спростили операції пункту 2 вихідної задачі.

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

Більш того, надалі ми створимо більш "автоматичні" процедури копіювання та перетворення, хоча і даний режим ручного вибору файлів буде нам іноді необхідний. Ми реалізували найбільш загальний випадок, причому сформований нами код на 90% стане в нагоді і для інших режимів роботи. Тепер можна передати створену утиліту для експлуатації користувачеві (собі самому) і приступити до її подальшого функціонального розвитку.

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


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

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

Ваш отзыв

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

*

*