Тема 1. Методології створення програмних продуктів
Якщо спробувати охарактеризувати сучасний рівень розвитку комп'ютерних і інформаційних технологій, то перше, на що варто звернути увагу - це зростаюча складність не тільки окремих фізичних і програмних компонентів, але й концепцій і ідей, що лежать в основі цих технологій. Здається, ще зовсім недавно професіональному програмісту було достатньо досконало володіти однією-двома мовами програмування, щоб розробляти серйозні програмні вироби. Вибір платформи і операційної системи, як правило, не були серйозною проблемою. А супровід програми, хоча і був зв'язаний з об'єктивними труднощами, міг бути реалізований простим додаванням або зміною коду програми.
Методологія процедурно-орієнтованого програмування
Поява перших електронних обчислювальних машин або комп'ютерів ознаменувало новий етап у розвитку техніки обчислень. Здавалося б, достатньо розробити послідовність елементарних дій, кожну з яких перетворити в зрозумілі комп 'ютеру інструкції, і будь-яка обчислювальна задача може бути вирішена. Ця ідея виявилась настільки життєздатною, що довший час домінувала над всім процесом розробки програм. З'явились спеціальні мови програмування, які дозволили перетворювати окремі обчислювальні операції у відповідний програмний код.
Основою даної методології розробки програм була процедурна або алгоритмічна організація структури програмного коду. Це було настільки природнім для вирішення обчислювальних задач, що ні у кого не викликала сумнівів у доцільності такого підходу. Вихідним поняттям цієї методології було поняття алгоритму, під яким, в загальному випадку, розуміється деякий припис виконати точно певну послідовність дій, направлених на досягнення заданої цілі або вирішення поставленої задачі.
З цієї точки зору вся історія математики тісно зв'язана з розробкою тих чи інших алгоритмів вирішення актуальних для своєї епохи задач. Більше того, само поняття алгоритму стало предметом відповідної теорії - теорії алгоритмів, яка займається вивченням загальних властивостей алгоритмів. З часом зміст цієї теорії став настільки абстрактним, що відповідні результати розуміли тільки спеціалісти. Як данина цій традиції деякий період часу мови програмування називались алгоритмічними, а перший графічний засіб документування програм отримав назву блок-схеми алгоритму. Відповідна система графічних позначень була зафіксована в ГОСТ 19.701-90, який регламентував використання умовних позначень в схемах алгоритмів, програм, даних і систем.
Проте, потреби практики не завжди вимагали встановлення обчислюваності конкретних функцій чи вирішуваності окремих задач. У мовах програмування виникло і закріпилось нове поняття процедури, яке конкретизувало загальне поняття алгоритму стосовно до вирішення задач на комп'ютерах. Так само, як і алгоритм, процедура представляє собою закінчену послідовність дій або операцій, направлених на вирішення окремої задачі. В мовах програмування появилась спеціальна синтаксична конструкція, яка отримала назву процедури.
З часом розробка великих програм перетворилась в серйозну проблему і вимагала їх поділу на більш дрібні фрагменти. Основою для такого поділу як раз і стала процедурна декомпозиція, при якій окремі частини програми або модулі представляли собою сукупність процедур для вирішення деякої сукупності задач. Головна особливість процедурного програмування полягає в тому, що програма завжди має початок в часі або початкову процедуру (початковий блок) і закінчення (кінцевий блок). При цьому вся програма може бути представлена візуально в виді направленої послідовності графічних примітивів або блоків.
Важливою властивістю таких програм є необхідність завершення всіх дій попередньої процедури для початку дій наступної процедури. Зміна порядку виконання цих дій навіть в межах однієї процедури вимагало включення в мови програмування спеціальних умовних операторів типу if-then-else і Goto для реалізації розгалуження обчислювального процесу в залежності від проміжних результатів вирішення задачі.
Розглянуті ідеї сприяли становленню деякої системи поглядів на процес розробки програм і написання програмних кодів, яка отримала назву методології структурного програмування. Основою даної методології є процедурна декомпозиція програмної системи і організація окремих модулів у виді сукупності виконуваних процедур. В межах даної методології отримав розвиток низхідне проектування програм або програмування «зверху-вниз». Період найбільшої популярності ідей структурного програмування приходиться на кінець 70-тих - початок 80-тих років.
Як допоміжний засіб структуризації програмного коду було рекомендовано використання відступів на початку кожної стрічки, які повинні виділяти вкладені цикли і умовні оператори. Все це покликано сприяти розумінню або читабельності самої програми. Дане правило з часом було реалізовано в сучасних інструментах розробки програм.
У цей період основним показником складності розробки програм вважали її розмір. Зовсім серйозно обговорювались такі оцінки складності програм, як кількість стрічок програмного коду. Правда, при цьому робились деякі припущення відносно синтаксису самих стрічок, які повинні були задовольняти певні правила. Загальна трудомісткість розробки програм оцінювалась спеціальною одиницею виміру - «людино-місяць» або «людино- рік». А професіоналізм програміста напряму зв'язувався з кількістю стрічок програмного коду, який він міг написати і налагодити на протязі деякого часу.
Методологія об'єктно-орієнтованого програмування
З часом ситуація стала суттєво мінятися. Виявилось, що трудомісткість розробки програмних виробів на початкових етапах програмування оцінювалась значно нижче реально затрачених зусиль, що служило причиною додаткових витрат і затягування кінцевих термінів готовності програм. У процесі розробки програм змінювались функціональні вимоги замовника, що ще більше віддаляло момент закінчення роботи програмістів. Збільшення розмірів програм приводило до необхідності залучення великої кількості програмістів, що, у свою чергу, вимагало додаткових ресурсів для організації їх узгодженої роботи.
Але не менш важливими виявились якісні зміни, зв'язані зі зміщенням акценту використання комп 'ютерів. Якщо в епоху «великих машин» основними споживачами програмного забезпечення були великі підприємства, компанії і заклади, то пізніше з'явились персональні комп'ютери і стали повсякденним атрибутом дрібного і середнього бізнесу. Обчислювальні і розрахунково- алгоритмічні задачі в цій галузі традиційно займали другорядне місце, а на перший план виступили задачі обробки і маніпулювання даними.
Стало очевидним, що традиційні методи процедурного програмування не здатні справитися ні з зростаючою складністю програм і їх розробки, ні з необхідністю підвищення їх надійності. У другій половині 80-тих років виникла потреба в новій методології програмування, яка була б здатна вирішити весь цей комплекс проблем. Такою методологією стало об'єктно-орієнтоване програмування (ООП).
Фундаментальними поняттями ООП є поняття класу і об'єкта. При цьому під класом розуміють деяку абстракцію сукупності об'єктів, які мають спільний набір властивостей і однакову поведінку. Кожен об'єкт у цьому випадку розглядається як екземпляр відповідного класу. Об'єкти, які не мають повністю однакових властивостей або не володіють однаковою поведінкою, за визначенням, не можуть бути віднесені до одного класу.
Важливою особливістю класів є можливість їх організації в виді деякої ієрархічної структури, яка за зовнішнім видом нагадує схему класифікації понять формальної логіки. У зв'язку з цим варто зауважити, що кожне поняття в логіці має деякий об'єм і зміст. При цьому під об'ємом поняття розуміють всі інші можливі поняття, для яких вихідне поняття може служити визначальною категорією або головною частиною. Зміст поняття складає сукупність всіх його ознак або атрибутів, які відрізняють дане поняття від всіх інших. У формальній логіці має місце закон зворотнього відношення: якщо зміст поняття А міститься в змісті поняття В, то об'єм поняття В міститься в об'ємі поняття А.
Ієрархія понять будується наступним чином. Як найбільш загальне поняття або категорія береться поняття, що має найбільший об'єм і, відповідно, найменший зміст. Це самий високий рівень абстракції для даної ієрархії. Потім дане загальне поняття деяким чином конкретизується, тим самим зменшується його об'єм і збільшується зміст. З'являється менш загальне поняття, яке на схемі ієрархії буде розміщене на рівень нижче вихідного поняття. Цей процес конкретизації понять може бути продовжений до тих пір, поки на самому нижньому рівні не буде отримане поняття, подальша конкретизація якого в даному контексті або неможлива, або недоцільна.
Прикладами найбільш загальних понять можуть служити такі абстрактні категорії, як система, структура, інтелект, інформація, сутність, зв'язок, стан, подія і багато інших. У процесі вивчення цих категорій з'являються нові особливості їх змісту і об'єму. Саме через ці причини завжди важко дати їм точне визначення.
Основними принципами ООП є успадкування, інкапсуляція і поліморфізм. Принцип, у відповідності з яким знання про більш загальну категорію дозволяється застосовувати для більш вузької категорії, називається успадкуванням. Успадкування тісно зв'язане з ієрархією класів, яка визначає, які класи потрібно вважати найбільш абстрактними і загальними у відношенні до інших класів. При цьому, якщо деякий більш загальний або батьківський клас (предок) має фіксований набір властивостей і поведінки, то похідний від нього клас (нащадок) повинен містити цей же набір властивостей і поведінки, а також додаткові, які будуть характеризувати унікальність отриманого таким чином класу. У цьому випадку говорять, що похідний клас успадковує властивості і поведінку батьківського класу.
Інформація про відношеннями класів у описовому вигляді має один суттєвий недолік, а саме відсутності наочності. Традиційно для зображення понять в формальній логіці використовувались кола або прямокутники. Тоді ієрархія породження класів може бути представлена в виді вкладених прямокутників, кожен із яких відповідає окремому класу.
Поява об'єктно-орієнтованих мов програмування було зв'язана з необхідністю реалізації концепції класів і об'єктів на синтаксичному рівні. З точки зору ООП клас є подальшим розширенням структури (structure) або запису (record). Включення в відомі мови програмування С і Pascal класів і деяких інших можливостей привело до появи відповідно C++ і Object Pascal, які на сьогодні є найбільш розповсюдженими мовами розробки програм. Розповсюдженню C++ і Object Pascal сприяла та обставина, що мова C++ була вибрана як базова для програмного інструменту MS Visual C++, а мова Object Pascal - для популярного засобу швидкої розробки програм Borland Delphi.
За короткий період часу обидва інструменти перетворились в потужні системи розробки програм з відповідними бібліотеками стандартних класів, які містять сотні різних властивостей і методів. Стосовно до середовища MS Visual C++ така бібліотека має назву - MFC (Microsoft Foundation Classes). При цьому похідні класи успадковують властивості і методи батьківських класів.
Процес розробки програм в середовищі Borland Delphi також тісно зв'язаний з використанням бібліотеки стандартних класів - VCL (Visual Component Library) або бібліотеки візуальних компонентів. Ця бібліотека також побудована за ієрархічним принципом, у відповідності з яким компоненти нижчих рівнів успадковують властивості і методи вищих компонентів.
Для однієї й тої ж загальної концепції ієрархії класів використовуються зовсім різні графічні засоби. У першому випадку - вкладені прямокутники, у другому - зв'язні прямокутники. На справді різних способів зображення класів запропоновано набагато більше. Проте вже зараз важливо усвідомити, що подібну ситуацію потрібно уніфікувати, тобто використовувати для цієї цілі деяку єдину систему позначень.
Наступний принцип ООП - інкапсуляція. Цей термін характеризує приховування окремих деталей внутрішньої будови класів від зовнішніх по відношенню до неї об'єктів або користувачів. Дійсно, суб'єкту або клієнту, який взаємодіє з класом, немає необхідності знати, яким чином реалізовано той чи інший метод класу, послугами якого він вирішив скористатися. Конкретна реалізація властивих класів властивостей і методів, які визначають поведінку цього класу, є власною справою даного класу. Більше того, окремі властивості і методи класу взагалі можуть бути невидимі за межами цього класу, що є базовою ідеєю введення різних категорій видимості для компонентів класу.
Інкапсуляція веде своє походження від поділу модулів в деяких мовах програмування на дві частини або секції: інтерфейс і реалізацію. При цьому в інтерфейсній секції модуля описуються всі оголошення функцій і процедур, а можливо й типів даних, які доступні за межами даного модуля. Іншими словами, вказані процедури і функції є способами надання послуг зовнішнім клієнтам. У другій секції модуля, яка називається реалізацією, міститься програмний код, який визначає конкретні способи реалізацій оголошених в інтерфейсній частині процедур і функцій.
Принцип поділу модуля на інтерфейс і реалізацію зображає суть представлень про навколишній світ. В інтерфейсній частині вказується вся інформація, яка необхідна для взаємодії з будь-якими іншими об'єктами. Реалізація приховує або маскує від інших об'єктів всі деталі, які не мають відношення до процесу взаємодії об'єктів.
Третім принципом ООП є поліморфізм. Під поліморфізмом розуміють властивість деяких об'єктів приймати різні зовнішні форми в залежності від обставин. Стосовно до ООП поліморфізм означає, що дії, які виконуються однойменними методами, можуть відрізнятися в залежності від того, до якого з класів відноситься цей чи інший метод.
Поліморфізм об'єктно-орієнтованих мов зв'язаний з перевантаженням функцій, але не тотожній з ним. Важливо мати на увазі, що імена методів і властивостей тісно зв'язані з класами, в яких вони описані. Ця обставини забезпечує певну надійність роботи програми, оскільки виключає випадкове застосування методу для вирішення невластивої йому задачі.
Широке розповсюдження методології ООП виявило вплив на процес розробки програм. Зокрема, процедурно-орієнтована декомпозиція програм уступила місце об'єктно-орієнтованій декомпозиції, при якій окремими структурними одиницями програми стали не процедури і функції, а класи і об'єкти з відповідними властивостями і методами. Як наслідок, програма перестала бути послідовністю визначених на етапі кодування дій, а стала керована подіями. Остання обставина стала домінуючою при розробці широкого кола сучасних програм. У цьому випадку кожна програма представляє собою нескінченний цикл очікування деяких наперед визначених подій. Ініціаторами подій можуть бути інші програми або користувачі. При настанні окремої події, наприклад, натискування клавіші на клавіатурі або клацання кнопки мишки, програма виходить із стану очікування і реагує на цю подію адекватним чином. Реакція програми при цьому також зв'язується з наступними подіями.
Найбільш суттєвою обставиною в розвитку методології ООП явилась усвідомлення того факту, що процес написання програмного коду може бути відділена від процесу проектування структури програми. Дійсно, до того як почати програмування класів, їх властивостей і методів, необхідно визначити, чим ж є самі ці класи. Більше того, потрібно дати відповіді на такі питання, як: скільки і які класи потрібно визначити для вирішення поставленої задачі, які властивості і методи необхідні для надання класам потрібної поведінки, а також встановити взаємозв'язки між класами.
Ця сукупність задач не стільки зв'язана з написанням коду, скільки з загальним аналізом вимог до майбутньої програми, а також з аналізом конкретної предметної області, для якої розробляється програма. Всі ці обставини привели до появи спеціальної методології, яка отримала назву методології об'єктно-орієнтованого аналізу і проектування (ООАП).
Методологія об'єктно-орієнтованого аналізу та проектування
Необхідність аналізу предметної області до початку написання програми була усвідомлена давно при розробці масштабних проектів. Процес розробки баз даних суттєво відрізняється від написання програмного коду для вирішення обчислювальної задачі. Головна відмінність полягає в тому, що при проектуванні бази даних виникає необхідність в попередній розробці концептуальної схеми, яка зображає загальні взаємозв'язки предметної області і особливості організації відповідної інформації. При цьому під предметною областю прийнято розуміти ту частину реального світу, яка має суттєве значення або безпосереднє відношення до процесу функціонування програми. Іншими словами, предметна область включає в себе тільки ті об'єкти і взаємозв'язки між ними, які необхідні для опису вимог і умов вирішення деякої задачі.
Виділення вихідних або базових компонентів предметної області, необхідних для вирішення той чи іншої задачі, представляє, в загальному випадку, нетривіальну проблему. Складність даної проблеми проявляється в неформальному характері процедур або правил, які можна застосовувати для цієї цілі. Більше того, така робота повинна виконуватися разом з спеціалістами або експертами, які добре знають предметну область.
Для виділення або ідентифікації компонентів предметної області було запропоновано декілька способів і правил. Сам цей процес отримав назву концептуалізації предметної області. При цьому під компонентою розуміють деяку абстрактну одиницю, яка має функціональністю, тобто може виконувати певні дії, які зв'язані з вирішенням поставлених задач. На попередньому етапі концептуалізації рекомендується використовувати так звані CRC-картки (Component, Responsibility, Collaborator - компонента, обов'язок, співробітники). Для кожної виділеної компоненти предметної області розробляється власна CRC-картка.
Поява методології ООАП вимагала, з одного боку, розробники різних засобів концептуалізації предметної області, а з іншого - відповідних спеціалістів, які використовували б цією методологією. На даному етапі з'являється відносно новий тип спеціаліста, який отримав назву аналітика або архітектора. Поряд зі спеціалістами з предметної області аналітик бере участь в побудові концептуальної схеми майбутньої програми, яка потім перетворюється програмістами в код. При цьому окремі компоненти вибираються таким чином, щоб при наступній розробці їх було зручно представити в формі класів і об'єктів. У цьому випадку велике значення набуває і сама мова представлення інформації про концептуальну схему предметної області.
Розділення процесу розробки складних програмних виробів на окремі етапи сприяли становленню концепції життєвого циклу програми. Під життєвим циклом (ЖЦ) програми розуміють сукупність взаємозв'язаних і протікаючих в часі етапів, починаючи від розробки вимог до неї і закінчуючи повною відмовою від її використання. Стандарт ISO/IEC 12207, хоча й описує загальну структуру ЖЦ програми, не конкретизує деталі виконання тих чи інших етапів. Згідно прийнятим поглядам ЖЦ програми складається з наступних етапів:
- Аналіз предметної області і формулювання вимог до програми;
- Проектування структури програми;
- Реалізації програми в кодах (власне програмування);
- Впровадження програми;
- Супровід програми;
- Відмова від використання програми.
На етапі аналізу предметної області і .формулювання вимог здійснюється визначення функцій, які повинна виконувати розроблювана програма, а також концептуалізація предметної області. Цю роботу виконують аналітики разом з спеціалістами предметної області. Результатом даного етапу повинна бути деяка концептуальна схема, яка містить опис основних компонентів і тих функцій, які вони повинні виконувати.
Етап проектування структури програми полягає в розробці детальної схеми майбутньої програми, на якій вказуються класи, їх властивості і методи, а також різні взаємозв'язки між ними. Як правило, на цьому етапі можуть брати участь в роботі аналітики, архітектори і окремі кваліфіковані програмісти. Результатом даного етапу повинна стати деталізована схема програми, на якій вказуються всі класи і взаємозв'язки між ними в процесі функціонування програми. Згідно методології ООАП, саме дана схема повинна служити вихідною інформацією для написання програмного коду.
Етап програмування не потребує уточнень, оскільки є найбільш традиційним для програмістів. Поява інструментів швидкої розробки програм (Rapid Application Development, RAD) дозволила суттєво скоротити час, і затрати на виконання цього етапу. Результатом даного етапу є програмний виріб, який має потрібну функціональність і здатний вирішувати потрібні задачі в конкретній предметній області.
Етапи впровадження і супроводу програми зв'язані з необхідністю налаштування і конфігурації середовища програми, а також з виправленням помилок, які виникли в процесі її використання. Іноді як окремий етап виділяють тестування програми, під яким розуміють перевірку працездатності програми на деякій сукупності вихідних даних або при деяких спеціальних режимах експлуатації. Результатом цих етапів є підвищення надійності програмного виробу, яке виключає виникнення критичних ситуацій або нанесення страт компанії, яка використовує дану програму.
Методологія ООАП тісно зв'язана з концепцією автоматизованої розробки програмного забезпечення (Computer Aided Software Engineering, CASE). Поява перших CASE-засобів була зустрінута з певною настороженістю. З часом появились як позитивні відгуки про їх застосування, так і критичні оцінки їх можливостей. Причин для таких суперечливих думок було декілька. Перша з них полягає в тому, що ранні CASE-засоби були простими надбудовами над деякою системою управління базами даних. Хоча візуалізація процесу розробки концептуальної схеми БД має немаловажне значення, вона не вирішує проблем розробки програм інших типів.
Друга причина має більш складну природу, оскільки зв'язана з графічною нотацією, яка реалізована в тому чи іншому CASE-засобі. Якщо мови програмування мають строгий синтаксис, то спроби запропонувати потрібний синтаксис для візуального представлення концептуальних схем БД були сприйняті далеко неоднозначно. Появилось декілька підходів. На цьому фоні поява уніфікованої мови моделювання (Unified Modeling Language, UML), яка орієнтована на вирішення задач перших двох етапів ЖЦ програм, було сприйнято з більшим оптимізмом програмістами.
Останнє, на що потрібно звернути увагу, це усвідомлення необхідності побудови попередньої моделі програмної системи, яку, згідно до сучасних концепцій ООАП, потрібно вважати результатом перших етапів ЖЦ програми. Оскільки мова UML навіть в своїй назві має відношення до моделювання, потрібно додатково зупинитися на цілому ряді достатньо важливих питань. Моделювання традиційно не розглядається в ООАП, але має саме беззпосереднє відношення до процесу побудови моделей. Мова йде про методологію системного аналізу і системного моделювання.
Методологія візуального системного аналізу та моделювання
Системний аналіз як науковий напрямок має більш давню історію, ніж ООП і ООАП, і власний предмет дослідження. Центральним поняттям системного аналізу є поняття системи, під якою розуміється сукупність об'єктів, компонентів або елементів довільної природи, які утворюють деяку цілісність. Визначальною передумовою виділення деякої сукупності як системи є виникнення в неї нових властивостей, які не мають елементи, що її складають.
Важливими характеристиками будь-якої системи є її структура і процес функціонування. Під структурою системи розуміють стійку в часі сукупність взаємозв'язків між її елементами або компонентами. Саме структура зв'язує в єдине всі елементи і перешкоджає розпаду системи на окремі компоненти. Структура системи може зображати самі різні взаємозв'язки, в тому числі і вкладеність елементів однієї системи в іншу. У цьому випадку прийнято називати більш дрібну або вкладену систему підсистемою, а більш крупну - метасистемою.
Процес функціонування системи тісно зв'язаний зі зміною її властивостей або поведінкою в часі. При цьому важливою характеристикою системи є її стан, під яким розуміють сукупність властивостей або ознак, які в кожен момент часу зображають найбільш суттєві особливості поведінки системи.
Процес функціонування системи зображає поведінку системи в часі і може бути представлений як послідовна зміна її станів. Якщо система змінює один свій стан на інший, то говорять, що система переходить з одного стану в інший. Сукупність ознак або умов зміни станів системи в цьому випадку називається переходом. Для системи з дискретними станами процес функціонування може бути представлений у виді послідовності станів з відповідними переходами.
Методологія системного аналізу служить концептуальною основою системно-орієнтованої декомпозиції предметної області. В цьому випадку вихідними компонентами концептуалізації є системи і взаємозв'язки між ними. При цьому поняття системи є більш загальним, ніж поняття класів і об'єктів в ООАП. Результатом системного аналізу є побудова деякої моделі системи або предметної області.
Стосовно до програмних систем інтерес викликає тільки ті поняття моделі, які використовуються в системному аналізі. А саме, під моделлю розуміють деяке представлення про систему, яка зображає найбільш суттєві закономірності її структури і процесу функціонування і зафіксовані на деякій мові або в іншій формі.
Найбільш загальною моделлю системи є та звана модель «чорного ящика». У цьому випадку система представляється у виді прямокутника, внутрішня будова якого прихована від аналітика або невідома. Проте система не є повністю ізольованою від зовнішнього середовища, оскільки остання інформаційно або матеріально впливає на систему. Такий вплив отримав назву вхідної дії. У свою чергу, система також впливає на середовище або інші системи, вихідна дія.
Цінність моделей, подібних моделі «чорного ящика», досить умовна. В межах системного аналізу розроблені певні методологічні засоби, які дозволяють виконати подальшу конкретизацію загальної моделі системи.
Процес розробки адекватних моделей і їх наступного конструктивного застосування потребує не тільки знань загальної методології системного аналізу, але й наявності відповідних наочних засобів або мов для фіксації результатів моделювання і їх документування. Очевидно, що природна мова не зовсім підходить для цієї цілі, оскільки вона неоднозначна і невизначена. Для побудови моделей були розроблені достатньо серйозні теоретичні методи, які базуються на розвитку математичних і логічних засобів моделювання, а також запропоновано різні формальні і графічні нотації, які зображають специфіку вирішуваних задач. Важливо представляти, що уніфікація будь-якої мови моделювання тісно зв'язана з методологією системного моделювання.