69071

Компонентна ідеологія

Лекция

Информатика, кибернетика и программирование

Слід зазначити що однією з багатьох важливих переваг компонентноорієнтованого програмування КОП є можливість створення кросплатформного програмного забезпечення. В індустрії програмування технологічні нововведення приходять хвилями кожна з яких проявляється як мода на нові засоби...

Украинкский

2014-09-29

210.54 KB

7 чел.

Лекція №2

Компонентна ідеологія

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

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

Десятиліття

Технологія програмування

Ключове нововведення

Мови програмування

1940-ві

машинні коди

програмовані машини

1950-ті

асемблерні мови

мнемонічні команди

асемблер

1960-ті

мови високого рівня

вирази і незалежність від машини 

Fortran, Кобол тощо

1970-ті

структурне програмування

структурні типи та керуючі конструкції 

Алгол, C, Pascal

1980-ті

модульне програмування

відокремлення інтерфейсу від реалізації

Modula-2, Ada

1990-ті

обєктно-орієнтоване програмування

поліморфізм

C++, Python, PHP тощо

2000-ні

компонентно-орієнтоване програмування

динамічна та безпечна композиція

C#, Java

Таблиця 2.1. Еволюція імперативного програмування

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

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

Мови високого рівня ввели незалежність від машини (апаратної платформи) і вирази (можливість використання потужних синтаксичних конструкцій), що помітно на прикладі мови Fortran, назва якої є скороченням від «formula translation». Основна відмінна риса мови третього покоління: орієнтування на алгоритм (алгоритмічні мови).

У запропонованій в 1970-х роках голландським науковцем Дейкстрою (Edsger Wybe Dijkstra), а потім розробленій та доповненій Ніклаусом Віртом методологіїї структурного програмування зроблено два кроки: уведені типи даних та запропонувано розглядати програму як структуру, створену на основі трьох основних конструкцій – послідовне виконання (передбачає лінійне виконання операторів програми), розгалуження (if, if...else, switch або case) та цикл (структури while, do/while, for), кожна з яких являє собою блок із одним входом та одним або кількома виходами. Блоки з’єднуються за двома правилами: пакетування (вихід одного блоку з’єднується із входом наступного) та вкладення (будь-який блок може бути замінений на керуючу структуру вибору або повторення).

С, Pascal, FORTRAN та інші схожі з ними мови програмування відносяться до категорії процедурних мов. Кожен оператор такої мови є вказівкою комп’ютеру виконати певну дію. Програміст створює перелік інструкцій, а комп’ютер виконує дії, що відповідають цим інструкціям.

Як би ефективно не використовувався структурний підхід, він не дозволяє в достатній мірі спростити великі складні проекти. Коли розмір програми великий, список команд стає доволі громіздким. Небагато програмістів здатні утримувати в голові більш ніж 500 рядків програмного коду. Крім того, у процедурній програмі існує ще й проблема неконтрольованого доступу до даних. В процедурній програмі, існує два типи даних. Локальні дані знаходяться всередині функції та призначені для використання виключно цією функцією. Якщо існує необхідність спільного використання одних і тих самих даних кількома функціями, то дані повинні бути оголошені як глобальні. А це, як правило, стосується тих даних програми, які є найбільш важливими. Великі програми зазвичай містять велику кількість функцій та глобальних змінних. Проблема процедурного підходу полягає в тому, що число можливих зв’язків між глобальними змінними та функціями може бути дуже великим.

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

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

Модульне програмування, прикладами якого є Modula-2 та Ada, ввели формальність інтерфейсу для кожного програмного компонента. Основна ідея полягає в реалізації обчислювальних процесів у вигляді окремих програмних одиниць – модулів – та звертанні до цих модулів в інших програмах з передачею необхідних для обчислень даних. Модульне програмування дозволяє зменшити обсяг вихідних текстів програм, зробити їх прозорішими, прискорити написання та тестування програм, зменшити витрати на супровід (експлуатацію) програм.

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

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

Функції об’єкта, що в С++ називаються методами (чи функціями-членами), зазвичай призначені для доступу до даних об’єкта. Прямий доступ до даних неможливий. Дані скриті від зовнішнього впливу, що захищає їх від випадкового змінення. Говорять, що дані та методи інкапсульовані.

Якщо необхідно змінити дані об’єкта, то, очевидно, ця дія також буде покладена на методи об’єкта. Ніякі інші “сторонні” функції не можуть змінити дані. Такий підхід полегшує написання, налагодження та використання програми.

Та, хоча кожен об’єкт є унікальним, він підпадає під певну категорію, що називається класом. І коли ми говоримо про об’єкти, ми говоримо, що вони є екземплярами класів. Що це означає? Клас є свого роду формою \зразком\, що визначає, які дані та функції будуть включені в об’єкт цього класу. Тобто, клас можна представити як деякий шаблон, що визначає формат об’єкта. Клас є описом сукупності схожих між собою об’єктів, а об’єкти є втіленням властивостей, притаманних класу, до якого вони належать.

Поняття класу приводить нас до поняття успадкування. У повсякденному житті ми часто стикаємося з розбиттям класів на підкласи: наприклад, клас “міський транспорт” поділяється на підкласи трамваї, тролейбуси, автобуси, метро, таксі тощо. Принцип, покладений в основу такого ділення, полягає в тому, що кожен підклас володіє властивостями, притаманними тому класу, з якого виділений даний підклас. Крім тих властивостей, які є загальними для класу та підкласу, підклас може володіти й власними властивостями.

У програмуванні клас також може породити безліч підкласів. Ця можливість називається наслідуванням. Успадкування – це можливість, яка дозволяє одному класу успадковувати властивості іншого. В С++ клас, що породжує всі інші класи, який успадковується, називається базовим класом. Класи, які успадковують базовий клас, називаються похідними. Базовий клас містить елементи, спільні для групи похідних класів. А похідні класи наслідують всі його властивості, одночасно володіючи власними властивостями. Тобто кожен похідний клас представляє собою спеціалізовану версію базового класу. Роль успадкування в ООП – скоротити розмір коду та спростити зв’язки між елементами програми.

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

Використання операцій та функцій різним чином в залежності від того, з якими типами даних вони працюють, називається поліморфізмом. Коли існуюча операція, наприклад = чи +, наділяється можливістю здійснювати дії над операндами нового користувацького типу, говорять, що така операція є перевантаженою. Перевантаженими можуть бути будь-які унарні чи бінарні операції. Перевантаження являє собою частковий випадок поліморфізму і є важливим інструментом ООП.

Але успадкування реалізації на практиці вимагає, щоб вихідний код успадкованого об'єкта був відкритий, тобто, приховування інформації відкидається, і реалізація повинна розглядатися як інтерфейс («успадкування руйнує інкапсуляцію»). Це так звана проблема «семантичної крихкості базового класу»: якщо в новій версії змінюється реалізація базового класу, то може перестати працювати підклас, який успадковується від цього базового класу.

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

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

Проблема “крихких базових класів” (fragile base class problem) – фундаментальна проблема об'єктно-орієнтованого програмування. Вона полягає в тому, що найменші правки в деталях реалізації базового класу можуть привнести помилку в похідні класи. У гіршому випадку це призводить до того, що будь-яка успішна модифікація базового класу вимагає попереднього вивчення всього дерева спадкування, і найчастіше неможлива (без створення помилок) навіть у цьому випадку.

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

Проблема може бути узагальнена і на системи, розроблені не на ООП мовах, що не використовують поняття «клас». Будь-яке повторне використання готового коду (без копіювання) як частини нового коду може спричинити за собою таку проблему.

У сучасних парадигмах програмування, розроблених під впливом ООП, використовуються поняття «зв'язки» та «зв'язність», і якість дизайну визначається керування зв'язками, що, зокрема, передбачає ослаблення зв'язків. Успадкування ж у розумінні ООП створює найсильніший з можливих зв'язків, і тому повинно використовуватися дуже обережно.

Компонентно-орієнтоване програмування (КОП, component-oriented programming) виникло як свого роду дисципліна, тобто як набір певних обмежень, що накладаються на механізм ООП, для підвищення надійності великих програмних комплексів, і як можливий метод боротьби з проблемою крихких базових класів. Згадайте, що структурне програмування теж виникло як деяка дисципліна використання структур управління, що виключає безконтрольні, неврегульовані переходи управління за допомогою оператора GOTO.

Хоча КОП почало бурхливо розвиватись у 90-ті, вперше практично реалізоване воно було ще у системі Оберон Вірта і Гуткнехта в кінці 80-х.

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

Динамічним зв'язуванням (dynamic linking) або пізнім з'єднанням (late binding) називається зв'язування, яке відбувається під час завантаження (load time) або виконання (run time) програми, а не під час створення виконуваного файлу. Динамічно завантажувані бібліотеки (dynamic-link library або DLL у ОС Windows та OS/2) або динамічно розподілювані об’єкти (dynamic shared object або DSO у Unix-подібних ОС) – це бібліотеки, призначені для динамічного зв'язування. Під час створення виконуваного файлу компонувальник лише фіксує те, що бібліотека відповідає потребам програми та імена або посилання (номера індексів) відповідають бібліотеці. Більшість робіт зв'язування виконується під час завантаження застосування (load time) або під час виконання (run time). Необхідна для цього програма-лінкувальник, яка називається динамічний компонувальник (dynamic linker) або завантажувач (linking loader), фактично є частиною операційної системи.

Вперше динамічна компоновка була розроблена в операційній системі Multics, запущеній у 1964 році, та у системі МТС (Michigan Terminal System), побудований в кінці 1960-х.

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

Можна сказати, що КОП – це таке ООП, яке підпорядковане вимогам безпеки "старого" структурного і модульного програмування приблизно в тому вигляді, в якому ці вимоги були реалізовані в класичній Модулі-2 (на відміну від мов типу Smalltalk, в яких ООП є основним механізмом, який застосовується без обмежень).

КОП можна описати приблизно такою формулою:

КОП = ООП +

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

+ Безпека (статичний контроль типів змінних і автоматичне керування пам'яттю) –

Наслідування/успадкування реалізації через кордони модулів.

Останнє означає, що в КОП заборонено успадкування від типів, реалізованих в інших модулях; успадковувати можна тільки абстрактним, чисто інтерфейсним типам (таким, що помічені атрибутом ABSTRACT в компонентному Паскалі).

Статична типізація – контроль типів здійснюється при компіляції (на відміну від динамічної типізації, за якої контроль типів здійснюється під час виконання).

Мови програмування

ООП мови

Модульні мови програмування

КОП мови

Динамічні ООП мови

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

Визначення 1. Компонент є виділеною структурною одиницею програмної системи, що володіє чітко визначеним інтерфейсом, який повністю описує її залежності від оточення [1].

Визначення 2. Компонент — це незалежний модуль програмного коду, призначений для повторного використання та розгортання [3].

Визначення 3. Компонент — це елемент конструкції з визначеним, зафіксованим у специфікації, інтерфейсом та явними залежностями від контексту. Компоненти можуть поширюватися незалежно один від одного та компонуватися третьою стороною.

1996 Workshop on Component-Oriented Programming in Linz [WCOP96]

Властивості компонентів та їх відмінності від класів ООП:

  1.  Компоненти – це істотно більші одиниці, ніж об'єкти (у тому сенсі, що об'єкт є конструкцію рівня мови програмування, а компонент – це «незалежний модуль програмного коду, призначений для повторного використання та розгортання»).
  2.  Компоненти можуть містити множинні класи.
  3.  Компоненти (у більшості випадків) незалежать від мови програмування. Зауважимо, що, автор і користувач компонента, взагалі кажучи, територіально розподілені і використовують різні мови. Цілком можливо, що вони не тільки пишуть програми, але і говорять на різних мовах. 

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

  1.  Застосування компонентного програмування покликане забезпечити більш просту, швидку і прямолінійну процедуру первинної інсталяції прикладного ПЗ, а також збільшити відсоток повторного використання коду, тобто посилити основні переваги ООП.
  2.  Компонент – це одиниця розгортання. Він може бути приєднаний до решти системи, коли вона вже деякий час працює, і повинен після цього виконувати всі свої функції, якщо ця система вже містить компоненти, від яких він залежить. Його можна вилучити з системи, після чого можуть перестати працювати ті компоненти, які від нього залежать. Він може бути вбудований в інші програмні продукти і розповсюджуватися разом з ними. В той самий час жодна з частин компонента не володіє цими властивостями.

Фундаментальна вимога до компонентного ПЗ полягає в тому, щоб компоненти могли розроблятися і поставлятися/продаватися незалежно один від одного, і, таким чином, могли комбінуватися споживачем.

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

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

  1.  Компонент має суворі вимоги до чіткості визначення інтерфейса. Абсолютно всі залежності компонента від його оточення повинні бути описані в рамках цього інтерфейсу.

Інтерфейс

Прихована реалізація

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

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

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

Специфікація інтерфейсу як контракту. Першим запропонував розглядати інтерфейс як контракт між викликаючим компонентом і компонентом, який викликається, автор мови Eiffel, Бертран Мейер (Meyer Bertrand) у 1989 році.

Примітка. Eiffel — об'єктно-орієнтована мова програмування, до основних рис якої належать:

  1.  Об'єктно-орієнтована структура програм, класи використовуються в якості базових одиниць декомпозиції.
  2.  Дизайн за контрактом, щільно інтегрований з іншими конструкціями мови.
  3.  Автоматичне керування пам'ятю, я правило, реалізується у вигляді автоматичного прибирання сміття.
  4.  Успадкування, включаючи множинне успадкування та механізми аби зробити успадкування безпечним.
  5.  Загальне програмування, з обмеженнями та без.
  6.  Одноманітна система типізації, з підтримкою семантики значень та посилань, всі типи, включно із базовими основані на класах.
  7.  Безпечна типізація (статична типізація).
  8.  Захист від викликів невизначених посилань.
  9.  «Агенти» (об'єкти, що містять обчислення, схоже на замикання та Лямбда числення).
  10.  Одноразові підпрограми (можуть виконуватись лише один раз під час роботи програми).
  11.  Ключові слова в стилі Алгол-подібних мов програмування та Pascal, але крапка з комою не є обов'язковою.
  12.  Нечутливість до регістру літер.

Контрактне програмування (design by contract (DbC), programming by contract, contract-based programming) — це метод проектування програмного забезпечення, який припускає, що проектувальник повинен визначити формальні, точні та верифіковані специфікації інтерфейсів для компонентів системи. При цьому, крім звичайного визначення абстрактних типів даних, також використовуються предумови, постумови та інваріанти. Ці специфікації називаються "контрактами" відповідно до концептуальної метафори умов і відповідальності в цивільно-правових договорах.

Історія. Термін запропонував Бертран Мейер у зв'язку з розробкою мови Eiffel. Контрактне програмування виросло з формальної верифікації, формальної специфікації та логіки Хоара. Контрактне програмування – це не лише проста метафора, яка вказує спосіб проектування. Умови, що полегшують застосування контрактного програмування:

  1.  наявність наслідування/спадкування та можливість динамічного зв'язування;
  2.  здатність обробляти виключення;
  3.  можливість автоматичного документування ПЗ.

Основна ідея контрактного програмування — це модель взаємодії елементів програмної системи, яка грунтується на ідеї взаємних зобов'язань та переваг. Як і в бізнесі, клієнт і постачальник діють у відповідності з певним контрактом. Контракт деякого методу чи функції може включати:

  1.  конкретні зобов'язання, які будь-який клієнтський модуль повинен виконати перед викликом методу – предумови, що надають перевагу постачальнику – він може не перевіряти виконання передумов;
  2.  конкретні властивості, які повинні бути присутні після виконання методу – постумови, які входять до зобов'язань постачальника;
  3.  зобов'язання по виконанню конкретних властивостей – інваріантів, які повинні виконуватися при отриманні постачальником повідомлення, а також при виході з методу.

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

В об'єктно-орієнтованому програмуванні контракт методу зазвичай включає наступну інформацію:

  1.  можливі типи вхідних даних та їх значення;
  2.  типи даних, що повертаються, та їх значення;
  3.  умови виникнення виключень, їх типи та значення;
  4.  присутність побічного ефекту методу;
  5.  предумови, які можуть бути ослаблені (але не посилені) у підкласах;
  6.  постумови, які можуть бути посилені (але не ослаблені) у підкласах;
  7.  інваріанти, які можуть бути посилені (але не ослаблені) у підкласах;
  8.  (іноді) гарантії продуктивності, наприклад, тимчасова складність або складність по пам'яті.

При використанні контрактів сам код не зобов'язаний перевіряти їх виконання. Зазвичай в таких випадках у коді роблять апаратний збій (fail hard), таким чином полегшуючи налагодження виконання контрактів. У багатьох мовах, таких як C, C++, Delphi, PHP, така поведінка реалізується оператором assert. У релізовому варіанті коду можна зберегти цю поведінку або прибрати перевірки для підвищення продуктивності.

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

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

При проектуванні компонентів їх інтерфейси повинні відповідати наступним вимогам (правилам):

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

Специфікація інтерфейсу може виконуватися засобами API (Application Programming Interface) мови програмування або на мові специфікації інтерфейсу (незалежній від мови програмування) – Interface Definition Language (IDL).

Мова опису інтерфейсів IDL (Interface Definition Language) – це мова специфікацій для опису інтерфейсів, синтаксично схожа на опис класів у мові C++. Реалізації:

CORBA IDL – мова опису інтерфейсів розподілених об'єктів, розроблений робочою групою OMG, створена у рамках узагальненої архітектури CORBA.

MIDL (Microsoft Interface Definition Language) – мова опису інтерфейсів для платформи Win32 визначає інтерфейс між клієнтом і сервером. Запропонована від Microsoft технологія використовує реєстр Windows та використовується для створення файлів і файлів конфігурацій застосувань, необхідних для інтерфейсів віддаленого виклику процедур (RPC) та COM/DCOM інтерфейсів.

COM IDL – мова опису інтерфейсів між модулями COM.

Сучасні мови програмування мають розширення, спеціально призначені для специфікації поведінки. Наприклад, мова JML (Java Modeling Language) – це мова специфікації для Java-програм, яка використовує передумови, постумови та інваріанти у стилі Hoare, що відповідають парадигмі контрактного прорамування. Характеристики записуються у вигляді коментарів-анотації Java у вихідних файлах, які можуть бути скомпільовані будь-яким компілятором Java.

Для розробки підтримуються різні інструменти перевірки, наприклад, перевірка припущень (assertion) виконання і розширені статичні засоби контролю (ESC/Java).

JML – це мова поведінкової специфікації інтерфейсів для модулів Java. JML містить семантику для формального опису поведінки модулів Java для запобігання двозначності щодо задумів/ідей розробників модулів. JML успадкувала ідеі Eiffel, мови специфікацій Larch та підходу Refinement Calculus для забезпечення формальної семантики з одночасною доступністю для будь-якого програміста Java. Існують різні інструменти, які використовують поведінкові специфікації JML. Оскільки специфікації можуть бути записані у вигляді анотацій у файлах Java-програми або зберігатися в окремих файлах специфікацій, Java модулі зі специфікаціями JML можуть компілюватися без змін з будь-яким компілятором Java.

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

1. Основоположний принцип цивільного та міжнародного праваPacta sunt servanda, що перекладається з латини як «контрактів/договорів необхідно дотримуватися».

2. Контракти містять, як мінімум, дві сторони, тобто, постачальника, який обіцяє надати певний товар (або послугу), і замовника, який обіцяє придбати товар відповідним чином.

3. Іноді контракти виходять від третьої сторони. Наприклад, багато професійні організації мають стандартизовані контракти для своєї діяльності.

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

  1.  Якщо наявні неоднозначності, кожна сторона може пред'явити своє трактування того, що вона й інші сторони зобов'язані робити. Це відразу веде до несумісних припущень, і потім – до конфлікту.
  2.  Якщо опущено щось важливе, можуть з’явитися неявні припущення. Якщо таке припущення залишається істинним деякий час, воно може перетворитися на неписаний закон, тобто, в обмеження контракту, яке мається на увазі. Але це обмеження є крихким, тому що інша сторона може перестати підтримувати зроблені припущення, якщо в майбутньому вона знайде причини поводитися іншим чином. Це може призвести до конфліктів або навіть анулювання контракту.
  3.  Якщо в контракті фіксуються незначні деталі, то на обидві сторони накладаються непотрібні обмеження. Прийде час, коли одна із сторін захоче змінити контракт, щоб умови стали більш гнучкими. Це може призвести до дорогих і, можливо, безуспішних спроб їх узгодити. Або, замість повторного узгодження, контрагент може просто порушити контракт. Стає можливим або анулювання контракту, або судова тяжба.

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

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

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

Як все це стосується інтерфейсів між компонентами? Сторони укладають контракт, який відповідає взаємодії компонентів через деякий інтерфейс. Погані контракти неясні, неповні і перевантажені.

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

Наведемо приклад наступної формальної специфікації:

PROCEDURE Sum (x, y: INTEGER; OUT z: INTEGER)

Передумова: (x >= 0) & (y >= 0)

Постумова: z = x + y

Це інтерфейс (контракт) між тим, хто реалізує процедуру, і тим, хто її викликає. Передумова, визначає, що вхідні параметри x і y повинні бути невід'ємними, постумова – що вихідний параметр z містить суму x і y. Розроблювач може припустити менш суворі передумови, наприклад, він може також дозволити негативні значення для x та y. Однак важко довести, що ці значення обробляються вірним чином. Аналогічно розробник може забезпечити більш суворі післяумови, тобто, він може надати більше, ніж від нього очікують.

А ось приклад вірної реалізації для наведеної специфікації:

PROCEDURE MySum (x, y: INTEGER; OUT z: INTEGER);

BEGIN

z: = ABS (x) + ABS (y)

END MySum;

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

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

Крім того, використання повної реалізації в якості специфікації ускладнює аналіз коду у випадку, якщо необхідно зрозуміти, як себе веде фрагмент програми.

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

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

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

На найпростішому рівні, кожному компоненту потрібно взаємодіяти з іншими компонентами виключно через їх інтерфейси; це різновид контракту, інакше кажучи, закон для програміста. Наприклад, прямий запис у пам'ять іншого компонента є грубим порушенням закону. У закритій системі, тобто, в ізольованому монолітному застосуванні, ця проблема вирішується легко. Але у відкритих компонентних системах взаємовплив компонентів – це принципово більш важливе питання. Якщо апаратна і програмна інфраструктура може повністю запобігти порушенню угод, надійність системи зросте, тому що можливості компонента що-небудь зруйнувати будуть обмежені. Існуючі засоби апаратного захисту і деякі сучасні мови програмування спроектовані так, щоб забезпечити безпеку такого роду.

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

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

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

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

Як вже зазначалося, інтерфейс компонента включає набір операцій, які можна викликати у будь-якого компонента, що реалізує даний інтерфейс, і набір операцій, які цей компонент може викликати у відповідь у інших компонентів. Інтерфейсний контракт для кожної операції самого компонента (або операції, яку він використовує) визначає передумову та постумову її виклику. Передумова операції має виконуватись під час її виклику, інакше коректність результатів не гарантується. Якщо ця операція викликається у компонента, то обов'язок подбати про виконання передумови лежить на клієнті, що викликає операцію. Якщо ж ця операція викликається компонентом в іншого компонента, він сам зобов'язується виконати цю передумову. З постумовою все навпаки: постумова викликаної у компонента операції повинна виконуватись після її виклику, і це – обов'язок компонента. Постумова операції визначає, які її результати вважаються коректними. Стосовно операцій, що викликаються компонентом, виконання їх постумов повинні гарантувати ті компоненти, у яких вони викликаються, а компонент викликає, що, може на них спиратися у своїй роботі.

Не менш важливий аспект компонентної ідеології – передбачуваність композиції взаємодіючих компонентів і каркасів. Можливі три основні види композицій в програмній системі:

– «компонент-компонент» (взаємодія по контрактах прикладного рівня, яка визначається під час розробки (раннє зв’язування) або під час виконання (пізнє зв’язування);

– «каркас-компонент» (взаємодія між компонентом і іншими компонентами каркаса по контрактах системного рівня із забезпеченням управління ресурсами);

  1.   «каркас-каркас» (взаємодія між компонентами, які розгортаються в гетерогенних середовищах (каркасах) по контрактах інтероперабельного (interoperation) рівня).

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

Компоненти розробляються у вигляді деякої програмної абстракції, що включає:

інформаційну частину – опис призначення, дати виготовлення, умов застосування (ОС, платформа тощо) та можливостей повторного використання;

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

– інтероперабільність – здатність взаємодіяти з компонентами інших середовищ;

– переносність (мобільність) – здатність працювати на різних платформах;

– інтегрованість – здатність до об'єднання з іншими компонентами в складі програмної системи;

– не функціональні характеристики - безпека, надійність і захист компоненту і даних;

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

Компонентна модель (component model) – набір правил визначення інтерфейсів компонетів і їх реалізацій, а також правил, за якими компоненти працюють в системі та взаємодіють один з одним.

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

Компонентна модель пропонує:

- стандарти по типах компонентів (наприклад, проекти, форми, COBRA-компоненти, RMI-компоненти, стандартні класи-оболонки, бази даних, JSP-компоненти, сервлети, XML-документи, DTD-документи тощо, які визначені у відповідних мовах програмування);

- стандарти схем взаємодії (методи локалізації, протоколи комунікації, необхідні атрибути якості взаємодії – безпека, управління транзакціями тощо);

- угоди про зв’язування компонентів з ресурсами (сервісами, що надаються каркасом або іншим компонентом, розгорненим у цьому каркасі). Модель описує, які ресурси доступні компонентам, як і коли компоненти зв'язуються з цими ресурсами. Каркас, у свою чергу, розглядає компоненти як ресурси, що підлягають управлінню.

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

Найбільш поширені специфікації компонентних моделей: COM (Component Object Model) (DCOM – розподілена компонентна модель, COM+), CORBA, .Net Framework, Java Beans.

1. Component Object Model (COM) – початковий стандарт Microsoft для компонентів. Визначає протокол для конкретизації і використання компонент усередині процесу, між процесами або між комп'ютерами. Основа для ActiveX, OLE і багатьох інших технологій. Може використосуватися в Visual Basic, C++ і ін.

2. Java Beans – стандарт Sun Microsystems для компонентів (тільки для Java).

3. CORBA (стандарт OMG, має громіздкий IDL-інтерфейс, складність відображення однієї мови реалізації в іншу).

4. Dot Net Framework сучасна компонента модель Microsoft для розробки складних розподілених програмних систем

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

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

Приклади компонентних середовищ: CORBA, J2EE,. NET. Самі по собі J2EE, .NET і CORBA є специфікаціями компонентних моделей і набору базових служб, які повинні підтримуватися їх реалізаціями.

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

Рис. 2.2. Співвідношення між компонентами, їх інтерфейсами, компонентною моделлю та компонентним середовищем

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

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

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

Переваги компонентного програмування:

  1.  зниження вартості ПЗ (КОП дозволяє будувати програмне забезпечення по принципу конструктора – із незалежних готових компонентів, що набагато ефективніше, ніж створювати з нуля);
  2.  КОП є в деякому сенсі розвитком об'єктно-орієнтованого підходу та практично більш придатний для розробки великих і розподілених систем (наприклад, корпоративних застосувань);
  3.  можливість повторного використання коду;
  4.  уніфікація обробки об'єктів різної природи;
  5.  менш людинозалежний процес створення ПЗ;
  6.  суворе математичне обгрунтування (ламбада-числення);
  7.  концепція універсальна й однаково застосовна для функціонального програмування і ООП;
  8.  платформна і мовна незалежність розробки ПЗ. 

Приклади компонентів.

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

<див. мал.>

Добре відомі технології складених документів:

  1.  Object Linking and Embedding (OLE) від Microsoft;
  2.  Bonobo від Ximian (вперше використано в GNOME);
  3.  XML та XSL – інкапсулює формати, які використовуються для складених документів будь-яких видів.

Складений документ – це композиція з візуальних об'єктів. Кожному типу об'єктів потрібний свій редактор. В ідеалі повинна бути можливість в будь-який момент додавати нові редактори. У цьому випадку редактор стає програмним компонентом.

Приклади типів компонентів. Візуальні:

  1.  елемент управління (control) – реалізує пов'язаний з контекстом інтерактивний об'єкт (командну кнопку, прапорець, перемикач, текстове поле);
  2.  редактор (editor) – реалізує контекстно-незалежні інтерактивні об'єкти (текстовий редактор, електронна таблиця, головоломка);
  3.  контейнер (container) –  реалізує інтерактивні об'єкти, що формують контекст, зазвичай спеціальні редактори (HTML-браузер, візуальний конструктор);
  4.  засіб перегляду (viewer) – редактор з відключеними можливостями, тобто, з вмістом тільки для читання (графічний браузер, система допомоги, Adobe Acrobat);
  5.  обгортка (wrapper) – спеціальний контейнер, який розширює або змінює поведінку обгорненого об'єкта (блок прокрутки, фонова підкладка, шар).

Невізуальні:

  1.  командний пакет (command package) – колекція інтерактивних команд, які зазвичай працюють з візуальними об'єктами (контролер орфографії);
  2.  сценарій (script) – простий командний пакет, написаний користувачем для автоматизації роботи (отримати e-mail → розібрати заголовок → зберегти в потрібній папці);
  3.  бібліотека (library) – колекція достатньо незалежних функцій або класів (математична, для роботи з рядками, класи колекцій);
  4.  служба (service) – надає каркас, який може розширюватися через plug-ins'и (потоковий ввід / вивід, зберігання документів, доступ до СУБД);
  5.  plug-in – реалізує об'єкти, які використовуються деякої службою (драйвер SCSI, компілятор з проміжного коду, файловий конвертер, драйвер до СУБД);
  6.  діловий (business) – реалізує специфічну для галузі програмну логіку (таблиці обліку / клієнтів / балансу, система контролю процесів);


Стратегії інтеграціі програмного забезпечення

Поява концепції сервісно-орієнтованої архітектури (service-oriented architecture, SOA) стало закономірним кроком на шляху пошуку розв’язання однієї з найбільш нагальних і складних проблем ІТ-індустрії – проблеми інтеграції додатків.

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

Передумови

Як вирішується завдання інтеграції програм? Традиційний підхід – побудова проміжного програмного шару того чи іншого типу. Оптимальною для об’єднання різнорідних платформ і рішень виглядала технологія взаємодії розподілених об’єктів CORBA, що дозволяла інкапсулювати бізнес-логіку додатків, що виконуються на різних платформах і створених з використанням різних мов програмування, організувавши зв’язок між ними на базі строго описаних інтерфейсів. Аналогічні можливості – правда, з природним обмеженням гетерогенності – пропонувала корпорація Microsoft в рамках своєї компонентної моделі DCOM. Однак цим рішенням не вистачало універсальності; навіть застосування CORBA сильно залежало від реалізації в продуктах різних постачальників, з’являлися нові об’єктні моделі, які не підтримують CORBA, інтеграція як і раніше реалізовувалася на досить низькому рівні, практично виключаючи можливість динамічного зміни зв’язків між додатками в ході виконання. Важливо і те, що всі пропоновані засоби інтеграції фокусувалися на технологічних особливостях реалізації програм і не дозволяли враховувати специфіку бізнес-процесів, в яких ці програми використовувалися.

У той же час нові потреби бізнесу диктують і нові умови інтеграції. Динамічність ІТ-середовища, її націленість на вирішення бізнес-завдань, необхідність швидких змін у відповідь на зміну цих завдань – Ці характеристики набувають ключового значення при проектуванні або реформуванні корпоративних ІТ-інфраструктур. У цих умовах окремі, “точкові” рішення по інтеграції настільки ускладнюють і саму інфраструктуру, і процес управління нею, що стають абсолютно неприйнятними. Уявімо собі, наприклад, що в компанії існує кілька програм, кожна з яких інтегровано з усіма іншими за допомогою відповідних інтерфейсів. Якщо таких програм – n, то все буде потрібно n (n-1) інтерфейсів. З додаванням всього лише одного нового додатка з’явиться 2n нових інтерфейсів, для яких буде потрібно відповідне документування, тестування і підтримка. У прикладі на рис. 1 п’ять взаємодіючих програм породжують 20 інтерфейсів, а додавання шостого програми зажадає ще 10. При цьому доведеться вносити модифікації в код кожного з існуючих програм для обліку нових інтерфейсів і проводити відповідне тестування. Щоб уникнути цього, потрібна модель інтеграції, яка дозволить максимально спростити процес додавання нових додатків і мінімізує кількість інтерфейсів взаємодії.

Рис. 1. Пряма інтеграція додатків 

Ще одна серйозна проблема – надмірність програмних компонентів і складність їх багаторазового використання. В [1] наводиться приклад програмної інфраструктури банку, що включає в себе кілька груп додатків для різних напрямків банківської діяльності, які були розроблені в рамках ніяк не пов’язаних між собою проектів. В результаті, з більшою часткою ймовірності можлива ситуація, коли одна функція (скажімо, отримання балансу по вкладу) реалізована багаторазово в системі автоматизації банкоматів, в системі підтримки філій і в системі розрахунків за кредитними картками, – навіть якщо всі ці системи використовують одні і ті ж дані про рахунок з загальної бази даних. А тепер припустимо, що банк має намір розробити нові системи, наприклад, для обслуговування клієнтів в Internet або видачі позик в режимі on-line. Розширення функціональності програмного середовища банку спричинить додаткову надмірність, якщо в цьому середовищі відсутні механізми багаторазового використання компонентів, що підтримують різні завдання бізнесу.

Всі ці інтеграційні проблеми і призвели до появи ідеї сервісно-орієнтованої архітектури (service-oriented architecture, SOA). Для вирішення цих проблем простого набору технологій вже недостатньо. Потрібен загальний, архітектурний підхід, концепція архітектури програмного середовища підприємства, в якій можлива адекватна потребам бізнесу динаміка розробки, інтеграції та експлуатації програм. Ідея SOA полягає у створенні архітектурної платформи, яка забезпечить швидку консолідацію розподілених компонентів – сервісів – в єдине рішення для підтримки певних бізнес-процесів. Різні визначення сервісно-орієнтованої архітектури сьогодні дають і аналітики, і виробники програмних систем. Вони не завжди збігаються в деталях, але загальний зміст їх єдиний – SOA пропонує новий підхід до створення розподілених інфраструктур, в яких програмні ресурси розглядаються як сервіси, що надаються через мережу.

Характеристики SOA

Наведемо формальне визначення сервісно-орієнтованої архітектури, яке сформульовано фахівцями корпорації IBM [1]: “SOA – це прикладна архітектура, в якій усі функції визначені як незалежні сервіси з викликуваними інтерфейсами. Звернення до цих сервісів в певній послідовності дозволяє реалізувати той чи інший бізнес-процес “. З точки зору розробників, ту ж думку можна передати дещо іншими словами: SOA – це компонентна модель, в якій різні функціональні одиниці додатків, звані сервісами, взаємодіють по мережі за допомогою інтерфейсів. Розшифруємо дані визначення.

  1.  Всі функції додатків визначені як сервіси. Як сервісу може виступати як ціле додаток, так і окремі його функціональні модулі. Сервісами можуть бути прикладні функції, що реалізують певну бізнес-логіку, бізнес-транзакції, що складаються з декількох функцій більш низького рівня, і системні функції, що відбивають специфіку різних операційних платформ.
  2.  Всі сервіси незалежні один від одного. Вони виконують певні дії за запитами, отриманими від інших сервісів, і повертають результати. Всі деталі цього повністю сховані: в концепції SOA сервіси – це “чорні ящики”.
  3.  В інтерфейсі сервісу визначені параметри і описаний результат. Іншими словами, інтерфейс визначає суть сервісу, а не технологію його реалізації. На архітектурному рівні для звернення до сервісу не має значення, чи він локальним (реалізований у даній системі) або віддаленим (зовнішній по відношенню до неї), який протокол використовується для передачі виклику, які компоненти інфраструктури при цьому задіяні. SOA припускає наявність єдиної схеми поводження до сервісу незалежно від того, чи перебуває вони в тому ж самому додатку, в іншому адресному просторі багатопроцесорної системи, на іншій апаратній платформі в корпоративній intranet-мережі або в додатку до системі партнера.

Інтерфейси – ключові елементи SOA. Вони повинні бути нейтральними до специфіки реалізації сервісу, які визначаються апаратної платформою, операційною системою, мовою програмування. Подібний нейтралітет забезпечує універсальність взаємодії сервісів в різнорідної середовищі, а сервіси, інтегровані за допомогою таких інтерфейсів, є слабко зв’язаними (loose coupling). Слабка зв’язаність забезпечує просту і швидку адаптацію системи в цілому до змін у структурі та принципах реалізації сервісів. Таким чином, для SOA характерна гнучкість, здатність реагувати на зміни в бізнес-процесах динамічно і без складних трансформацій на інтеграційному рівні.

Сервіси в SOA можуть являти собою прості або складні об’єкти, процеси, що охоплюють певну множину об’єктів, процеси, які в свою чергу складаються з декількох процесів, або навіть якийсь комплекс програм, які в сукупності призводять до отримання єдиного результату. Важливо, що з точки зору архітектури сервіс (незалежно від внутрішньої структури і мови реалізації) виглядає як єдине ціле. Можливо, що з міркувань продуктивності краще виявиться реалізація сервісів, більш складних по організації, ніж прості об’єкти.

Багато авторів підкреслюють, що ідея SOA не нова і, по суті, не пов’язана з конкретними технологіями реалізації, що її зачатки вгадуються вже в CORBA і в програмному забезпеченні проміжного шару на базі обміну повідомленнями (message oriented middleware), що її не можна ототожнювати з Web-сервісами, які представляють собою сукупність технологій і стандартів. Все це вірно, однак саме поява Web-сервісів зробило SOA реальністю. Мова опису інтерфейсів у CORBA не забезпечує тієї незалежності від платформ, яка потрібна для побудови SOA, а тому дана модель дозволяє реалізувати тільки сильно пов’язану інтеграцію компонентів. З появою XML був відкритий шлях до створення нейтральних до платформи реалізації інтерфейсів. Заснований на XML мова опису Web-сервісів WSDL і використання XML для обміну повідомленнями між сервісами забезпечують той універсальний механізм взаємодії різнорідних компонентів, без якого неможливо реалізувати SOA.

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

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

Платформа реалізації SOA

Як відзначають аналітики компанії ZapThink, яка спеціалізується на питаннях SOA, і замовникам, і постачальникам необхідно усвідомити наступний принциповий момент: SOA – це не черговий варіант розподіленої обчислювального середовища, який, досягнувши стадії зрілості, буде існувати паралельно з іншими можливими варіантами [2]. У перспективі будь-яка архітектура ІТ-середовища – клієнт-серверна, многозвенная, побудована на базі шини повідомлень і т.д. – Повинна розглядатися в контексті орієнтації на сервіси. SOA – це більш високий рівень абстракції, який дає можливість об’єднати різні архітектурні стилі та моделі організації розподілених систем на різних платформах за допомогою слабо пов’язаних інтерфейсів і асинхронного взаємодії між ними.

За прогнозами ZapThink, найближчі три роки будуть періодом вдосконалення стандартів і продуктів, які підтримують SOA, при цьому інші підходи до побудови розподілених середовищ продовжать розвиватися незалежно. До 2007-2008 року більшість програмних продуктів вже зможуть запропонувати інтерфейси Web-сервісів, і значна частина ІТ-рішень буде сервісно-орієнтованої. Аналітики ZapThink вважають, що переможний хід SOA як загальновизнаної архітектури для побудови складних, розподілених програмних інфраструктур почнеться не раніше 2008 року, і тільки до початку наступного десятиліття можна очікувати, що альтернатив сервісно-орієнтованого підходу не залишиться.

Однак, щоб отримати архітектуру для реальних додатків, концепцію SOA необхідно деталізувати. SOA – це не тільки інтерфейси для опису сервісів. Необхідно зрозуміти, як організовано потік робіт між сервісами в додатку для вирішення певної бізнес-завдання. SOA повинна відображати бізнес-процеси в програмні компоненти не тільки з урахуванням внутрішніх процесів, а й з урахуванням взаємодії з партнерами. Необхідні механізми завдання та контролю політик для зв’язку між сервісами, в тому числі, формальних угод про рівень обслуговування. Крім того, взаємодія між сервісами зобов’язує дотримуватись певних правил захисту інформації і має відбуватися в надійній середовищі. Звідси завдання забезпечення безпеки в SOA.

Програмні компоненти для вирішення всіх цих завдань утворюють платформу реалізації SOA. У ZapThink виділяють п’ять основних груп функцій програмних продуктів, необхідних для побудови SOA: це функції захисту, управління, підтримки процесів, інтеграції та інструментарію. Для того, щоб отримати працездатні програми в архітектурі SOA, обов’язковим для цих компонентів є проходження відкритим стандартам (Насамперед, стандартам Web-сервісів) і принципам сервісної орієнтації, таким як слабка зв’язаність, інкапсуляція змісту, асинхронність взаємодії.

П’ять категорій програмних рішень – це п’ять сегментів ринку програмного забезпечення, які з часом стануть частиною єдиного ринку засобів для реалізації SOA. У той же час, ці основи SOA є частиною “екосистеми” сучасного ринку програмного забезпечення, яка починає поступовий перехід до глобальної підтримки принципів орієнтації на сервіси. ZapThink призводить вражаючу діаграму ( рис. 2 ), Яка ілюструє взаємозв’язки між різними групами програмних продуктів (і відповідними сегментами цього ринку), їх положення щодо платформи реалізації SOA зараз і в найближчій перспективі.

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

Зелені блоки символізують ринки систем, пов’язаних з Web-сервісами. Вони також перебувають у перехідному стані, оскільки з’явилися порівняно недавно і з плином часу стануть частиною інших сегментів ринку сервісно-орієнтованих систем. У деяких випадках цей перехід вже фактично завершений, наприклад, для такої категорії продуктів, як СУБД, розраховані на безпосередню роботу з XML-даними. Постачальники цих рішень проявляли велику активність в 2002 році, але вже до середини 2003 року більшість з них або взагалі вийшли з гри, або були придбані іншими компаніями, або переорієнтували свою діяльність на інші стратегічні напрями, такі як оперативні сховища даних або системи управління контентом.

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


 

А также другие работы, которые могут Вас заинтересовать

76681. Психофізіологічні аспекти посттравматичного стресового розладу 87.5 KB
  Стрес присутній у житті кожної людини так як наявність стресових імпульсів в усіх сферах людського життя та діяльності безперечна. Стрес – це психічна та емоційна реакція людини на ситуацію причому будьяку ситуацію як фізичну так і емоційну.
76682. Стратегічний менеджмент 66 KB
  Зона стратегічних ресурсів становить сегмент ринку, на якому діють організації-постачальники певних ресурсів, що можуть суттєво впливати на діяльність організацій – виробників кінцевого продукту за рахунок їх дефіциту, значної конкуренції або обмеженого доступу з інших причин.
76683. Переломи стегна клінічні ознаки, особливості надання першої медичної допомоги та лікування 112.5 KB
  Перелом стегна актуальна проблема для людей, особливо у літніх людей. Перелом стегна в похилому віці може нести небезпечні для життя наслідки, тому даній травмі приділено багато уваги. Можливий перелом стегна зі зміщенням, чрезвертельный, відкритий...
76684. Boing -747 19.14 KB
  The four-engine 747 uses a double deck configuration for part of its length. It is available in passenger, freighter and other versions. Boeing designed the 747’s hump-like upper deck to serve as a first class lounge or extra seating, and to allow the aircraft to be easily converted...
76685. РЕФОРМЫ ПЕТРА I И ИХ ЗНАЧЕНИЕ 108 KB
  Многие из этих преобразований уходят корнями в XVII век социально-экономические преобразования того времени послужили предпосылками реформ Петра задачей и содержанием которых было формирование дворянско-чиновничьего аппарата абсолютизма.
76686. ИСКОВАЯ ДАВНОСТЬ 257.87 KB
  В юриспруденции учение об исковой давности является одним из фундаментальных, и привлекает к своему исследованию многих ученых цивилистов. Не смотря на то, что дефиниция исковой давности относится к числу теоретических разногласий, институт исковой давности не умаляет своего научного и практического значения.
76687. Увольнение за утрату доверия к работнику 21.19 KB
  Для этого существует статья 81 Расторжение трудового договора по инициативе работодателя в частности пункт 7 данной статьи Увольнение сотрудника в связи с утратой к нему доверия. Так какие же лица подлежат увольнению по данной статье Можем ли мы уволить сотрудника по субъективному мнению о его нечестности...