Технологія створення форм для роботи з довідниками
Для початківців, та й не тільки, програмістів часто великою проблемою є створення однотипних форм для роботи з довідниками тощо. Принаймні велика кількість питань як на форумах, так і особисто, про це свідчить. Тому і на прохання одного зі своїх друзів я вирішив присвятити окрему статтю питанню організації роботи з формами — і зокрема організації роботи з однотипними формами. Адже у великих проектах не рідкість величезна кількість різних довідників — таких як довідники посад, довідники підрозділів, довідники типів виплат і нема їм числа. Мало того, в процесі експлуатації програми не рідкість додаткове зростання числа довідників - що саме собою доставляє. Як із цим боротися? Відповідь на це я спробую дати у своїй статті. Хочу звернути увагу, що наведені рекомендації ґрунтуються на особистому практичному досвіді розробки великих програмних систем. У статті буде розглянуто дві основні теми
- Використання в роботі шаблону проектування Модель-Подання-Контролер (MVС)
- Динамічний створення форм, як це роблю я.
Ці дві теми практично не відокремлені одна від одної – з однієї простої причини – якщо ви не користуєтеся MVС, рано чи пізно, у порівняно великому проекті, ви почнете писати моторошний «макаронний» код, в якому плутатиметеся самі. Щоб цього уникнути — використовуйте хороші шаблони програмування.
Всі приклади, наведені в цій статті, спираються на засоби розробки компанії Borland — Borland Builder C++, але по суті можу застосовуватися в будь-якій системі незалежно від мови програмування. BCB використовується тут лише тому, що на ньому пише людина, яка попросила написати цю статтю.
І такMVС. Що це таке, із чим її їдять і чому саме вам треба цей шаблон використовувати? Все дуже просто. Основний принцип використання MVС полягає в розділенні коду - якщо ви поділяєте код, який отримує дані з бази, від коду коорий ці дані обробляє і окремо формуєте код, який результат цієї обробки показує - вітаю - ви використовуєте MVС. Більшість вдалих програмних інструментів спроектовано таким чином, що дотримуватися цього шаблону в них досить просто, легко та інтуїтивно зрозуміло. Але саме BCB і Delphi до таких систем не відносяться (за що, я думаю, їхні творці горітимуть в Аду — у спеціально для них створеному 10 колі), бо в них надзвичайно просто і легко писати «макаронний» бидлокод — коли все отримання даних, їх обробка і висновок запихається в один єдиний клас єдиної форми, на яку горе програміст накидав під сотню контролів — і весь цей, з дозволу сказати, код розміром кілька тисяч рядків компілюється в файл, що здійснюється, і гордо називається «продуктом».
У принципі нічого звичайно страшного в цьому немає - якщо не вам це все надалі обслуговувати та підтримувати. Тому що, в процесі обслуговування та підтримки працюючої програми так чи інакше доводиться її розширювати, доопрацьовувати і… і ось тут настає армагедець. Тому що, через кілька місяців вже погано пам'ятати навіщо була написана та функція — яка викликається по 20 разів у різних місцях, і чому в деяких місцях місце цієї функції викликається зовсім інший код…ну і так далі. Ті, кому доводилося підтримувати «продукти» життєдіяльності таких «програмістів» мене зрозуміють.
Як реалізувати все це практично? Спроектуємо невеликий модуль системи – припустимо наш модуль будереалізувати наступну функціональність:
- Виведення та відображення записів різних довідників.
- Додавання, редагування та видалення вибраних записів.
- Надання єдиного інтерфейсу для отримання записів довідників (списки, дерева тощо) у будь-якій точці програми.
Для початку цілком достатньо. Якщо використовувати стандартний підхід - то зазвичай створюється форма, туди запихаються потрібні контроли та компоненти - потім створюються ще форма (а часто й не одна) для редагування та додавання. Вибір даних з довідників виконується в кожній точці програми незалежно.
Як це зробити з погляду MVС? Необхідно спроектувати чотири класи – клас-контролер, клас доступу до даних, клас-форма основна та клас-форма додавання редагування. Так як довідник англійською Reference то відповідно класи особисто я маю наступним чином:
- TRefernceController - клас контролера, успадковує від загального класу контролера (якщо потрібно);
- TmfMain - клас основної форми, успадковує від TForm (BCB);
- TfmAddEdit - клас допоміжної форми, успадковує від TForm (BCB);
- TdmMain - модуль даних, успадковує від TDataModule (BCB).
Звичайно, успадкування класів залежить від вашого конкретного додатка — я взяв найпростіший варіант, щоб не надто заглиблюватися і не плутатися. Назва модулів теж залежить від того, яка система найменувань прийнята у вас. Наприклад, TmfMain - у мене має назву будь-яка основна форма модуля, але втім, це деталі, і я залишаю це на ваш розгляд.
Оголошення класу контролера може виглядати приблизно так: