Концепція каркасно-компонентного програмування (К3П) — це певний погляд на набір засобів для створення каркаса проєкту в цілому та розробки каркасів окремих компонентів, наповнення таких каркасів необхідним функціоналом та їх впровадження до самого проєкту чи інших компонентів.
Основна термінологія Каркас проєкту — набір певним чином структурованих файлів та каталогів, що містять початкові відомості для створення програмного засобу (інсталяційного пакету, сайту, веб-застосунку, інше), але не містять конкретного змістовного наповнення (кодів, що визначають функціонал проєкту).
Проєкт — це каркас проєкту, що принаймні частково містить змістовне наповнення у якому реалізований певний функціонал відповідно до технічних завдань.
К3П передбачає можливість створення каркаса проєкту на етапі аналізу предметної області і відповідних технічних завдань, поділ між розробниками ділянок роботи (у разі потреби, із використанням принципів мережевого планування). У найбільш загальному випадку допускається розробка у повному обсязі каркаса проєкту та лише після цього наповнення його предметним змістом. З іншого боку К3П цілком допускає подальше масштабування та редагування проєкту з мінімальною витратою часу на аналіз вже виконаних робіт за рахунок строго визначених принципів його побудови.
Клас — структура опису даних та функціоналу їх опрацювання згідно концепції ООП.
Об'єкт — змінна типу даних «клас» в концепції ООП.
Функціонал - набір функцій (методів) класу.
Під компонентом будемо розуміти логічно та функціонально завершений блок кодів програми, який у загальному випадку містить засоби для опрацювання та відображення певних даних у залежності від його призначення. Структура компонента описується наперед визначеною ієрархією класів.
Твердження. Будь-який компонент є об'єктом, але не будь-який об'єкт є компонентом.
Каркас кодів — набір певним чином структурованих каталогів та файлів у цих каталогах.
Каркас компонента — це каркас кодів, що містить файли-заготовки з початковими кодами створеними певною мовою програмування, які мають наперед визначену структуру. Після наповнення каркаса предметним вмістом він набуває ознак компоненту.
СЕ — структурний елемент або елемент структури на певній схемі, що описує загальні принципи функціонування компоненту.
Базовий компонент — компонент, що не містить у своїй структурі інших компонентів.
Асоціаційний компонент — компонент, що містить у своїй структурі інші компоненти (композиція) або зв'язки з іншими компонентами (агрегація).
Із вище зазначеного можна зробити висновок, що проєкт є блоком кодів та асоціаційним компонентом, компонент є міні-проєктом.
Для чого потрібна К3П? Як відомо, основна причина використання кожної концепції програмування — систематизувати та узагальнити методи написання кодів, структуризувати певним чином елементи проєкту так, щоб він був масштабованим та зручним для читання/редагування не лише розробниками, які починали проект, а й залученими до розробки працівниками (програмістами, дизайнерами, тестувальниками) у майбутньому.
З цієї причини з'явилась концепція ООП, паттерни програмування, парадигма MVC, бібліотеки шаблонів, фреймворки та інше.
Метою даної статті є демонстрація можливостей організації кодів проєкту у вигляді набору компонентів, які створюються на основі строго визначеного каркаса. У свою чергу така організація кодів проєкту має сприяти підвищенню ефективності його редагування та масштабування.
Як реалізувати К3П? У цілому, кожен може самостійно розвинути подібну ідею для власної практичної діяльності та у залежності від того, з чим розробник працює (Java, Pyton, C++ і т. д.).
Перше з чого варто почати — ретельна розробка загальної структури компонента. Подальша зміна цієї складової вкрай небажана, особливо при наявності вже створених на її основі компонентів чи проєктів.
Друге — створення шаблонів, що моделюють елементи попередньо розробленої структури. Розроблені шаблони цілком допускається редагувати у майбутньому, але з врахуванням принципу «не нашкодь!», тобто внесені зміни не повинні впливати на вже працюючі раніше створені компоненти.
Третє — створення засобу для автоматичного генерування каркаса компонента.
Подальший матеріал стосовно реалізації вищеперерахованих кроків буде демонструватися на прикладах з використанням JavaScript.
MVC та К3П Перш ніж перейти до JavaScript коротко згадаємо загальновідомий архітектурний шаблон MVC.
Особисто автору даної статті у схемі «Model View Controller» завжди чогось не вистачало… Виникає думка, що не вистачає такої компоненти, як події (Event). Можна зазначити, що Event це частина View або частина іншого СЕ. Але якщо це все ж частина, то чому б цю частину не винести окремо?
Загальні уявлення про MMVCE Вище було згадано про події, але з'явилося певне подвоєне «MM» в абревіатурі «MMVCE». Перша «M» — це «Main», ще один СЕ, який є точкою запуску та стикування компонента.
Нижче наведено схему MMVCE.
У цілому, СЕ схеми майже такі, як на типових схемах MVC.
Але є певні зауваження. Про них йде мова далі.
Коротко про головне і загально відоме: принцип роботи будь-чого у всесвіті взагалі та в програмуванні зокрема, у загальному, зводиться до трьох кроків.
1-й крок — сприймання даних (отримання даних, у програмуванні це передавання даних на опрацювання до певного алгоритму).
2-й крок — опрацювання даних (певні обчислювальні процеси у залежності від поставленої задачі, власне, пропускання цих даних через деякий алгоритм).
3-й крок — зворотна реакція (повернення результату опрацювання даних).
Таким чином на схемі жовті стрілки — це (механізми, потоки, процеси) передавання даних.
Сині стрілки — це (механізми, потоки, процеси) отримання результату.
Блоки на схемі — це СЕ, що позначають відповідний функціонал з реалізацією певних алгоритмів опрацювання даних.
Тут СЕ «модель», «вигляд», та «контролер» мають приблизно той самий зміст, що і у концепції MVC.
Кожен СЕ реалізується у вигляді окремого класу.
Коротко про суть кожного СЕ в схемі MMVCE.
Модель (Model). Містить дані, закриті для безпосереднього доступу користувача та функції опрацювання цих даних. Структура таких даних залежить від призначення компонента. Наприклад, для компонента "Меню" СЕ "Модель" може містити структуру, що моделює дерево меню та функції опрацювання вузлів такого дерева.
Контролер (Controller). Ні, він нічим не керує, як про це вказують у парадигмі MVC, це лише місток, що пов'язує СЕ моделі, вигляду та подій. Ще одне важливе значення контролера — це точка підключення інших компонентів (нижче буде наведена відповідна схема та деякі приклади).
Вигляд (View). СЕ з функціоналом, що відповідає за інтерпретацію та відображення даних.
Події (Event). СЕ у якому описані усі події, що можуть відбуватися над компонентом.
BEC (bus for external connection — шина для зовнішнього підключення). Це лише позначення можливості використовувати одні компоненти, як елементи у інших компонентах (така собі агрегація).
На схемі СЕ прямокутники Main та View зображені, відповідно, червоним та зеленим кольором і з певним виходом за межі прямокутника, який позначає компонент. Це зроблено для того, щоб підкреслити, що такі СЕ застосовуються для безпосереднього використання користувачем-програмістом (Main) та користувачем вашого програмного засобу (View).
Main — це «точка» створення/запуску компонента (такий собі ключ запалювання).
View — це «площина» взаємодії користувача програмного засобу з компонентом (така собі консоль).
Прямокутники СЕ Controller, Model, Event та BEC позначені сірим кольором, що демонструє обмежений доступ до цих елементів для користувача-програміста та закритий доступ для користувачів програмного засобу.
Загальна структура проєкту у концепції каркасно-компонентного програмування Кожен завершений додаток (програма), готовий до кінцевого використання сторонніми користувачами — це компонент.
Деякі компоненти можуть містити у своїй структурі інші компоненти (асоціаційні компоненти).
Отже кожен завершений додаток — це ієрархічна структура, що складається з компонентів.
Існують компоненти, що не містять у своїй структурі інших компонентів (базові компоненти).
Компоненти поєднуються у певну ієрархію через точку виходу на СЕ Main та точку входу на СЕ Controller. Інші способи поєднання компонентів теоретично можливі, але вважаються недоцільними, оскільки це порушує загальну структуру побудови проєкту і, таким чином, його подальше, у разі потреби, масштабування та редагування.
Усі компоненти мають строго визначену структуру, каркас компонента формується за єдиним алгоритмом.
Усе вище описане демонструється на наступній схемі:
На схемі у крайньому лівому положенні розташовано блок, що позначає проєкт (Main Prj), праворуч від нього показано розгортання усіх компонентів, які входять до його складу.
Так, наприклад, компоненти 'C 01' , 'C 02' та 'C 04' - базові компоненти. Компонент 'C 03' - асоціаційний.
Проєкт 'Main Prj' , фактично, є асоціаційним компонентом, який включає в себе компоненти 'C 03' та 'C 04' .
Загальний опис реалізації парадигми MMVCE мовою JavaScript
На малюнку зображено структуру файлів та каталогів компонента "Menu".
Файл "Menu.css" містить опис css-стилів для відображення компонента. Якщо компонент не візуальний - вміст цього файлу залишається порожнім. Якщо передбачається, що компонент міститиме додаткові ресурси, притаманні лише йому, то допускається у каталозі "css" або у кореневому каталозі компонента створення вкладених каталогів, наприклад, "fonts", "images", "sounds", інше. Спільні ресурси доцільно розміщувати у каталогах проєкту чи каталогах асоціаційних компонентів.
Кожен *.js файл містить опис відповідного класу та отримує назву відповідно до шаблону C[NameComponent][NameFile]. Так, наприклад, якщо компонент має назву Menu, то клас у файлі controller.js матиме назву CMenuController.
Кожен клас компонента допускає успадкування від відповідного базового класу. Так, наприклад, похідний клас CMenuView може бути успадкованим від базового класу CView. Таким чином для опису компонента можна використати п'ять базових класів CMain, CModel, CView, CController, CEvent, які у свою чергу можуть бути успадковані від базового класу CObject. Подібна ієрархія класів використовується, зокрема, такими мовами програмування, як Object Pascal, MFC C++, NET Framework, Java, інше.
Файл «test.php» слугує для тестування можливостей використання компонента.
Які саме коди мають бути створені у відповідних класах, у цілому, питання творче і має бути вирішене програмістом чи групою програмістів у залежності від поставлених завдань. Нижче будуть наведені деякі зразки подібних кодів, які є лише зразками, але вони, можливо, спонукають читачів даної статті до покращення розуміння К3П та розробки власних підходів в організації кодів, як невеликих так і масштабних проєктів.
Про можливості використання сторонніх бібліотек та фреймворків Одне із основних завдань К3П - створення "чистого коду на чистій архітектурі" (див. " Роберт Мартін. "Чистий код"). У свою чергу один із постулатів створення "чистого коду" - обережне використання сторонніх бібліотек та фреймфорків. Сторонні інструменти не повинні визначати та керувати логікою проєкту, їх задача спростити розробку, а не підпорядкувати її.
Саме з цієї причини, у ідеальному варіанті, класи з описами компонентів мають містити лише коди, створені розробником цього компоненту, усі сторонні бібліотеки мають бути винесені у п'ять вищезазначені базові класи.
Приклад компонента Menu мовою JavaScript Нижче наведений лістинг кодів тестування компонента Menu (файл test.php). <?php $p = "?p=".time();
$path_to_js = "../../js/"; $path_to_base_class = "../../js/bc/"; $use_jquery = true;
extract($_GET); ?>
<!DOCTYPE html>
<html> <head> <title>Testing the "Menu" component</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel='stylesheet' type='text/css' href='css/Menu.css<?php echo $p; ?>'> </head> <body> <div id="container"></div>