Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lab_4.doc
Скачиваний:
9
Добавлен:
12.02.2016
Размер:
4.24 Mб
Скачать

Розробка програмного продукту. Етап реалізації.

Лабораторна робота № 4

Міністерство освітиі науки України

Національний університет “Львівськполітехніка”

Кафедра автоматизованих систем управління

Методичні вказівки

до лабораторної роботи № 4

Розробка програмного продукту.

Етап реалізації”

з дисципліни

Технологія програмування та створення програмних продуктів”

для студентів базового напрямку підготовки по спеціальності

Комп’ютерні науки” (шифр 0804)

Львів 2011

Методичні вказівки до лабораторної роботи № 4 Розробка програмного продукту. Етап реалізації з дисципліни Технологія програмування та створення програмних продуктів для студентів спеціальності - шифр 0804 “Комп’ютерні науки”/ Укл. доц. Ковівчак Я.В.,

Львів: Національний університет “Львівська політехніка”, 2011.

Методичні вказівки обговорено та схвалено на засіданні кафедри АСУ Протокол № ___________ від «___»___________2011 р.

Завідувач кафедрою АСУ ______________ Рашкевич Ю. М.

Методичні вказівки обговорено та схвалено на засіданні методичної комісії базового напрямку підготовки

Протокол № ___________ від «___»___________2011 р.

Лабораторна робота №4

Розробка програмного продукту. Етап реалізації

Мета: Ознайомлення з основними задачами, які необхідно розв’язати під час виконання етапу реалізації

Завдання: Навчитись реалізовувати моделі, які були побудовані на попередньому етапі проектування

  1. Теоретична частина

Етап реалізації виконується в певному середовищі розробки і визначає надійність проекту. Вона досягається униканням або виправленням помилок.

Всі помилки усунути не можливо. Але ми можемо зменшити ймовірність їх виникнення, застосовуючи наступне:

  • відхід від небезпечних методів, наприклад використання вказівників,

  • обмежені принципи доступу (розділення пам'яті, принципи діапазону, інкапсуляція),

  • використання типізованих мов і компіляторів,

  • використання мов високого рівня,

  • послідовність у використанні інтерфейсів між модулями,

  • врахування надзвичайних ситуацій (порожні множини, цикли, невизначеності),

  • використання існуючих компонентів,

  • мінімум відмінностей між концептуальною моделлю і моделлю реалізації.

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

Він вимагає:

  • виявлення помилок,

  • опрацювання помилок,

  • виправлення помилок.

Опрацювання помилок є можливим, якщо виконана відповідна діагностика, можливо - вказання рядка з помилкою.

Існує два методи опрацювання помилок:

  • перевірка даних, наприклад, виконання тестованих формул,

  • порівняння результатів декількох версій модулів.

Ключові чинники успіху:

  • високоякісна і детальна специфікація,

  • хороше знання середовища розробки,

  • відповідність стандартів,

  • опрацювання помилок.

Основні результати етапу:

  • покращений документ, що описує вимоги,

  • покращена аналітична модель,

  • покращений проект,

  • код з перевіреними модулями,

  • звіт про перевірені модулі,

  • розроблена база даних,

  • планування етапу тестування.

Ця стадія виробництва програмного забезпечення (ПЗ) увійшла до ери автоматизованого виробництва ПЗ. Тут використовуються такі інструменти, як швидка розробка програм (Rapid Application Development, RAD) і мови високого рівня.

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

    1. Надійність програмного забезпечення

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

На першому етапі необхідна надійність повинна задаватися умовно, що дозволило б виробникові спланувати всі кроки і розмістити ресурси для того, щоб досягти поставлених завдань.

Основними методами збільшення надійності є:

  • запобігання помилкам;

  • визначення похибки помилок.

Запобігання помилкам

Всіх помилок уникнути неможливо, але є способи, що допоможуть зменшити їхню кількість:

  • Не використовувати методи з великою вірогідністю помилок (наприклад, використання вказівників і т.п.);

  • Використання принципу обмеженого доступу (інкапсуляція, розділення пам'яті і т.д.);

  • Використання мов і компіляторів з перевіркою відповідності типів;

  • Використання мов високого рівня;

  • Строго визначати інтерфейси користувача;

  • Приділити увагу виключенням (порожні множини, порожні цикли, нульові значення, змінні, що не були ініціалізовані, і т.д.);

  • Використання готових компонентів (бібліотеки, класи і т.д.);

  • Мінімізація відмінностей між абстрактною моделлю і моделлю реалізації.

Небезпечні техніки

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

Але методів з більшою вірогідністю помилки слід уникати. Іноді їх дійсно необхідно застосувати. У таких випадках методи обробки помилок і контролю результатів повинні розроблятися дуже ретельно.

Найнебезпечнішою технікою програмування є:

  • Використання команди "goto". Ця команда може призвести до труднощів розуміння програм і їх підтримки (внесення подальших змін).

  • Використання чисел з плаваючою крапкою. Числа мають обмеження по точності, і обчислення можуть накопичувати відхилення від реальних чисел.

  • Використання вказівників і адресної арифметики з їх використанням. Вказівники є надзвичайно небезпечними. Вони дозволяють проникнути в пам'ять і здійснити в ній будь-які зміни. На них необхідно звертати увагу.

  • Паралельне обчислення. Паралельні обчислення приводять до складної залежності часу і так званому галопуванню (залежить від випадкових результатів деяких потоків). Їх важко перевірити.

  • Використання виключень і переривань. Використання цієї техніки веде до паралелізму і провокує такі ж проблеми. Так само це може "підвісити" програму.

  • Використання рекурентних співвідношень. Програму з рекурентними співвідношеннями важко зрозуміти і трасувати.

  • Використання динамічного розподілу пам'яті. Динамічний розподіл пам'яті без контролю даних може призвести до втрат інформації і "підвісити" програму.

  • Несподівані побічні ефекти у функціях і процедурах.

  • Використання складних виразів без дужок. Таке відбувається, коли програмісти покладаються на пріоритет операторів і уникають дужок. Це не веде до збільшення продуктивності. Але підхід може викликати багато помилок і труднощів в управлінні.

  • Обробка даних багатьма процесами без синхронізації (блокування, транзакції). Деякі з методів є корисними, але їх потрібно використовувати обережно.

Принцип обмеженого доступу

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

Він може бути сформульований таким чином:

Все, що повинно бути схованим, слід приховати.

Програміст не повинен мати доступу до даних, що не є потрібними для виконання певного завдання. Права доступу повинні бути обмежені. Типові мови програмування не задовільняють цю вимогу. Воно застосовується в операційних системах, наприклад, DOS і WINDOWS.

Принцип обмеженого доступу реалізується інкапсуляцією (відомою з Modula 2) і об'єктно-орієнтованим підходом.

  • приватні поля, змінні, методи

  • таблиці експорту

  • таблиці імпорту (визначають внутрішні ресурси)

Строгий контроль типів

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

Тип визначає значення даних і є формальним обмеженням конструкції змінних і об'єктів.

Мета типізації - керувати формальним програмуванням.

Типізація підтримує об'єктно-орієнтоване програмування. Ім'я зазвичай відображає семантику об'єкту, наприклад, D представляє дані (від Data). У мовах з сильною типізацією (наприклад, Pascal і Modula2) така ідентифікація повинна бути присутньою в оголошенні типів. Оголошення перевіряються (наприклад, якщо програміст оголосить X як ціле число (integer), компілятор перевірить, чи всі виклики сприймають X як ціле число.

Сильна типізація запобігає помилкам в 80% випадків. На жаль, в багатьох комерційних продуктах цей контроль не повний, або ним і зовсім нехтують (Smalltalk, SQL).

Система сильного статичного контролю типів містить наступні елементи:

  • Специфікація всіх видів змінних і об'єктів, наприклад:

  • Typedef TypWorker = struct{string name, int salary, Works_in, int salary_without_taxes()};

  • TypWorker Worker;

  • Визначення сигнатури всіх операторів, процедур, функцій, методів, наприклад:

  • Boolean works_long (in TypWorker wrkr, in WorkSphere, out years_works)

  • Визначення інтерфейсів, класів і інших інкапсульованих абстракцій.

  • При визначенні параметрів ми вказуємо параметри вводу і виводу.

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

    1. Похибка

Жодна техніка не гарантує, що програма не матиме помилок. Похибка помилки означає, що програма працюватиме нормально навіть коли вона матиме помилки.

Тому програма повинна:

  • виявляти помилки;

  • відновлюватися після помилки, коректно завершуватися;

  • проводити корекцію помилок, тобто вносити зміни, щоб позбутися помилки.

Важливо провести діагностику помилки. Рядок коду, в якому відбулася помилка, повинен бути визначений.

Є два основні методи автоматичного виявлення помилок:

  • Перевірка коректності даних. Метод складається з розміщення додаткових рядків в код для того, щоб перевірити коректність даних.

  • Порівняння декількох версій модулів.

Порівняння декількох версій модулів

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

Багатоваріантне програмування може бути реалізоване декількома способами:

Перший з них називається n-версії. Він розробляється n незалежними програмістами. Програми виконуються паралельно і результати порівнюються PCU. У разі розбіжності PCU вибирає правильний результат, наприклад, "голосування" використовується для ухвалення рішень. Службові дані для таких обчислень є важливим чинником. Проблема критично важлива для таких систем, як системи реального масштабу часу (Real Time Systems, RTS), для яких потрібно брати до уваги час реакції, наприклад, на погодні умови або кут нахилу літака.

Характеристики n-рівневого рішення паралельні, з одночасним відкриттям операцій над загальними даними декількома незалежними модулями.

Рисунок 1.

Інше рішення - це програмування з допоміжними модулями. Метод припускає існування двох модулів, один з яких активний, а інший використовується для перевірки результатів активного модуля. Якщо виявляється будь-яка некоректність, додатковий операційний модуль замінює базовий модуль. Існують різні версії паралельних рішень.

Рисунок 2

    1. Транзакції

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

Транзакція складається з наступних операцій:

  • читання даних x транзакцією T,

  • запис даних x транзакцією T,

  • відміна транзакції T,

  • ухвалення транзакції T.

Транзакції використовуються для компактності та у випадку паралельних операцій.

Якщо виконується значна кількість процесів, компактність може не дотриматися і є можливість виникнення помилок.

У таблиці 1. наведена схема роботи двох процесів А і B, які використовують загальні дані.

Таблиця 1.

У Таблиці 1. наведено два паралельні процеси, які не порушують компактність.

Таблиця 2.

У таблиці 2. наведено два процеси, які порушують компактність.

Блок 6 не компактний. Є два процеси, які при незалежному виконанні дадуть результат 11. Відсутність синхронізації призведе до того, що один з процесів не буде оновлений.

Приклад: ми маємо 4 автори, які оновлюють тест. Якщо немає ніякого протоколу щодо оновлень, деякі виправлення можуть бути втрачені.

Транзакції роблять можливою підтримку сумісності процесів. При цьому ручна синхронізація або домовленості не потрібні.

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

Уявімо банківську систему з наступними операціями над рахунками клієнта F.

  1. Клієнт читає магнітну картку і авторизується

  2. Клієнт оголошує суму

  3. Рахунок перевіряється

  4. Залишок на рахунку зменшується на вказану суму

  5. Посилається замовлення передачі

  6. Касир знімає суму з рахунку

  7. Касир проводить оплату

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

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

Постулати ACID

Транзакції гарантують відновлення до стану перед виникненням помилки. Це - основний принцип для забезпечення надійності програмного забезпечення, що працює з базами даних.

Під транзакціями розуміють наступні властивості:

(A) Атомарність – у всіх транзакціях виконується або одна операція, або нічого.

(C) Цілісність – якщо транзакція увійшла до цілісної бази даних, то поля і база даних повинні теж залишитися цілісними.

(I) Ізоляція – транзакція не знає про інші транзакції і не втручається в їх дії. Дії, що виконуються однією транзакцією, не повинні бути видимі іншим, поки не будуть отримані результати.

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

Транзакції в SQL

У SQL кожна транзакція починається з почати транзакцію (BEGIN TRANSACTION), і закінчується операцією фіксування(COMMIT), що позначає правильне закінчення, або відкат (ROLLBACK) (або відміна (ABORT)), означає повернення до початкового стану (або відміну) транзакції.

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

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

Приклад транзакції з командами відміна та фіксування наведені на рис. 3:

Рисунок 3. Приклад використання транзакцій.

Застосування блокування та проблеми, пов'язані з цим

Транзакції вимагають застосування спеціальних модулів (планувальників) і протоколу обробки транзакцій.

Щоб уникнути проблем з розподіленою обробкою використовуються блокування.

Існує два типи блокувань:

Блокування X-типу– повністю блокує доступ до транзакції

Блокування S-типу- це блокування передбачає режим "лише читання", але транзакцію не можна модифікувати.

У реляційній базі даних найчастіше використовується протокол двофазного блокування 2PL.

Правила приведені нижче:

  1. Якщо операції pi(x) можуть виконуватися, блокування застосовується на транзакцію Ti і операція виконується. Якщо операція не може виконуватися, вона розміщується в чергу.

  2. Видалення блокування виконується після завершення транзакції.

  3. Якщо блокування було видалене з транзакції, транзакцію вже не можна заблокувати.

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

Рисунок 4. Протокол 2PL.

Застосування блокування може призвести до взаємного блокування і зависання. Використання блокування змушує транзакцію дочекатися звільнення ресурсу. Розглянемо три транзакції:

Транзакція А блокує ресурс X і вимагає доступу до ресурсу Y. Транзакція B блокує доступ до ресурсу Y і запитує доступ до ресурсу X. Виходить взаємоблокування, і жодна з транзакцій не може завершитися.

Приклади блокувань зображені на малюнку:

Рисунок 5. Взаємоблокування транзакцій.

Рисунок 6. Взаємоблокування транзакцій.

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

Методи боротьби з взаємоблокуваннями:

Метод 1.

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

Метод 2.

Уникнення взаємних блокувань. Є багато таких методів, наприклад:

Попередній запит ресурсу: перед початком кожна транзакція визначає свої потреби. Зміни не вносяться. Недолік - зниження ефективності паралельного обчислення.

Чекай-помри (wait-die): якщо транзакція намагається дістати доступ до заблокованого ресурсу, вона відміняється. Це неприпустимо для діалогових систем, оскільки користувач може бути збентежений потребою багатократного введення даних. Це зменшує продуктивність.

Часова мітка і розбиття транзакцій

У обробках транзакцій застосовуються схеми, засновані на впорядкуванні до потрібної часової мітки. Кожній транзакції привласнюється унікальна часова мітка, коли вона запускається. Часова мітка визначає свою позицію в часовій послідовності в процесі виконання транзакцій. Впорядковування часових міток засноване на конфліктах операцій і є дуже простим:

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

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

Проблема блокування також має відношення до розбиття. Розбиття визначається рішенням, яка транзакція повинна бути неподільною, щоб її не можна було заблокувати.

Розглядаються наступні рівні:

  • база даних,

  • відносини,

  • записи,

  • елементи запису,

  • індивідуальний атрибут,

  • фізичні аспекти пам'яті.

Великі частини розбиття можуть забезпечити відповідність, але мають небагато паралельних процесів. Малі ж вимагають багато блокувань і обслуговування.

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

Нижче перераховані найважливіші механізми відновлення системи:

Рисунок 7. Механізми відновлення після аварійної відмови.

    1. Середовище реалізації

Середовище процедурних мов

Це традиційне середовище реалізації. Процеси і модулі можуть бути представлені цілими програмами. Групи Процедур і функцій відповідають системним функціям. Пам'ять і контейнери в проекті відповідають структурам мови.

Процедурні мови не забезпечують достатні механізми для контролю доступу до даних. Доступ до структур отримується легко. Є інші мови, наприклад, Ada, Modula 2, які мають досконаліші механізми.

Об'єктно-орієнтовані середовища

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

Проте їх не достатньо у разі великих проектів і тоді вони вимагають складної обробки даних і використання баз даних.

Більшість об'єктно-орієнтованих мов - це гібридні мови, які були розроблені, ґрунтуючись на процедурних мовах, з додаванням до них об'єктної орієнтації. Одна з таких мов - C++.

Такі мови, як Eiffel, Visual Age, і Smalltalk показують, що гібридні мови стають все менш популярними.

Середовища реляційних баз даних

Найрозвиненіші середовища зараз використовують реляційні бази даних.

Їхні переваги:

  • множинний доступ;

  • автоматична перевірка цілісності;

  • користувачеві привласнюються права доступу;

  • висока надійність;

  • розширюваність (обмежена);

  • високий рівень доступу (SQL, ODBC, JDBC).

Також є і недоліки:

  • ускладнені відображення абстрактної моделі;

  • низька ефективність для деяких завдань;

  • обмежена типізація;

  • недолік механізмів інкапсуляції і інших об'єктно-орієнтованих механізмів;

  • збільшена довжина програми.

Об'єктно-орієнтована база даних

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

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

Об'єктно-орієнтований підхід вводить більшу кількість понять, саме тому реляційна модель розширює мозкову функцію.

Об'єктно-орієнтовані бази даних (ObjectStore, O2, Versant, Gemstone, Poet, Objectivity/DB, Jasmine, Jade і т.д.) вже є розвинутими, але все ще ведуть боротьбу за клієнтів.

Об'єктно-орієнтовано-реляційні середовища баз даних

Завдяки успіху об'єктно-орієнтованого підходу багато понять були введені в реляційні середовища.

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

Об'єктно-орієнтовано-реляційні системи (Oracle-8, Informix Dynamic Server і т.п.) розвиваються поступово.

Середовище програм користувача

Приклад середовища програми користувача - Microsoft Office, документи якого можуть бути оброблені багатьма програмами.

Наприклад, найважливішими особливостями Microsoft Excel є: повністю процедурна мова Visual Basic для програм, добре розроблена об'єктна бібліотека, яка надає майже всі пакети, дозволяє реєстрацію макроозначень, можливість створення інтерфейсного діалогу, розміщуючи поля у листах, обладнана відлагоджувачем, має вдосконалений метод роботи з DLL, DDE, OLE, ODBC.

Перераховані методи роблять MS Office середовищем, яке може використовуватися для розробки програм зі складним логічним і швидким прикладним розвитком.

Інструментарій CASE на етапі реалізації

Прогрес інструментів CASE останнім часом полегшив життя програмістів. Вони можуть застосовувати інструменти CASE безпосередньо для перегляду діаграм і словника баз даних. Деякі системи CASE генерують коди, які створюють діаграми і шаблони.

Типовими кодовими елементами є:

  • скрипти, що створюють відношення в базі даних;

  • визначення структури даних;

  • заголовки процедур і функцій;

  • визначення класів;

  • заголовки методів.

Код завершується багатьма коментарями, що засновані на словнику баз даних. Деякі з інструментів CASE мають інтерфейс для RAD.

    1. Чинники успіху і результати етапу реалізації

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

Основними результатами етапу реалізації є:

  • Розширений документ, що описує вимоги;

  • Розширена аналітична модель;

  • Розширений проект, який в даний момент завершується документацією;

  • Код, що складається з протестованих модулів;

  • Звіт, що описує результати тестів;

  • Спроектована і створена база даних;

  • Розклад етапу тестування.

  1. Приклад виконання етапу реалізації

Згідно з поставленими вимогами до етапу реалізації, було проведено розробку продукту «СОСtrial». До основих результатів даного етапу належить:

  1. Розширений документ, що описує вимоги.

На даному етапі розробки ПЗ не було внесено ніяких змін до документу описання вимог, оскільки було реалізовано лише ті вимоги, які було поставлено.

  1. Розширена аналітична модель.

Аналітична модель не була змінена порівняно з етапом розробки цієї моделі, було використано тільки її можливості для реалізації цього програмного забезпечення.

  1. Розширений проект, який у даний момент завершується документацією.

Проект складається з двох частин, а саме клієнта для адміністрування і створення тестувань та опитувань (Клієнт 1), і клієнта для проходження тестувань та опитувань (Клієнт 2).

В свою чергу Клієнт 1 складається з п’яти модулів:

FmMain – модуль, який відповідає за інтерфейс клієнта 1;

AccountManagerDAL – модуль, який відповідає за логування користувачів та адміністрування системи;

ReportBuilderDAL – модуль, який призначений для створення звітів успішності студентів, а також результатів опитувань;

SurveyBuilderDAL – модуль, який відповідає за створення тестувань та опитувань;

DataModule – модуль, призначений для організації зв’язку з базою даних.

Клієнт 2 складається з трьох модулів:

FmMain – модуль, який відповідає за інтерфейс клієнта 2;

SurveyDAL – модуль, що забезпечує проходження тестувань та опитувань думки;

DataModule – модуль, призначений для організації зв’язку з базою даних.

  1. Код, що складається з протестованих модулів.

Для реалізації системи СОСtrial було обрано середовище швидкої розробки програм для Windows Code Gear RAD Studio 2009, оскільки, є воно зручним у використанні і включає в себе великий набір стандартник компонент, які значно спрощують і пришвидшують процес розробки. Також в цьому середовищі досить легко будувати зручний інтерфейс.

Дане середовище програмування дає змогушвидко створювати програми мовою Delphi. Синтаксис мови Delphi є дуже простим і зрозумілим на відміну від інших мов програмування. Delphi-код легко читати і тестувати, що є дуже актуальним у випадку розробки великих систем, таких як ‘COCtrial’. Мова Delphi добре пристосована до створення Desktop-аплікацій і широко використовується при створенні різноманітних програм під Windows.Також мова Delphiвключає в себенабір бібліотек, таких як ADODB, призначених для реалізації систем типу клієнт-сервері систем які ваємодіють з базами даних.

Клієнт 1

FmMain. Це модуль який відповідає за інтерфейс клієнта 1.

Класи TMain, TAMFrame, TPassDlg, TRBFrame, TSBFrame, що він в себе включає, є класами інтерфейсу тобто класами-формами, які містять методи обробки стандартних подій та методи необхідні для функціонування інтерфейсу.

{ -------- Стандартні бліотеки використані в даному модулі -------- }

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, ComCtrls, sTreeView, acShellCtrls, Menus, StdCtrls,

ImgList, ToolWin, Grids, DBGrids,

ActnList, ExtCtrls, Buttons, ADODB, DBCtrls, Mask, FmAccManager;

{ -------- Підключення модулірозробленого модуля DataModule -------- }

uses

DataModule, AccountManagerDAL, FmOKCANCL, FmPassWord;

  • TMain– клас-форма, що включає в себе головне меню, а також фрейми менеджера користувачів (TAMFrame), будівника звітів (TRBFrame) і будівника тестувань та опитувань (TSBFrame).

Форма:

Код:

type

TMain = class(TForm)

ActionList1: TActionList;

Help: TAction;

ImageList1: TImageList;

SignIn: TAction;

SignOut: TAction;

Exit: TAction;

Splitter1: TSplitter;

Settings: TAction;

PopupMenu1: TPopupMenu;

DataBase1: TMenuItem;

DataBase: TAction;

PageControl1: TPageControl;

TabSheet1: TTabSheet;

TabSheet2: TTabSheet;

TabSheet3: TTabSheet;

StatusBar1: TStatusBar;

Frame11: TFrame1;

Splitter2: TSplitter;

CoolBar1: TCoolBar;

ToolBar1: TToolBar;

BitBtn4: TBitBtn;

BitBtn3: TBitBtn;

BitBtn2: TBitBtn;

ToolButton1: TToolButton;

BitBtn5: TBitBtn;

ToolButton2: TToolButton;

BitBtn1: TBitBtn;

procedure HelpExecute(Sender: TObject);

procedure ExitExecute(Sender: TObject);

procedure DataBaseExecute(Sender: TObject);

procedure SignInExecute(Sender: TObject);

procedure SignOutExecute(Sender: TObject);

procedure AboutExecute(Sender: TObject);

procedure SettingsExecute(Sender: TObject);

procedure ToolBar1MouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure FormShow(Sender: TObject);

end;

{ глобальні змінні }

var

P: boolean;

UsersDAL1: UsersDAL;

GroupsDAL1: GroupsDAL;

{метод що відображає вікно допомоги}

procedure TMain.AboutExecute(Sender: TObject);

begin

ShowMessage('Developed by Mo3oK :)');

end;

{метод що відображає діалогове вікно налаштевання зв’язку з базою}

procedure TMain.DataBaseExecute(Sender: TObject);

begin

DataModule1.Connection.Connected := false;

DataModule1.UsersStoredProc.Active := false;

DataModule1.GroupsStoredProc.Active := false;

DataModule1.Connection.ConnectionString := ADODB.PromptDataSource(Self.Handle,'');

DataModule1.GroupsStoredProc.Active := true;

DataModule1.UsersStoredProc.Active := true;

DataModule1.Connection.Connected := true;

end;

{ метод що відображає діалогове вікно закриття клієнта }

procedure TMain.ExitExecute(Sender: TObject);

begin

OKRightDlg.Label1.Caption := 'Do you realy want to exit?';

OKRightDlg.ShowModal;

if OKRightDlg.rez = true then

Close

else

OKRightDlg.Close;

end;

procedure TMain.FormShow(Sender: TObject);

begin

ShowMessage(inttostr(PasswordDlg.ShowModal));

UsersDAL1 := UsersDAL.Create;

GroupsDAL1 := GroupsDAL.Create;

end;

procedure TMain.HelpExecute(Sender: TObject);

begin

ShowMessage('Developed by Mo3oK :)');

end;

procedure TMain.SettingsExecute(Sender: TObject);

begin

if P = false then begin

PopupMenu1.Popup(Form1.Left + 186, Form1.Top + 84);

P := true

end else

P := false;

end;

{метод що проводить логування}

procedure TMain.SignInExecute(Sender: TObject);

begin

ShowMessage('Sing In!');

end;

{метод що проводить вихід з системи}

procedure TMain.SignOutExecute(Sender: TObject);

begin

ShowMessage('Sign Out!');

end;

procedure TMain.ToolBar1MouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

P := false;

end;

  • TAMFrame– клас-фрейм менеджера користувачів.

Форма:

Код:

type

TFrame1 = class(TFrame)

PageControl2: TPageControl;

TabSheet4: TTabSheet;

GroupBox2: TGroupBox;

Label3: TLabel;

Label4: TLabel;

Label5: TLabel;

Label6: TLabel;

Label7: TLabel;

ComboBox2: TComboBox;

Panel2: TPanel;

BitBtn6: TBitBtn;

BitBtn7: TBitBtn;

GroupBox1: TGroupBox;

Label1: TLabel;

Label2: TLabel;

Edit1: TEdit;

RadioGroup1: TRadioGroup;

ComboBox1: TComboBox;

Panel1: TPanel;

TabSheet5: TTabSheet;

GroupBox5: TGroupBox;

Labe11: TLabel;

Label13: TLabel;

SpeedButton1: TSpeedButton;

BitBtn12: TBitBtn;

Panel4: TPanel;

GroupBox4: TGroupBox;

Label10: TLabel;

Label12: TLabel;

Label9: TLabel;

BitBtn9: TBitBtn;

Panel3: TPanel;

BitBtn10: TBitBtn;

BitBtn11: TBitBtn;

GroupBox3: TGroupBox;

Label8: TLabel;

Edit2: TEdit;

RadioGroup2: TRadioGroup;

DBGrid2: TDBGrid;

DBGrid1: TDBGrid;

Panel6: TPanel;

Splitter1: TSplitter;

SpeedButton2: TSpeedButton;

Edit4: TEdit;

Edit5: TEdit;

Edit6: TEdit;

Edit7: TEdit;

Edit8: TEdit;

Edit9: TEdit;

Edit3: TEdit;

Edit10: TEdit;

Edit11: TEdit;

SpeedButton3: TSpeedButton;

BitBtn1: TBitBtn;

Panel5: TPanel;

procedure ToolBar1MouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure RadioGroup1Click(Sender: TObject);

procedure RadioGroup1Enter(Sender: TObject);

procedure ComboBox1Change(Sender: TObject);

procedure Edit1Change(Sender: TObject);

procedure DBGrid1CellClick(Column: TColumn);

procedure TabSheet5Show(Sender: TObject);

procedure TabSheet4Show(Sender: TObject);

procedure DBGrid1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);

procedure DBGrid2CellClick(Column: TColumn);

procedure DBGrid2KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);

procedure SpeedButton1Click(Sender: TObject);

procedure Edit2Change(Sender: TObject);

procedure RadioGroup2Click(Sender: TObject);

procedure DBGrid1TitleClick(Column: TColumn);

procedure DBGrid2TitleClick(Column: TColumn);

procedure DBGrid2StartDock(Sender: TObject;

var DragObject: TDragDockObject);

procedure BitBtn6Click(Sender: TObject);

procedure SpeedButton2Click(Sender: TObject);

procedure BitBtn7Click(Sender: TObject);

procedure Edit8KeyPress(Sender: TObject; var Key: Char);

procedure Edit4KeyPress(Sender: TObject; var Key: Char);

procedure Edit2KeyPress(Sender: TObject; var Key: Char);

procedure Edit1KeyPress(Sender: TObject; var Key: Char);

procedure SpeedButton3Click(Sender: TObject);

procedure BitBtn9Click(Sender: TObject);

procedure BitBtn11Click(Sender: TObject);

procedure BitBtn12Click(Sender: TObject);

procedure BitBtn1Click(Sender: TObject);

public

procedure RefreshUsers;

procedure RefreshGroups;

procedure FillFildsUsers;

procedure FillFildsGroups;

end;

var

P: boolean;

UsersDAL1: UsersDAL;

GroupsDAL1: GroupsDAL;

sort: string;

procedure TFrame1.DBGrid1CellClick(Column: TColumn);

begin

if PageControl2.ActivePage = TabSheet4 then

GroupsDAL1.GetGroupsByUserId(DBGrid1.Fields[0].AsInteger)

else

FillFildsGroups;

FillFildsUsers;

end;

procedure TFrame1.DBGrid1KeyUp(Sender: TObject; var Key: Word;

Shift: TShiftState);

begin

if PageControl2.ActivePage = TabSheet4 then

GroupsDAL1.GetGroupsByUserId(DBGrid1.Fields[0].AsInteger)

else

FillFildsGroups;

FillFildsUsers;

end;

procedure TFrame1.DBGrid2CellClick(Column: TColumn);

begin

if (PageControl2.ActivePage = TabSheet5) and (SpeedButton1.Down = false) then

Edit3.Text := IntToStr(UsersDAL1.GetUsersByGroupId(DBGrid2.Fields[0].AsInteger));

FillFildsGroups;

end;

procedure TFrame1.DBGrid2KeyUp(Sender: TObject; var Key: Word;

Shift: TShiftState);

begin

if (PageControl2.ActivePage = TabSheet5) and (SpeedButton1.Down = false) then

Edit3.Text := IntToStr(UsersDAL1.GetUsersByGroupId(DBGrid2.Fields[0].AsInteger));

FillFildsGroups;

end;

//------------ методи для сортування списків ---------------

procedure TFrame1.DBGrid1TitleClick(Column: TColumn);

{$J+}

const PreviousColumnIndex : integer = 0;

{$J-}

begin

if DBGrid1.DataSource.DataSet is TADOStoredProc then

with TADOStoredProc(DBGrid1.DataSource.DataSet) do

begin

if (Pos(string(Column.Field.FieldName), string(Sort)) = 1)

and (Pos(string(' DESC'), string(Sort))= 0) then

Sort := Column.Field.FieldName + ' DESC'

else

Sort := Column.Field.FieldName + ' ASC';

end;

end;

procedure TFrame1.DBGrid2TitleClick(Column: TColumn);

{$J+}

const PreviousColumnIndex : integer = 0;

{$J-}

begin

if DBGrid2.DataSource.DataSet is TADOStoredProc then

with TADOStoredProc(DBGrid2.DataSource.DataSet) do

begin

if (Pos(string(Column.Field.FieldName), string(Sort)) = 1)

and (Pos(string(' DESC'), string(Sort))= 0) then

Sort := Column.Field.FieldName + ' DESC'

else

Sort := Column.Field.FieldName + ' ASC';

end;

end;

//------------------------------------

procedure TFrame1.Edit1Change(Sender: TObject);

begin

RefreshUsers;

end;

procedure TFrame1.Edit1KeyPress(Sender: TObject; var Key: Char);

begin

if ((RadioGroup1.ItemIndex = 0) and not (Key in ['0'..'9',#8])) or

((Length(Edit2.Text) = 9) and (Key <> #8)) then

Key := #0;

end;

procedure TFrame1.Edit2Change(Sender: TObject);

begin

RefreshGroups;

FillFildsGroups;

end;

procedure TFrame1.Edit2KeyPress(Sender: TObject; var Key: Char);

begin

if ((RadioGroup2.ItemIndex = 0) and not (Key in ['0'..'9',#8])) or

((Length(Edit2.Text) = 9) and (Key <> #8)) then

Key := #0;

end;

procedure TFrame1.Edit4KeyPress(Sender: TObject; var Key: Char);

begin

if ((RadioGroup1.ItemIndex = 0) and not (Key in ['0'..'9',#8])) or

((Length(Edit4.Text) = 9) and (Key <> #8)) then

Key := #0;

end;

procedure TFrame1.Edit8KeyPress(Sender: TObject; var Key: Char);

begin

if ((RadioGroup2.ItemIndex = 0) and not (Key in ['0'..'9',#8])) or

((Length(Edit8.Text) = 9) and (Key <> #8)) then

Key := #0;

end;

procedure TFrame1.SpeedButton1Click(Sender: TObject);

begin

if SpeedButton1.Down = true then

UsersDAL1.GetUsersByRoleId(3)

else

UsersDAL1.GetUsersByGroupId(DBGrid2.Fields[0].AsInteger);

end;

procedure TFrame1.SpeedButton2Click(Sender: TObject);

begin

Edit4.Text := IntToStr(UsersDAL1.GetFreeUserId);

end;

procedure TFrame1.SpeedButton3Click(Sender: TObject);

begin

Edit8.Text := IntToStr(GroupsDAL1.GetFreeGroupId);

end;

procedure TFrame1.TabSheet4Show(Sender: TObject);

begin

DBGrid1.Align := alNone;

DBGrid2.Align := alNone;

Splitter1.Align := alNone;

DBGrid1.Left := 0;

DBGrid2.Left := 723;

DBGrid1.Align := alLeft;

Splitter1.Align := alLeft;

DBGrid2.Align := alClient;

RefreshUsers;

FillFildsUsers;

end;

procedure TFrame1.TabSheet5Show(Sender: TObject);

begin

DBGrid1.Align := alNone;

DBGrid2.Align := alNone;

Splitter1.Align := alNone;

DBGrid1.Left := 174;

DBGrid2.Left := 0;

DBGrid2.Align := alLeft;

Splitter1.Align := alLeft;

DBGrid1.Align := alClient;

RefreshGroups;

FillFildsGroups;

end;

procedure TFrame1.ToolBar1MouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

P := false;

end;

//----------------- Account Manager -> Users -------------------

procedure TFrame1.FillFildsGroups;

begin

Edit8.Text := IntToStr(DBGrid2.Fields[0].AsInteger);

Edit9.Text := DBGrid2.Fields[1].AsString;

Edit10.Text := DBGrid1.Fields[1].AsString;

Edit11.Text := DBGrid2.Fields[1].AsString;

end;

procedure TFrame1.FillFildsUsers;

begin

Edit4.Text := IntToStr(DBGrid1.Fields[0].AsInteger);

Edit5.Text := DBGrid1.Fields[1].AsString;

Edit6.Text := DBGrid1.Fields[2].AsString;

Edit7.Text := DBGrid1.Fields[3].AsString;

if DBGrid1.Fields[4].AsString = 'Administrator' then ComboBox2.ItemIndex := 0;

if DBGrid1.Fields[4].AsString = 'Teacher' then ComboBox2.ItemIndex := 1;

if DBGrid1.Fields[4].AsString = 'Student' then ComboBox2.ItemIndex := 2;

end;

procedure TFrame1.RefreshUsers;

begin

if Edit1.Text = '' then

UsersDAL1.GetUsersByRoleId(ComboBox1.ItemIndex)

else

case RadioGroup1.ItemIndex of

0: UsersDAL1.GetUsersById(StrToInt(Edit1.Text), ComboBox1.ItemIndex);

1: UsersDAL1.GetUsersByName(Edit1.Text, ComboBox1.ItemIndex);

2: UsersDAL1.GetUsersByLogin(Edit1.Text, ComboBox1.ItemIndex);

3: UsersDAL1.GetUsersByPassword(Edit1.Text, ComboBox1.ItemIndex);

end;

GroupsDAL1.GetGroupsByUserId(DBGrid1.Fields[0].AsInteger);

end;

procedure TFrame1.RefreshGroups;

begin

if Edit2.Text = '' then

GroupsDAL1.GetGroupsByName

else

case RadioGroup2.ItemIndex of

0: GroupsDAL1.GetGroupsById(StrToInt(Edit2.Text));

1: GroupsDAL1.GetGroupsByName(Edit2.Text);

end;

Edit3.Text := IntToStr(UsersDAL1.GetUsersByGroupId(DBGrid2.Fields[0].AsInteger));

end;

{- filter -}

procedure TFrame1.BitBtn11Click(Sender: TObject);

begin

OKRightDlg.Label1.Caption := ' Are you sure?';

OKRightDlg.ShowModal;

if OKRightDlg.rez = true then begin

with GroupsDAL1 do begin

if ((IsInName(Edit9.Text) = 1) and (IsInGroupId(StrToInt(Edit8.Text)) = 1)) or

(IsInName(Edit9.Text) = 1) then

ShowMessage(' This user already exists!')

else begin

if (IsInGroupId(StrToInt(Edit8.Text)) = 1) then

UpdateGroup(StrToInt(Edit8.Text), Edit9.Text)

else

AddGroup(StrToInt(Edit8.Text), Edit9.Text);

RefreshUsers;

end;

end;

end else

OKRightDlg.Close;

end;

procedure TFrame1.BitBtn1Click(Sender: TObject);

begin

GroupsDAL1.AddUserToGroup(DBGrid1.Fields[0].AsInteger,DBGrid2.Fields[0].AsInteger);

RefreshUsers;

RefreshGroups;

end;

procedure TFrame1.BitBtn12Click(Sender: TObject);

begin

GroupsDAL1.DeleteUserFromGroup(DBGrid1.Fields[0].AsInteger,DBGrid2.Fields[0].AsInteger);

RefreshUsers;

RefreshGroups;

end;

procedure TFrame1.BitBtn6Click(Sender: TObject);

begin

OKRightDlg.Label1.Caption := ' Are you sure?';

OKRightDlg.ShowModal;

if OKRightDlg.rez = true then begin

with UsersDAL1 do begin

if ((IsInLogin(Edit6.Text) = 1) and (IsInUserId(StrToInt(Edit4.Text)) = 1)) or

(IsInLogin(Edit6.Text) = 1) then

ShowMessage(' This user already exists!')

else begin

if (IsInUserId(StrToInt(Edit4.Text)) = 1) then

UpdateUser(StrToInt(Edit4.Text), Edit5.Text, Edit6.Text, Edit7.Text, ComboBox2.ItemIndex + 1)

else

AddUser(StrToInt(Edit4.Text), Edit5.Text, Edit6.Text, Edit7.Text, ComboBox2.ItemIndex + 1);

RefreshUsers;

end;

end;

end else

OKRightDlg.Close;

end;

procedure TFrame1.BitBtn7Click(Sender: TObject);

begin

OKRightDlg.Label1.Caption := ' Are you sure?';

OKRightDlg.ShowModal;

if OKRightDlg.rez = true then begin

UsersDAL1.DeleteUser(StrToInt(Edit4.Text));

RefreshUsers

end else

OKRightDlg.Close;

end;

procedure TFrame1.BitBtn9Click(Sender: TObject);

begin

OKRightDlg.Label1.Caption := ' Are you sure?';

OKRightDlg.ShowModal;

if OKRightDlg.rez = true then begin

GroupsDAL1.DeleteGroup(StrToInt(Edit8.Text));

RefreshUsers

end else

OKRightDlg.Close;

end;

procedure TFrame1.ComboBox1Change(Sender: TObject);

begin

Edit1.Text := '';

UsersDAL1.GetUsersByRoleId(ComboBox1.ItemIndex);

end;

{---------}

procedure TFrame1.RadioGroup1Click(Sender: TObject);

begin

Edit1.Text := '';

Edit1.SetFocus;

end;

procedure TFrame1.RadioGroup1Enter(Sender: TObject);

begin

P := false;

end;

procedure TFrame1.RadioGroup2Click(Sender: TObject);

begin

Edit2.Text := '';

Edit2.SetFocus;

end;

TSBFrame – клас-фрейм будівника тестувань та опитувань;

TRBFrame – клас-фрейм будівника звітів;

TPassDlg – клас-форма логування.

Форма:

Код:

type

TPasswordDlg = class(TForm)

Panel1: TPanel;

GroupBox1: TGroupBox;

Label1: TLabel;

Edit1: TEdit;

Label2: TLabel;

CancelBtn: TButton;

OKBtn: TButton;

Edit2: TEdit;

procedure OKBtnClick(Sender: TObject);

function ShowModal: integer; override;

private

{ Private declarations }

public

{ Public declarations }

end;

{глобальні змінні}

var

PasswordDlg: TPasswordDlg, Role_Id: integer;

{метод обробки події натиснення кнопки Enter}

procedure TPasswordDlg.OKBtnClick(Sender: TObject);

var

UsersDAL1: UsersDAL;

begin

UsersDAL1 := UsersDAL.Create;

Role_Id := UsersDAL1.GetRoleId(Edit1.Text, Edit2.Text);

UsersDAL1.Destroy;

end;

function TPasswordDlg.ShowModal: integer;

begin

inherited ShowModal;

ShowModal := Role_Id;

end;

AccountManagerDAL: Модуль, який відповідає за логування користувачів та адміністрування системи. Він включає в себе два класи: TUsersDAL, TGroupsDAL.

{ -------- Стандартні бліотеки використані в даному модулі -------- }

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls;

{ -------- Підключення модулірозробленого модуля DataModule -------- }

uses

DataModule;

  • UsersDAL– клас, що містить методи для роботи з користувацькими записами системи, такі як: GetRoleId (отримати роль користувача), GetFreeUserId (отримати вільне ID користувача), IsInLogin (перевірка, за логіном, наявності запису користувача в базі), IsInUserId (перевірка, заID, наявності запису користувача в базі), AddUser (добавити користувача), UpdateUser (обновити запис користувача), DeleteUser (видалити запис користувача), GetUsers (отримати список користувачів), GetUsersById (отримати список користувачів заID), GetUsersByName (отримати список користувачів за іменем), GetUsersByLogin (отримати список користувачів за логіном), GetUsersByPassword (отримати список користувачів за паролем), GetUsersByRoleId (отримати список користувачів за ролю), GetUsersByGroupId (отримати список користувачів заIDгрупи).

TUsersDAL = class (TObject)

function GetRoleId(Login,Password: string): integer;

function GetFreeUserId: integer;

function IsInLogin(Login: string): integer;

function IsInUserId(UserId: integer): integer;

//------- actions ---------

procedure AddUser(UserId: integer; FullName: string; Login: string; Password: string; RoleId: integer);

procedure UpdateUser(UserId: integer; FullName: string; Login: string; Password: string; RoleId: integer);

procedure DeleteUser(UserId: integer);

//------- view --------

procedure GetUsers;

procedure GetUsersById(UserId: integer; RoleId: integer = 0);

procedure GetUsersByName(Name: string; RoleId: integer = 0);

procedure GetUsersByLogin(Login: string; RoleId: integer = 0);

procedure GetUsersByPassword(Password: string; RoleId: integer = 0);

procedure GetUsersByRoleId(RoleId: integer = 0);

function GetUsersByGroupId(GroupId: integer): integer;

end;

{----------------------------------------------------------------------------------------------------}

{ метод для перевірки, за логіном, наявності запису користувача в базі }

function TUsersDAL.IsInLogin(Login: string): integer;

begin

DataModule1.ActionStoredProc.ProcedureName := 'IsInLogin';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := Login;

DataModule1.ActionStoredProc.ExecProc;

IsInLogin := DataModule1.ActionStoredProc.Parameters[0].Value;

end;

{ метод для перевірки, за ID, наявності запису користувача в базі }

function TUsersDAL.IsInUserId(UserId: integer): integer;

begin

DataModule1.ActionStoredProc.ProcedureName := 'IsInUserId';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := UserId;

DataModule1.ActionStoredProc.ExecProc;

IsInUserId := DataModule1.ActionStoredProc.Parameters[0].Value;

end;

{ метод для отримання ролі користувача}

function TUsersDAL.GetRoleId(Login, Password: string): integer;

begin

DataModule1.ActionStoredProc.ProcedureName := 'GetRoleId';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := 0;

DataModule1.ActionStoredProc.Parameters[2].Value := Login;

DataModule1.ActionStoredProc.Parameters[3].Value := Password;

DataModule1.ActionStoredProc.ExecProc;

GetRoleId := DataModule1.ActionStoredProc.Parameters[1].Value;

end;

{ метод для отримання вільного ID користувача}

function TUsersDAL.GetFreeUserId: integer;

begin

DataModule1.ActionStoredProc.ProcedureName := 'GetFreeUserId';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.ExecProc;

GetFreeUserId := DataModule1.ActionStoredProc.Parameters[0].Value;

end;

//----- add --------

{ метод для добавлення користувача в базу }

procedure TUsersDAL.AddUser(UserId: integer; FullName: string; Login: string; Password: string; RoleId: integer);

begin

DataModule1.ActionStoredProc.ProcedureName := 'AddUser';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := UserId;

DataModule1.ActionStoredProc.Parameters[2].Value := FullName;

DataModule1.ActionStoredProc.Parameters[3].Value := Login;

DataModule1.ActionStoredProc.Parameters[4].Value := Password;

DataModule1.ActionStoredProc.Parameters[5].Value := RoleId;

DataModule1.ActionStoredProc.ExecProc;

end;

{ метод для обновлення запису користувача }

procedure TUsersDAL.UpdateUser(UserId: integer; FullName: string; Login: string; Password: string; RoleId: integer);

begin

DataModule1.ActionStoredProc.ProcedureName := 'UpdateUser';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := UserId;

DataModule1.ActionStoredProc.Parameters[2].Value := FullName;

DataModule1.ActionStoredProc.Parameters[3].Value := Login;

DataModule1.ActionStoredProc.Parameters[4].Value := Password;

DataModule1.ActionStoredProc.Parameters[5].Value := RoleId;

DataModule1.ActionStoredProc.ExecProc;

end;

{ метод для видалення запису користувача з бази }

procedure TUsersDAL.DeleteUser(UserId: integer);

begin

DataModule1.ActionStoredProc.ProcedureName := 'DeleteUser';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := UserId;

DataModule1.ActionStoredProc.ExecProc;

end;

//----- view -------

{ метод для отримання списку користувачів }

procedure TUsersDAL.GetUsers;

begin

DataModule1.UsersStoredProc.Active := false;

DataModule1.UsersStoredProc.ProcedureName := 'GetUsers';

DataModule1.UsersStoredProc.Active := true;

end;

{ метод для фільтрації списку користувачів за ID }

procedure TUsersDAL.GetUsersById(UserId: integer; RoleId: integer =0);

begin

DataModule1.UsersStoredProc.Active := false;

DataModule1.UsersStoredProc.Parameters.Clear;

DataModule1.UsersStoredProc.ProcedureName := 'GetUsersById';

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := UserId;

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := RoleId;

DataModule1.UsersStoredProc.Active := true;

end;

{ метод для фільтрації списку користувачів за іменем }

procedure TUsersDAL.GetUsersByName(Name: string; RoleId: integer = 0);

begin

DataModule1.UsersStoredProc.Active := false;

DataModule1.UsersStoredProc.Parameters.Clear;

DataModule1.UsersStoredProc.ProcedureName := 'GetUsersByName';

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := Name;

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := RoleId;

DataModule1.UsersStoredProc.Active := true;

end;

{ метод для фільтрації списку користувачів за логіном }

procedure TUsersDAL.GetUsersByLogin(Login: string; RoleId: integer = 0);

begin

DataModule1.UsersStoredProc.Active := false;

DataModule1.UsersStoredProc.Parameters.Clear;

DataModule1.UsersStoredProc.ProcedureName := 'GetUsersByLogin';

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := Login;

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := RoleId;

DataModule1.UsersStoredProc.Active := true;

end;

{ метод для фільтрації списку користувачів за паролем }

procedure TUsersDAL.GetUsersByPassword(Password: string; RoleId: integer = 0);

begin

DataModule1.UsersStoredProc.Active := false;

DataModule1.UsersStoredProc.Parameters.Clear;

DataModule1.UsersStoredProc.ProcedureName := 'GetUsersByPassword';

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := Password;

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := RoleId;

DataModule1.UsersStoredProc.Active := true;

end;

{ метод для фільтрації списку користувачів за роллю }

procedure TUsersDAL.GetUsersByRoleId(RoleId: integer = 0);

begin

DataModule1.UsersStoredProc.Active := false;

DataModule1.UsersStoredProc.Parameters.Clear;

DataModule1.UsersStoredProc.ProcedureName := 'GetUsersByRoleId';

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := RoleId;

DataModule1.UsersStoredProc.Active := true;

end;

{ метод для фільтрації списку користувачів за ID групи }

function TUsersDAL.GetUsersByGroupId(GroupId: Integer): Integer;

begin

DataModule1.UsersStoredProc.Active := false;

DataModule1.UsersStoredProc.Parameters.Clear;

DataModule1.UsersStoredProc.ProcedureName := 'GetUsersByGroupId';

DataModule1.UsersStoredProc.Parameters.AddParameter.Value := GroupId;

DataModule1.UsersStoredProc.Active := true;

Result := DataModule1.UsersStoredProc.RecordCount;

end;

  • TGroupsDAL– клас, який містить методи якого необхідні для роботи з групами користувачів системи, такі як: GetFreeGroupId (отримати вільне ID групи), IsInGroupId (перевірити, заID, наявність групи), IsInName (перевірити, за назвою, наявність групи); AddGroup (добавити групу), UpdateGroup (обновити інформації про групу); DeleteGroup (видалити групу), AddUserToGroup (добавити студента в групу); DeleteUserFromGroup (видалити студента з групи), GetGroupsByName (отримати список груп за назвою), GetGroupsByUserId (оримати список груп заIDстудента), GetGroupsById (отримати список груп заIDгрупи).

TGroupsDAL = class (TObject)

function GetFreeGroupId: integer;

function IsInGroupId(GroupId: integer): integer;

Function IsInName(Name: string): integer;

//------- actions ---------

procedure AddGroup(GroupId: integer; Name: string);

procedure UpdateGroup(GroupId: integer; Name: string);

procedure DeleteGroup(GroupId: integer);

procedure AddUserToGroup(UserId: integer; GroupId: integer);

procedure DeleteUserFromGroup(UserId: integer; GroupId: integer);

//------- view ---------

procedure GetGroupsByName(Name: string = '');

procedure GetGroupsByUserId(UserId: integer);

procedure GetGroupsById(GroupId: integer);

end;

{--------------------------------------------------------------------------------------------------------}

{ метод для отримання вільного ID групи}

function TGroupsDAL.GetFreeGroupId: integer;

begin

DataModule1.ActionStoredProc.ProcedureName := 'GetFreeGroupId';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.ExecProc;

GetFreeGroupId := DataModule1.ActionStoredProc.Parameters[0].Value;

end;

{ метод для перевірки, за ID, наявності групи в базі }

function TGroupsDAL.IsInGroupId(GroupId: integer): integer;

begin

DataModule1.ActionStoredProc.ProcedureName := 'IsInGroupId';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := GroupId;

DataModule1.ActionStoredProc.ExecProc;

IsInGroupId := DataModule1.ActionStoredProc.Parameters[0].Value;

end;

{ метод для перевірки, за назвою, наявності групи в базі }

function TGroupsDAL.IsInName(Name: string): integer;

begin

DataModule1.ActionStoredProc.ProcedureName := 'IsInName';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := Name;

DataModule1.ActionStoredProc.ExecProc;

IsInName := DataModule1.ActionStoredProc.Parameters[0].Value;

end;

//------- actions ---------

{ метод для добавлення груп в базу }

procedure TGroupsDAL.AddGroup(GroupId: integer; Name: string);

begin

DataModule1.ActionStoredProc.ProcedureName := 'AddGroup';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := GroupId;

DataModule1.ActionStoredProc.Parameters[2].Value := Name;

DataModule1.ActionStoredProc.ExecProc;

end;

{ метод для видалення групи }

procedure TGroupsDAL.DeleteGroup(GroupId: integer);

begin

DataModule1.ActionStoredProc.ProcedureName := 'DeleteGroup';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := GroupId;

DataModule1.ActionStoredProc.ExecProc;

end;

{ метод для добавлення студента в групу }

procedure TGroupsDAL.AddUserToGroup(UserId: integer; GroupId: integer);

begin

DataModule1.ActionStoredProc.ProcedureName := 'AddUserToGroup';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := UserId;

DataModule1.ActionStoredProc.Parameters[2].Value := GroupId;

DataModule1.ActionStoredProc.ExecProc;

end;

{ метод для видалення студента з групи }

procedure TGroupsDAL.DeleteUserFromGroup(UserId: integer; GroupId: integer);

begin

DataModule1.ActionStoredProc.ProcedureName := 'DeleteUserFromGroup';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := UserId;

DataModule1.ActionStoredProc.Parameters[2].Value := GroupId;

DataModule1.ActionStoredProc.ExecProc;

end;

{ метод для обновлення інформації про групу }

procedure TGroupsDAL.UpdateGroup(GroupId: integer; Name: string);

begin

DataModule1.ActionStoredProc.ProcedureName := 'UpdateGroup';

DataModule1.ActionStoredProc.Parameters.Refresh;

DataModule1.ActionStoredProc.Parameters[1].Value := GroupId;

DataModule1.ActionStoredProc.Parameters[2].Value := Name;

DataModule1.ActionStoredProc.ExecProc;

end;

// ----------- view ----------------

{ метод для фільтрації груп за назвою }

procedure TGroupsDAL.GetGroupsByName(Name: string = '');

begin

DataModule1.GroupsStoredProc.Active := false;

DataModule1.GroupsStoredProc.Parameters.Clear;

DataModule1.GroupsStoredProc.ProcedureName := 'GetGroups';

DataModule1.GroupsStoredProc.Parameters.AddParameter.Value := Name;

DataModule1.GroupsStoredProc.Active := true;

end;

{ метод для фільтрації груп за ID студента }

procedure TGroupsDAL.GetGroupsByUserId(UserId: integer);

begin

DataModule1.GroupsStoredProc.Active := false;

DataModule1.GroupsStoredProc.Parameters.Clear;

DataModule1.GroupsStoredProc.ProcedureName := 'GetGroupsByUserId';

DataModule1.GroupsStoredProc.Parameters.AddParameter.Value := UserId;

DataModule1.GroupsStoredProc.Active := true;

end;

{ метод для фільтрації груп за ID групи }

procedure TGroupsDAL.GetGroupsById(GroupId: integer);

begin

DataModule1.GroupsStoredProc.Active := false;

DataModule1.GroupsStoredProc.Parameters.Clear;

DataModule1.GroupsStoredProc.ProcedureName := 'GetGroupsById';

DataModule1.GroupsStoredProc.Parameters.AddParameter.Value := GroupId;

DataModule1.GroupsStoredProc.Active := true;

end;

ReportBuilderDAL: Модуль, призначений для створення звітів успішності студентів, а також результатів опитувань. Він включає в себе клас TReportDAL.

{ -------- Стандартні бліотеки використані в даному модулі -------- }

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, RaveReports;

{ -------- Підключення модулірозробленого модуля DataModule -------- }

uses

DataModule;

TReportDAL – клас, який містить методи необхідні для роботи зі звітами системи, такі як: CreateSurveyReport (створити звіт за іменем опитування), CreateTestReport (створити звіт за іменем тестування), GetUserTestResults (отримати результат тесту окремого користувача).

TReportDAL = class (TObject)

procedure TReportDAL.CreateSurveyReport (SurveyName: string);

procedure TReportDAL.CreateTestReport (TestName: string);

function TReportDAL.GetUserTestResults (User_Id: integer): TStrings;

end;

{--------------------------------------------------------------------------------------------------------}

{ метод для створення звіту за іменем опитування}

procedure TReportDAL.CreateSurveyReport (SurveyName: string);

begin

{ some code }

end;

{ метод для створення звіту за іменем тестування }

procedure TReportDAL.CreateTestReport (TestName: string);

begin

{ some code }

end;

{ метод для отримання результатів тесту окремого користувача}

function TReportDAL.GetUserTestResults (User_Id: integer): TStrings;

begin

{ some code }

end;

SurveyBuilderDAL: Модуль, який відповідає за створення тестувань та опитувань. Даний модуль включає в себе два класи: TSurveyDAL,TSurvey.

{ -------- Стандартні бліотеки використані в даному модулі -------- }

uses

Windows, Messages, SysUtils, Variants, Classes , Controls;

{ -------- Підключення модулірозробленого модуля DataModule -------- }

uses

DataModule;

  • TSurveyDAL– клас, який включає методи призначені для завантаження, видалення та відтворення списків тестувань та опитувань, такі як: IsInName (перевірка за назвою, наявності тестування / опитування),LoadSurvey(завантажити тестування / опитування),SaveSurvey(заберегти тестування / опитування), UpdateSurvey(обновити тестування / опитування), DeleteSurvey(видалити тестування / опитування), GetSurveysByUserId(отримати список тестувань / опитувань доступних конкретному користувач), GetSurveysByGroupId(отримати список тестувань / опитувань доступних конкретній групі).

TSurveyDAL = class (TObject)

function IsInName(Name: string): integer;

function LoadSurvey(Survey_Id: integer):TSurvey;

procedure SaveSurvey(Survey: TSurvey);

procedure UpdateSurvey(Survey: TSurvey);

procedure DeleteSurvey(Survey_Id: integer);

function GetSurveysByUserId(User_Id: integer):TStringList;

function GetSurveysByGroupId(Group_Id: integer):TStringList;

end;

{--------------------------------------------------------------------------------------------------------}

{ метод для перевірки, за назвою, наявності тестування / опитування в базі даних }

function TSurveyDAL.IsInName(Name: string): integer;

begin

{ some code }

end;

{ метод для завантаження тестування / опитування з бази }

function TSurveyDAL.LoadSurvey(Survey_Id: integer):TSurvey;

begin

{ some code }

end;

{ метод для забереження тестування / опитування в базу }

procedure TSurveyDAL.SaveSurvey(Survey: TSurvey);

begin

{ some code }

end;

{ метод для обновлення тестування / опитування }

procedure TSurveyDAL.UpdateSurvey(Survey: TSurvey);

begin

{ some code }

end;

{ метод для видалення тестування / опитування }

procedure TSurveyDAL.DeleteSurvey(Survey_Id: integer);

begin

{ some code }

end;

{ метод для отримання списку тестувань / опитувань доступних конкретному користувачу }

function TSurveyDAL.GetSurveysByUserId(User_Id: integer):TStringList;

begin

{ some code }

end;

{ метод для отримання списку тестувань / опитувань доступних конкретній групі }

function TSurveyDAL.GetSurveysByGroupId(Group_Id: integer):TStringList;

begin

{ some code }

end;

  • TSurvey– клас для створення тестувань та опитувань та їх збереження у вигляді об’єкта (екземпляра даного класу). Містить методи такі як:CreateSurvey(створити тестування / опитування),AddQuestion(додати запинання до тестування / опитування),GetQuestions(відтворити запитання тестування / опитування),DeleteQuestion(видалити запинання з тестування / опитування).

TSurvey = class (TObject)

procedure CreateSurvey;

procedure AddQuestion(Questions: TStringList);

function GetQuestions: TStringList;

procedure DeleteQuestion(Question_Id: integer);

end;

{--------------------------------------------------------------------------------------------------------}

{ метод для створення тестування / опитування }

procedure TSurvey .CreateSurvey;

begin

{ some code }

end;

{ метод для додавання запинання до тестування / опитування }

procedure TSurvey .AddQuestion(Questions: TStringList);

begin

{ some code }

end;

{ метод для відтворення запинань тестування / опитування }

function TSurvey .GetQuestions: TStringList;

begin

{ some code }

end;

{ метод для видалення запинання з тестування / опитування }

procedure TSurvey .DeleteQuestion(Question_Id: integer);

begin

{ some code }

end;

DataModule. Цей модуль призначений для організації зв’язку з базою даних, включає в себе клас TDataModule.

{ -------- Стандартні бліотеки використані в даному модулі -------- }

uses

SysUtils, Classes, DB, ADODB;

TDataModule – клас, що включає в себе компоненти необхідні для зв’язку та роботи з базою.

Ф

2

2

6

орма:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]