- •Міністерство освіти та науки України в.В. Литвин, н.Б. Шаховська Проектування інформаційних систем
- •Передмова наукового редактора серії підручників «комп’ютинґ»
- •1.1. Складність програмного забезпечення
- •1.2. Структура складних систем
- •1.2.1. Приклади складних систем
- •1.2.2. П'ять ознак складної системи
- •1.2.3. Організована і неорганізована складність
- •1.3. Методи подолання складності
- •1.3.1. Роль декомпозиції
- •1.3.3. Роль абстракції
- •1.3.4. Роль ієрархії
- •1.4. Про проектування складних систем
- •1.4.1. Інженерна справа як наука і мистецтво
- •1.4.2. Сенс проектування
- •4. Методи подолання складності.
- •2.1. Базові означення
- •2.2. Методи проектування інформаційних систем
- •2.3. Види інформаційних систем
- •2.4. Рівні моделей даних
- •3. Види інформаційних систем.
- •3.1. Методологія процедурно-орієнтованого програмування
- •3.2. Методологія об'єктно-орієнтованого програмування
- •3.3. Методологія об'єктно-орієнтованого аналізу і проектування
- •3.4. Методологія системного аналізу і системного моделювання
- •4.1. Передісторія. Математичні основи
- •4.1.1. Теорія множин
- •4.1.2. Теорія графів
- •4.1.3. Семантичні мережі
- •4.2. Діаграми структурного системного аналізу
- •4.3. Основні етапи розвитку uml
- •3. Семантичні мережі.
- •5.1. Принципи структурного підходу до проектування
- •5.2. Структурний аналіз
- •5.3. Структурне проектування
- •5.4. Методологія структурного аналізу
- •5.5. Інструментальні засоби структурного аналізу та проектування
- •6.1. Основні елементи
- •6.2. Типи зв’язків
- •6.3. Техніка побудови
- •6.4. Діаграма бізнес – функцій
- •6.4.1. Призначення діаграми бізнес-функцій
- •6.4.2. Основні елементи
- •7.1. Призначення діаграм потоків даних та основні елементи
- •7.1.1. Зовнішні сутності
- •7.1.2. Процеси
- •7.1.3. Накопичувачі даних
- •7.1.4. Потоки даних
- •7.2. Методологія побудови dfd.
- •8.1. Діаграма «сутність-зв’язок»
- •8.2. Діаграма атрибутів
- •8.3. Діаграма категоризації
- •8.4. Обмеження діаграм сутність-зв’язок
- •8.5. Методологія idef1
- •9.1. Основні елементи
- •9.2. Типи керуючих потоків
- •9.3. Принципи побудови
- •10.1. Структурні карти Константайна
- •10.2. Структурні карти Джексона
- •11.1. Призначення case-технологій
- •11.2. Інструментальний засіб bPwin
- •11.2.4. Інші діаграми bpWin
- •11.2.5. Моделі as is і to be
- •11.3.1. Основні властивості
- •11.3.2. Стандарт idef1x
- •11.4. Програмний засіб Visio
- •12.1. Системний аналіз області наукових досліджень
- •12.1.1. Аналіз предметної області
- •12.2. Системний аналіз біржі праці
- •12.2.1. Дерево цілей
- •12.2.2. Опис об’єктів предметної області
- •12.2.3. Концептуальна модель
- •14.1. Еволюція об'єктної моделі
- •14.1.1. Основні положення об'єктної моделі
- •14.2. Складові частини об'єктного підходу
- •14.2.1. Парадигми програмування
- •14.2.2. Абстрагування
- •14.2.3. Інкапсуляція
- •14.2.4. Модульність
- •14.2.5. Ієрархія
- •14.2.7. Паралелізм
- •14.2.8. Збереженість
- •14.3. Застосування об'єктної моделі
- •14.3.1. Переваги об'єктної моделі
- •14.3.2. Використання об'єктного підходу
- •14.3.3. Відкриті питання
- •15.1. Природа об'єкта
- •15.1.1. Що є й що не є об'єктом?
- •15.1.2. Стан
- •15.1.3. Поведінка
- •15.1.4. Ідентичність
- •Void drag(DisplayItem I); // Небезпечно
- •15.2. Відношення між об'єктами
- •15.2.1. Типи відношень
- •15.2.2. Зв'язки
- •15.2.3. Агрегація
- •15.3. Природа класів
- •15.3.1. Що таке клас?
- •15.3.2. Інтерфейс і реалізація
- •15.3.3. Життєвий цикл класу
- •15.4. Відношення між класами
- •15.4.1. Типи відношень
- •15.4.2. Асоціація
- •15.4.3. Успадкування
- •15.4.4. Агрегація
- •15.4.5. Використання
- •15.4.6. Інсталювання (Параметризація)
- •15.4.6. Метакласи
- •15.5. Взаємозв'язок класів і об'єктів
- •15.5.1. Відношення між класами й об'єктами
- •15.5.2. Роль класів і об'єктів в аналізі й проектуванні
- •16.1. Важливість правильної класифікації
- •16.1.1. Класифікація й об’єктно-орієнтовне проектування
- •16.1.2. Труднощі класифікації
- •16.2. Ідентифікація класів і об'єктів
- •16.2.1. Класичний і сучасний підходи
- •16.2.2. Об’єктно-орієнтований аналіз
- •16.3. Ключові абстракції й механізми
- •16.3.1. Ключові абстракції
- •16.3.2. Ідентифікація механізмів
- •17.1. Призначення мови uml
- •17.2. Загальна структура мови uml
- •17.3. Пакети в мові uml
- •17.4. Основні пакети мета-моделі мови uml
- •17.5. Специфіка опису мета-моделі мови uml
- •17.6. Особливості зображення діаграм мови uml
- •18.1. Варіант використання
- •18.2. Актори
- •18.3. Інтерфейси
- •18.4. Примітки
- •18.5. Відношення на діаграмі варіантів використання
- •18.5.1. Відношення асоціації
- •13.5.2. Відношення розширення
- •18.5.3. Відношення узагальнення
- •18.5.4. Відношення включення
- •18.6. Приклад побудови діаграми варіантів використання
- •18.7. Рекомендації з розроблення діаграм варіантів використання
- •19.1. Клас
- •19.1.1. Ім'я класу
- •19.1.2. Атрибути класу
- •19.1.3. Операція
- •19.2. Відношення між класами
- •19.2.1. Відношення залежності
- •19.2.2. Відношення асоціації
- •19.2.3. Відношення агрегації
- •19.2.4. Відношення композиції
- •19.2.5. Відношення узагальнення
- •19.3. Інтерфейси
- •19.5. Шаблони або параметризовані класи
- •19.6. Рекомендації з побудови діаграми класів
- •20.1. Автомати
- •20.2. Стан
- •20.2.1. Ім'я стану
- •20.2.2. Список внутрішніх дій
- •20.2.3. Початковий стан
- •20.2.4. Кінцевий стан
- •20.3. Перехід
- •20.3.2. Сторожова умова
- •20.3.3.Вираз дії
- •15.4. Складений стан і підстан
- •20.4.1. Послідовні підстани
- •20.4.2. Паралельні підстани
- •15.5. Історичний стан
- •20.6. Складні переходи
- •15.6.1. Переходи між паралельними станами
- •20.6.2. Переходи між складеними станами
- •20.6.3. Синхронізуючі стани
- •20.7. Рекомендації з побудови діаграм станів
- •21.1. Стан дії
- •21.2. Переходи
- •21.5. Рекомендації до побудови діаграм діяльності
- •22.1.1. Лінія життя об'єкта
- •22.1.2. Фокус керування
- •22.2. Повідомлення
- •22.2.1. Розгалуження потоку керування
- •22.2.2. Стереотипи повідомлень
- •22.2.3. Тимчасові обмеження на діаграмах послідовності
- •22.2.4. Коментарі або примітки
- •22.3. Приклад побудови діаграми послідовності
- •22.4. Рекомендації з побудови діаграм послідовності
- •23.1. Кооперація
- •23.2.1. Мультиоб'єкт
- •23.2.2. Активний об'єкт
- •23.2.3. Складений об'єкт
- •23.3. Зв'язки
- •23.3.1. Стереотипи зв'язків
- •23.4. Повідомлення
- •23.4.1. Формат запису повідомлень
- •23.5. Приклад побудови діаграми кооперації
- •23.6. Рекомендації з побудови діаграм кооперації
- •24.1. Компоненти
- •24.1.1. Ім'я компоненту
- •24.1.2. Види компонент
- •24.2. Інтерфейси
- •24.3. Залежності
- •24.4. Рекомендації з побудови діаграми компонент
- •25.1. Вузол
- •25.2. З'єднання
- •25.3. Рекомендації з побудови діаграми розгортання
- •26.1. Загальна характеристика case-засобу Rational Rose
- •26.2. Особливості робочого інтерфейсу Rational Rose
- •26.1.1. Головне меню програми
- •26.1.2. Стандартна панель інструментів
- •26.1.3. Вікно браузера
- •26.1.4. Спеціальна панель інструментів
- •26.1.5. Вікно діаграми
- •26.1.6. Вікно документації
- •26.1.7. Вікно журналу
- •26.3. Початок роботи над проектом у середовищі Rational Rose
- •26.4. Розроблення діаграми варіантів використання в середовищі Rational Rose
- •26.5. Розроблення діаграми класів у середовищі Rational Rose
- •26.6. Розроблення діаграми станів у середовищі Rational Rose
- •26.7. Розроблення діаграми послідовності в середовищі Rational Rose
- •26.8. Розроблення діаграми кооперації в середовищі Rational Rose
- •26.9. Розроблення діаграми компонентів у середовищі Rational Rose
- •26.10. Розроблення діаграми розгортання в середовищі Rational Rose
15.1.3. Поведінка
Що таке поведінка. Об'єкти не існують ізольовано, а піддаються впливу або самі впливають на інші об'єкти.
Поведінка - це те, як об'єкт діє й реагує; поведінка виражається в термінах стану об'єкта й передачі повідомлень.
Іншими словами, поведінка об'єкта - це його спостережувана й перевірена ззовні дія.
Операцією називається певний вплив одного об'єкта на іншій з метою викликати відповідну реакцію. Наприклад, клієнт може активізувати операції append і pop для того, щоб керувати об'єктом-чергою (додати або вилучити елемент). Існує також операція length, що дозволяє визначити розмір черги, але не може змінити це значення. У чисто об’єктно-орієнтованій мові, такій як Smalltalk, прийнято говорити про передачу повідомлень між об'єктами. У мовах типу C++, в яких чіткіше відчувається процедурне минуле, ми говоримо, що один об'єкт викликає функцію-член іншого. В основному поняття повідомлення збігається з поняттям операції над об'єктами, хоча механізм передачі різний. Для наших цілей ці два терміни можуть використовуватися як синоніми.
В об’єктно-орієнтованих мовах операції, що виконуються над даним об'єктом, називаються методами й входять у визначення класу об'єкта. В C++ вони називаються функціями-членами. Ми будемо використовувати ці терміни як синоніми.
Передача повідомлень - це одна частина рівняння, що задає поведінку. З нашого означення випливає, що стан об'єкта також впливає на його поведінку. Розглянемо торговельний автомат. Ми можемо зробити вибір, але поведінка автомата буде залежати від його стану. Якщо ми не опустили в нього достатню суму, швидше за все нічого не відбудеться. Якщо ж грошей досить, автомат видасть нам бажане (і тим самим змінить свій стан). Отже, поведінка об'єкта визначається виконуваними над ним операціями і його станом, причому деякі операції мають побічну дію: вони змінюють стан. Концепція побічної дії дозволяє уточнити наше визначення стану:
Стан об'єкта представляє сумарний результат його поведінки.
Найцікавіші ті об'єкти, стан яких не статичний: їхній стан змінюється й запитується операціями.
Приклади. Опишемо мовою C++ клас Queue (черга):
class Queue {
public:
Queue();
Queue(const Queue&);
virtual ~Queue();
virtual Queue& operator=(const Queue&);
virtual int operator==(const Queue&) const;
int operator!=(const Queue&) const;
virtual void clear();
virtual void append(const void*);
virtual void pop();
virtual void remove(int at);
virtual int length() const;
virtual int isEmpty() const;
virtual const void* front() const;
virtual int location(const void*);
protected:
...
};
У визначенні класу використовується звичайна для С ідіома посилання на дані невизначеного типу за допомогою void*, завдяки чому в чергу можна вставляти об'єкти різних класів. Ця техніка не безпечна - клієнт повинен розуміти, з яким (якого класу) об'єктом він має справу. Крім того, під час використання void* черга не "володіє" об'єктами, які до неї поміщені. Деструктор Queue() знищує чергу, але не її учасників. У наступному розділі ми розглянемо параметризовані типи, які допомагають справлятися з такими проблемами.
Оскільки визначення Queue задає клас, а не об'єкт, ми повинні оголосити екземпляри класу, з якими можуть працювати клієнти:
Queue a, b, c, d;
Ми можемо виконувати операції над об'єктами:
a.append(&deb);
a.append(&karen);
a.append (&denise);
b = a;
a.pop();
Тепер черга а містить двох співробітників (першим стоїть karen), а черга b - трьох (першим стоїть deb). Таким чином, черги мають певний стан, який впливає на їхню майбутню поведінку - наприклад, одну чергу можна безпечно просунути (pop) ще два рази, а іншу - три.
Операції. Операція - це послуга, яку клас може надати своїм клієнтам. На практиці типовий клієнт здійснює над об'єктами операції п'яти видів. Нижче наведені три найпоширеніші операції:
Модифікатор |
Операція, яка змінює стан об'єкту |
Селектор |
Операція, яка читає стан об'єкту, але не міняє його |
Ітератор |
Операція, що дозволяє організувати доступ до всіх частин об'єкта в строгій послідовності |
Оскільки логіка цих операцій досить різна, корисно вибрати такий стиль програмування, що враховує ці розходження в коді програми. У нашій специфікації класу Queue ми спочатку перелічили всі модифікатори (функції-члени без специфікаторів const - clear, append, pop, remove), а потім всі селектори (функції зі специфікаторами const - length, isEmpty, front і location).
Дві операції є універсальними; вони забезпечують інфраструктуру, необхідну для створення й знищення екземплярів класу:
Конструктор |
Операція створення об'єкта і/або його ініціалізації |
Деструктор |
Операція, що звільняє стан об'єкта і/або руйнує сам об'єкт |
У мові C++ конструктор і деструктор становлять частину опису класу, тоді як в Smalltalk і CLOS ці оператори визначені в протоколі метакласу (тобто в класі класу).
У чисто об’єктно-орієнтованих мовах операції можуть бути тільки методами, тому що процедури й функції поза класами в цій мові визначати не можна. В інших мовах допускається описувати операції як незалежні від об'єктів підпрограми. В C++ вони називаються функціями-нечленами; ми ж будемо тут називати їх вільними підпрограмами. Вільні підпрограми - це процедури й функції, які виконують роль операцій високого рівня над об'єктом або об'єктами одного або різних класів. Вільні процедури групуються відповідно до класів, для яких вони створюються. Це дає підставу називати такі пакети процедур утилітами класу. Наприклад, для визначеного вище класу Queue можна написати таку вільну процедуру:
void copyUntilFound(Queue& from, Queue& to, void* item)
{
while ((!from.isEmpty()) && (from.front() != item))
{
to.append(from.front());
from.pop();
}
}
Зміст полягає в тому, що вміст однієї черги переходить в іншу доти, поки на початку першої черги не виявиться заданий об'єкт. Це операція високого рівня; вона будується на операціях-примітивах класу Queue.
В C++ (і Smalltalk) прийнято збирати всі логічно зв'язані вільні підпрограми й повідомляти їх частиною деякого класу, що не має стану. Всі такі функції будуть статичними.
Таким чином, можна стверджувати, що всі методи - операції, але не всі операції - методи: деякі з них є вільними підпрограми. Ми схильні використовувати тільки методи, хоча, як буде показано у наступному розділі, іноді важко втриматися від спокуси, особливо якщо операція через свою природу виконується над кількома об'єктами різних класів і немає ніяких причин оголосити її операцією саме одного класу, а не іншого.
Ролі й відповідальності. Сукупність всіх методів і вільних процедур, що відносяться до конкретного об'єкта, утворює протокол цього об'єкта. Протокол, таким чином, визначає поведінку об'єкта, що охоплює всі його статичні й динамічні аспекти. У самих нетривіальних абстракціях корисно підрозділяти протокол на часткові аспекти поведінки, які ми будемо називати ролями. Роль - це маска, яку носить об'єкт; вона визначає контракт між абстракцією та її клієнтами.
Поєднуючи наші означення стану й поведінки об'єкта. Введемо поняття відповідальності. Відповідальність об'єкта має дві сторони - знання, які об'єкт підтримує, і дії, які об'єкт може виконувати. Вони виражають зміст його призначення й місце в системі. Відповідальність розуміється як сукупність всіх послуг і всіх контрактних зобов'язань об'єкта. В такий спосіб можна сказати, що стан і поведінка об'єкта визначають ролі, а ті, у свою чергу, необхідні для виконання відповідальності цієї абстракції.
Дійсно більшість цікавих об'єктів виконують у своєму житті різні ролі, наприклад:
Банківський рахунок може бути в хорошому або поганому стані (дві ролі), і від цієї ролі залежить, що відбудеться при спробі зняття з нього грошей.
Для фондового брокера пакет акцій - це товар, який можна купувати або продавати, а для юриста це знак володіння певними правами.
На протязі дня одні і та ж сама особа може відігравати роль матері, лікаря, садівника й кінокритика.
Ролі банківського рахунку є динамічними й взаємовиключними. Ролі пакету акцій трохи перекриваються, але кожна з них залежить від того, що клієнт з ними робить. У випадку особи ролі динамічно змінюються щохвилини.
Об'єкти як автомати. Наявність внутрішнього стану об'єктів означає, що порядок виконання операцій має істотне значення. Це наводить на думку представити об'єкт як маленьку незалежну машину. Дійсно, для деяких об'єктів такий часовий порядок настільки істотний, що найкращим способом їхнього формального опису буде кінцевий автомат.
Продовжуючи аналогію з машинами, можна сказати, що об'єкти можуть бути активними й пасивними. Активний об'єкт має свій потік керування, а пасивний - немає. Активний об'єкт у загальному випадку автономний, тобто він може проявляти свою поведінку без впливу зі сторони інших об'єктів. Пасивний об'єкт, навпаки, може змінювати свій стан тільки під впливом інших об'єктів. Таким чином, активні об'єкти системи - джерела керуючих впливів. Якщо система має кілька потоків керування, то й активних об'єктів може бути кілька. У послідовних системах звичайно в кожний момент часу існує тільки один активний об'єкт, наприклад, головне вікно, диспетчер який опрацьовує всі повідомлення. У такому випадку інші об'єкти пасивні: їхня поведінка проявляється, коли до них звертається активний об'єкт. В інших видах послідовних архітектур (системи опрацювання транзакцій) немає явного центру активності, і керування розподілене серед пасивних об'єктів системи.