Шарувата архітектура на основі фреймворку yii

Уявімо собі компанію, яка реалізує цілий ряд продуктів: зовнішніх і внутрішніх. Це не аутсорсингова розробка, а робота і розвиток власних продуктів. Швидше за все, кожен продукт компанії не буде існувати окремо, як сферичний кінь у вакуумі, а буде в якійсь мірі інтегрований з іншими продуктами компанії (інтеграція з CRM як з внутрішнім продуктом або інтеграція з якимсь зовнішнім продуктом). Тобто, в підсумку всі вони разом утворюють певний шар взаємопов'язаних між собою самостійно розвиваються (швидше за все, навіть різними групами розробки) продуктів. Хороший приклад - Яндекс (карти, пошта, МойКруг) або Гугл (пошта, Docs, карти). Зрозуміло, що у перелічених гігантів технології в кожному продукті свої, але якщо взяти компанію трохи менше і працює в більш вузької предметної області, то можна припустити, що веб-продукти такої компанії скоріше за все будуть виконані на одних технологіях (ЯП, фреймворки і т.д .) Звідси можемо ввести два поняття:

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

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

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

Нашою метою було створення такої веб-інфраструктури компанії. Ми почали з підготовки технологічної бази. Були обрані наступні фреймворки і технології:

Чому вибрані саме ці системи, обговорювати не будемо, стаття не про це.

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

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

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

Не розглядаючи мережу і сервера, які самі по собі є окремими шарами, звернемося до пристрою самого додатка. У додатку можна виділити три шари:

Рис. 1. Шари архітектури технологічної платформи

На рис.1. виділено три шари:

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

Розглянемо більш детально файлову організацію програми в Application layer з урахуванням специфіки yii.

application
 framework - сюди деплоітся фреймворк
 lib - компоненти з core і shared. Для цієї папки в конфіги Yii заведений окремий alias
  components
  extensions
  ...
 protected
  components
  extensions
  ...
 public
 themes
 config
рис 2. Файлова організація yii програми

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

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

Тепер по кожному пункту детальніше.

Архітектура програми

В основу архітектури додатки також покладемо шари. Виділимо наступні рівні:

рис 3. Шари yii-додатки

Шар «тонких» контролерів містить мінімум логіки і оперує API розширень. Шар бізнес логіки складається з рівня Розширення та рівня моделей даних. Шар yii Розширення та моделі даних мають дуже сильну ступінь пов'язаності, на діаграмі це показано більше жирної стрілкою.

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

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

Приклад підключення розширення:

'geoip' =>array ('class' =>'application.extensions.GeoIP.CGeoIP'),

До ініціалізіруемому розширенню в додатку можна буде звертатися по ключу geoip. Наприклад:

Yii:: $ app->geoip.

При першому зверненні до компоненту відбудеться ініціалізація класу CGeoIP. Гнучкість полягає в наявності ключа. :) Ми можемо в будь-який момент через конфіг підмінити реалізацію, а додаток буде працювати як і раніше по ключу geoip.

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

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

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

Давайте трохи пофантазуємо і придумаємо додаток:

рис 4. Приклад архітектури yii-додатки

Наше додаток працює з декількома розширеннями. Розширення оперують набором даних і тісно пов'язані з шаром моделей. Важливий момент: ступінь зв'язаності меду шарами росте зверху вниз. Тісніше за все пов'язані між собою моделі даних.

Тепер давайте уявимо, що виникла необхідність у створенні єдиного сервісу користувачів, щоб всі наші продукти працювали з одними і тими ж користувачами, була єдина авторизація и.т.д Ми можемо легко реалізувати цей сервіс у вигляді окремого додатка. Для роботи з новим додатком пишемо розширення - rest клієнта UserServiceRestClient. Клієнт матиме таке ж API, що і UserExtension API. Дивимося малюнок для наочності:

рис. 5

UserServiceRestClient поміщаємо в shared рівень і міняємо в конфіги програми клас, який потрібно використовувати. Так як API однакове, підміна реалізації пройшла без зміни коду. Дуже гнучко. :) Всі інші програми так само працюють із сервісом користувачів, використовуючи UserServiceRestClient.

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

Система деплоя і збірки

Що повинна робити система деплоя:

А також завдання запуску unit-тестів, складання debug-версій проекту і т.д Все не перераховую - справа смаку, та й уваги всім цим операція приділено вже досить багато в інтернеті. :) Наприклад, у нас в компанії Деплой-система конфігурує супутнє ПЗ типу Nginx, Sphinx і RabbitMQ і створює документацію. Зручно.

В цілому, завдання звичайні: файлові операції, робота з системами контролю версій, запуск сторонніх утиліт (phpUnit, наприклад, або doxygen) і т.д Єдине, на що варто звернути увагу, це генерація конфіга. Ми зробили генерацію конфіга за шаблоном з мета-конфігураційним файлом. Тобто:

application
 protected
  config
  main.php.template - шаблон конфіга yii
 public
 themes
 build.prop - мета-конфігураційний файл
 build.xml - конфіг phing'a
рис. 6

При генерації конфіга phing пропарсівает шаблон і замінює все placeholder'и на відповідні параметри, задані в мета-конфігураційному файлі. Вийшло дуже зручно. Всі залежності програми задаємо в мета-конфіг. Наприклад:

# # List of extensions, components and etc. to install # #
EXTENSIONS = myExt, myExt2
COMPONENTS = component1, component2
HELPERS = myHeper, myTextHelper
COMMANDS =

Також в мета-конфіги прописані бази даних, шляхи, хости - загалом, все. Додаткова зручність для автоматизації полягає в тому, що всі ці параметри можна передати через командний рядок phing'у і перевизначити. А в майбутньому, наприклад, налагодити складання пакетів під використовувану вами * nix ОС.

Таким чином, мета-конфігураційний файл - це шар абстракції від формату і кількості конфіги в нашому додатку. :)

У результаті гнучкість конфігурації yii + система збирання = легко конфігуровані і збираються продукти.

Підсумок

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

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

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

Опубліковано: 26/09/11 @ 06:57
Розділ Різне

Рекомендуємо:

25-й випуск подкасту «Відверто про IT кар'єризм». Бесіда з дизайнером, талановитої та обдарованої всебічно Юлією Кривицької
Карго-культ управління проектами
Шантаж DDOS-атакою як нова модель бізнесу
Эстафета «Комментёры» и не покидающие меня мысли о заработке
Анна Старинська: «Менеджмент не дає трапитися поганого, а лідерство дає трапитися хорошому»