0 follower

Кращі практики MVC

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

Допустимо, що веб-додаток складається із декількох піддодатків, таких як

  • front end: та частина сайту, яку бачать користувачі;
  • back end: адміністративна частина сайту, яка дозволяє керувати додатком. Доступ до неї зазвичай обмежений;
  • консоль: додаток, який складається із набору консольних команд та запускається у вікні терміналу або як завдання cron-у;
  • API: надає стороннім додаткам інтерфейси для інтеграції з вашим додатком.

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

1. Модель

Моделі представляють структури даних, які використовуться у додатку, і часто є спільними для кількох піддодатків. Наприклад, модель LoginForm може бути використана як у користувальницькій, так і у адміністративній частині додатку. Модель News може використовуватися консольними командами, API та front/back частинами додатку. Тому, моделі

  • повинні містити властивості, які представляють конкретні дані;

  • повинні включати у себе бізнес-логіку (наприклад, правила валідації) для того, щоб переконатися, що дані відповідають вимогам;

  • можуть містити код для роботи із даними. Наприклад, модель SearchForm, окрім даних для пошуку, може містити метод search, який цей пошук здійснює.

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

  • Створити модель NewsBase, яка містить тільки код, загальний для піддодатків (користувальницької та административної частин);

  • У кожному піддодатку створити модель News, наслідувану від NewsBase та визначити у ній специфічні для піддодатку методи.

Таким чином, якщо застосувати це до розглянутому вище прикладу, необхідно додати модель News із методом getLatestNews у користувальницьку частину та ще одну модель News із методом getDeletedNews у адміністративну частину.

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

  • не повинні використовувати $_GET, $_POST або інші подібні змінні, які напряму отримуємо із запиту користувача, так як моделі можуть використовуватися у зовсім інших піддодатках (наприклад, у модульних тестах або API), у яких ці змінні недоступні. Всі змінні, які відносяться до запиту користувача, повинні оброблятися у контролері;

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

2. Представлення

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

  • повинні, головним чином, містити розмітку, таку як HTML, або простий PHP код, який використовується для обходу, форматування та відображення даних;

  • не повинні безпосередньо звертатися до бази даних. Цим повинні займатися моделі;

  • не повинні безпосередньо звертатися до $_GET, $_POST та іншим змінним, які отримуються із запиту користувача. Цю задачу повинен виконувати контролер. Представлення повинно використовуватися для задання зовнішнього вигляду даних, отриманих із контролера та моделі;

  • може безпосередньо звертатися до властивостей та методів контролера або моделей. При цьому дані властивості та методи повинні відповідати за відображення.

Представлення можна використовувати повторно кількома способами:

  • Загальний шаблон: у нього можна винести розмітку, загальну для всіх сторінок. Наприклад, шапку та підвал;

  • Частини шаблону: використовуються всередині інших шаблонів та, як правило, не використовуються із загальним шаблоном. Приміром, частину шаблону _form.php можна використовувати для відображення форми вводу моделі, яка буде використовуватися як при її створенні, так і при редагуванні;

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

  • Хелпери: у шаблонах часто потрібно виконувати невеликі завдання, такі як форматування даних або генерація HTML-тегів. Замість того, щоб вставляти код безпосередньоу у шаблони, можна помістити його в клас-хелпер та використовувати цей клас у шаблонах. Наприклад, такий підхід можна знайти у класі CHtml, який допомогає генерувати часто використовуваний HTML код. Для того, щоб уникнути явного підключення класів, хелпери можна помістити у окрему директорію, яка прописана у import.

3. Контролер

Контролери — сполучна ланка, яка поєднує моделі, представлення та інші компоненти у робочий додаток. Контролер відповідає за обробку запитів користувача. Тому контролер

  • може звертатися до $_GET, $_POST та інших змінних PHP, які отримуються із запиту користувача;

  • може створювати екземпляри моделей та керувати ними. Приміром, у типової дії оновлення моделі контролер може спочатку створити екземпляр моделі, потім заповнити його даними із $_POST та, після вдалого збереження моделі, перенаправити браузер користувача на сторінку створеної моделі. Слід відмітити, що саме зберігання моделі повинно бути реалізоване у моделі, а не в контролері;

  • не повинен містити SQL-запитів. Їх краще тримати у моделях;

  • не повинен містити HTML та іншої розмітки. Її варто винести у представлення.

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

Found a typo or you think this page needs improvement?
Edit it on github !