MVC (Model, View, Controller) - це схема організації коду в додатку для покращення технічного обслуговування.
Уявіть фотографа зі своїм фотоапаратом у студії. Замовник просить його сфотографувати коробку.
Архітектури, що не належать до MVC, як правило, тісно інтегровані разом. Якби коробка, контролер і камера були одним і тим самим об'єктом, тоді нам доведеться роз'єднатись, а потім перестроювати і коробку, і камеру кожного разу, коли ми хотіли отримати новий вигляд. Також фотографувати завжди було б як спробувати зробити селфі - і це не завжди дуже просто.
bwaha написав:
Автор посилається на mvctree.py в wxPython як приклад дизайну MVC. Однак я все ще занадто зелений, тому вважаю, що конкретний приклад є занадто складним, і я не розумію розлуки, яку рекомендує автор.
MVC - це все, що стосується відокремлення проблем.
Модель несе відповідальність за управління даними програми (як приватними, так і клієнтськими). Перегляд / контролер відповідає за забезпечення зовнішнього світу засобами взаємодії з клієнтськими даними програми.
Модель пропонує внутрішній інтерфейс (API), що дозволяє іншим частинам програми взаємодіяти з нею. Контролер View / Controller пропонує зовнішній інтерфейс (GUI / CLI / веб-форма / IPC високого рівня / тощо), що дозволяє всім поза програмою спілкуватися з нею.
Модель несе відповідальність за збереження цілісності даних програми, тому що якщо це пошкоджується, то це гра закінчена для всіх. Перегляд / контролер відповідає за збереження цілісності інтерфейсу користувача, переконуючись, що всі перегляди тексту відображають актуальні значення, вимикають пункти меню, які не стосуються поточного фокусу тощо.
Модель не містить коду перегляду / контролера; немає класів віджетів GUI, немає коду для розміщення діалогових вікон або отримання вводу користувача. Перегляд / контролер не містить коду моделі; відсутній код для перевірки URL-адрес або виконання запитів SQL, а також вихідний стан: будь-які дані, що зберігаються віджетами, призначені лише для відображення, а лише відображення справжніх даних, що зберігаються в Моделі.
Тепер ось тест справжнього дизайну MVC: програма, по суті, повинна бути повністю функціональною навіть без доданого View / Controller. Гаразд, зовнішній світ матиме проблеми з взаємодією з ним у такому вигляді, але поки хтось знає відповідні заклики API API, програма буде зберігати та обробляти дані як звичайні.
Чому це можливо? Ну, проста відповідь полягає в тому, що все це завдяки низькій зв'язці між шарами Model і View / Controller. Однак це ще не повна історія. Ключове значення для всього шаблону MVC - це напрямок, в якому йде це з'єднання: ВСІ інструкції надходять від View / Controller до Model. Модель НІКОЛИ не повідомляє View / Controller що робити.
Чому? Тому що в MVC, хоча View / Controller дозволено трохи знати про Модель (конкретно, API моделі), але Моделі заборонено знати нічого про View / Controller.
Чому? Тому що MVC збирається створити чітке розмежування проблем.
Чому? Щоб запобігти складності програми, яка вийшла з-під контролю і поховала вас, розробника, під нею. Чим більша програма, тим більша кількість компонентів у цій програмі. І чим більше зв'язків існує між цими компонентами, тим складніше розробникам підтримувати / розширювати / замінювати окремі компоненти або навіть просто слідкувати за тим, як працює вся система. Задайте собі запитання: дивлячись на схему структури програми, ви б краще побачили дерево або котячу колиску? Шаблон MVC дозволяє уникнути останнього, забороняючи кругові з'єднання: B може з'єднуватися з A, але A не може з'єднуватися з B. У цьому випадку A - модель, а B - перегляд / контролер.
До речі, якщо ви різкі, ви помітите проблему із щойно описаним обмеженням "в одну сторону": як Модель може повідомити Перегляд / Контролер про зміни в даних користувачів моделі, коли Моделі навіть не дозволено знаєте, що Перегляд / Контролер, незважаючи на те, щоб надсилати на нього повідомлення? Але не хвилюйтеся: для цього є рішення, і воно досить акуратне, навіть якщо спочатку це здається трохи крутим. Ми повернемося до цього через мить.
На практиці, об'єкт View / Controller може через API моделі 1. сказати Моделі робити речі (виконувати команди) та 2. сказати Моделі дати їй речі (повернути дані). Шар Перегляд / Контролер
висуває інструкції до шару Модель і витягує інформацію з шару Модель.
І ось тут ваш перший приклад MyCoolListControl піде не так, оскільки API цього класу вимагає, щоб
в нього була спрямована інформація , тож ви повертаєтесь до двостороннього з’єднання між шарами, порушуючи правила MVC і скидаючи вас прямо назад у котяча архітектура колиски, якої ви [імовірно] намагалися уникнути в першу чергу.
Натомість клас MyCoolListControl повинен йти разом із потоком, витягуючи потрібні йому дані із шару нижче, коли це потрібно. Що стосується віджета списку, це, як правило, означає запитати, скільки значень існує, а потім по черзі запитувати кожен з цих елементів, оскільки це про найпростіший і найбідніший спосіб зробити це, і тому зводить мінімальну зв'язок до мінімуму. І якщо віджет хоче, скажімо, подати ці значення користувачеві в приємному алфавітному порядку, то це вже його негатив; і його відповідальність, звичайно.
Тепер, остання головоломка, як я натякав раніше: як ви зберігаєте дисплей інтерфейсу синхронізований із станом моделі в системі на базі MVC?
Ось проблема: багато об’єктів View є стаціонарними, наприклад, прапорець може бути галочкою або відмічено, текстове поле може містити текст, який можна редагувати. Однак MVC диктує, що всі користувацькі дані зберігаються на рівні Model, тому будь-які дані, що зберігаються іншими шарами для цілей відображення (стан прапорця, поточний текст текстового поля), таким чином, повинні бути допоміжною копією цих первинних даних моделі. Але якщо стан Моделі зміниться, копія перегляду цього стану вже не буде точною і потребує оновлення.
Але як? Шаблон MVC перешкоджає, щоб Модель штовхала свіжу копію цієї інформації в шар Перегляд. Чорт забирає, вона навіть не дозволяє Моделі надсилати Погляд повідомлення, щоб сказати, що його стан змінився.
Ну, майже. Гаразд, шару Model не дозволяється спілкуватися безпосередньо з іншими шарами, оскільки для цього потрібно, щоб він знав щось про ці шари, і правила MVC цьому перешкоджають. Однак, якщо дерево падає в лісі і його ніхто не чує, це звучить?
Відповідь, ви бачите, це створити систему сповіщень, забезпечивши шару "Модель" місце, яке він може оголосити нікому, зокрема, що він щойно зробив щось цікаве. Потім інші шари можуть публікувати слухачів із цією системою сповіщень, щоб слухати ті повідомлення, які їх насправді цікавлять. Шар моделі не повинен нічого знати про те, хто слухає (або навіть якщо хтось взагалі слухає!); він просто розміщує оголошення, а потім забуває про нього. І якщо хтось почує це оголошення і захоче щось робити після цього - як-от запитати у Моделі якісь нові дані, щоб він міг оновити її екранне відображення - то чудово. Модель просто перераховує, які сповіщення він надсилає як частину свого визначення API; і те, що хтось ще робить з цим знанням, залежить від них.
MVC збережений, і всі радіють. Ваша програма застосунків може забезпечити вбудовану систему сповіщень, або ви можете написати свою, якщо ні (див. "Шаблон спостерігача").
...
У будь-якому випадку, сподіваюся, що це допомагає. Як тільки ви зрозумієте мотивацію, що стоїть за MVC, причини, чому все робиться так, як вони є, починають мати сенс, навіть коли - на перший погляд - вони здаються складнішими, ніж потрібно.
Ура,
має