Як вибрати відповідну архітектуру iOS (частина 2)

MVC, MVP, MVVM, VIPER або VIP

Ви можете порадитися з першою частиною тут.

Основні архітектури iOS

Короткий огляд

MVC

Шари MVC наступні:

М: Бізнес-логіка, мережевий рівень та рівень доступу до даних

V: Прошарок інтерфейсу користувача (речі UIKit, дошки розкадрів, Xibs)

C: Координує посередництво між моделлю та поданням.

Для розуміння MVC ми повинні розуміти контекст, в якому він був винайдений. MVC був винайдений в старі часи веб-розробки, де у видах немає стану. За старих часів кожного разу, коли нам потрібна візуальна зміна веб-сайту, браузер знову завантажує весь HTML. На той час не існувало концепції збереження та збереження стану перегляду.

Наприклад, були деякі розробники, які змішувались в межах одного HTML-файла, PHP та доступу до бази даних. Тож основною мотивацією MVC було відокремлення шару View від шару Model. Це збільшило простежуваність шару Модель. Імовірно, у MVC шар шару View і Model нічого не повинен знати один про одного. Щоб зробити це можливим, був винайдений посередницький шар під назвою Controller. Це було застосовано СРП.

Приклад циклу MVC:

  1. Дія / подія користувача в шарі перегляду (наприклад: Оновити дію) запускається, і ця дія повідомляється Контролеру
  2. Контролер, який запитує дані до шару моделі
  3. Моделюйте дані, що повертаються в контролер
  4. Контролер каже для оновлення View оновлення свого стану новими Даними
  5. Переглянути оновлення його стану

Apple MVC

В iOS контролер перегляду поєднаний з UIKit та поданням життєвого циклу, тому MVC не є чистим. Однак у визначенні MVC ніщо не говорить про те, що Контролер не може знати конкретної реалізації View або Model. Його основна мета полягає в тому, щоб відокремити відповідальність шару "Модель" від шару "Перегляд", щоб ми могли його повторно використовувати і протестувати шар Моделі ізольовано.

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

MVC часто створює назву проблеми Massive View Controller, але це лише відбувається і стає серйозною справою в додатках з достатньою складністю.

Існує кілька методів, які розробник може використовувати, щоб зробити контролер перегляду більш керованим. Деякі приклади:

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

MVC проти MVP

Як ви бачите діаграму MVP дуже схожа на MVC

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

Тим часом всесвітня павутина зростала, і багато спільноти розробників розвивалися. Наприклад, програмісти почали використовувати Ajax і завантажують одразу лише частини сторінок замість усієї HTML-сторінки.

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

HTML був частиною шару View, і багато випадків були тупими, як нахабно. У деяких випадках він отримує лише події від користувача та відображає візуальний вміст GUI.

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

Логіка презентації - це логіка, яка керує способом відображення інтерфейсу користувача та взаємодією елементів інтерфейсу. Прикладом може слугувати логіка керування, коли індикатор завантаження повинен починати показувати / анімувати, а коли він повинен перестати показувати / анімувати.

У MVP та MVVM простір перегляду повинен бути тупим як ебать без будь-якої логіки та інтелекту в ньому, а в iOS контролер перегляду повинен бути частиною шару перегляду. Те, що View є німим, означає, що навіть логіка презентації залишається поза шаром View.

Однією з проблем MVC є те, що не зрозуміло, де повинна залишатися логіка презентації. Він про це просто мовчить. Чи повинна логіка презентації бути в шарі «Перегляд» або в шарі моделі?

Якщо роль Моделі полягає в тому, щоб просто надавати "необроблені" дані, це означає, що код у Перегляді буде таким:

Розглянемо наступний приклад: у нас є Користувач із прізвищем та прізвищем. У Перегляді нам потрібно відобразити ім'я користувача як "Прізвище, ім'я" (наприклад, "Флорес, Тіаго").

Якщо роль Моделі полягає у наданні "необроблених" даних, це означає, що кодом у Перегляді буде:

нехай firstName = userModel.getFirstName ()
нехай lastName = userModel.getLastName ()
nameLabel.text = lastName + “,“ + firstName

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

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

нехай ім'я = userModel.getDisplayName ()
nameLabel.text = ім'я

Про це MVP зрозуміло, і логіка презентації залишається в шарі презентації. Це збільшує простежуваність шару Presenter. Тепер Модель і Шари для презентацій легко перевірити.

Зазвичай у реалізаціях MVP Перегляд приховується за інтерфейсом / протоколом, і не повинно бути посилань на UIKit у Presenter.

Інша річ, яку слід пам’ятати, - це перехідні залежності.

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

Різні шари також змінюються з різних причин і з різною швидкістю. Отже, змінюючи шар, ви не хочете, щоб це викликало вторинні ефекти / проблеми в інших шарах.

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

Отже контракти (протоколи) створюють розв'язку між шарами.

MVP проти MVVM

Діаграма MVVM

Однією з головних відмінностей між MVP і MVVM є те, що в MVP Презентатор спілкується з Поглядом через інтерфейси, а в MVVM Погляд орієнтований на зміни даних і подій.

У MVP ми робимо вручну прив'язку між Presenter та View за допомогою інтерфейсів / протоколів.
У MVVM ми робимо автоматичне прив'язування даних, використовуючи щось на зразок RxSwift, KVO або використовуючи механізм із загальними та закритими даними.

У MVVM нам навіть не потрібен контракт (наприклад: інтерфейс java / протокол iOS) між ViewModel та View, оскільки ми зазвичай спілкуємося через шаблон дизайну Observer.

MVP використовує шаблон «Делегат», тому що представники Layer Layer надають замовлення на шар перегляду, тому йому потрібно щось знати про перегляд, навіть якщо це лише підпис інтерфейсу / протоколу. Подумайте про різницю між Центром сповіщень та Делегатами TableView. Центру сповіщень не потрібні інтерфейси для створення каналу зв'язку, але TableView Delegates використовує протокол, який повинні застосовувати класи.

Подумайте про логіку подання індикатора завантаження. У MVP презентатор робить ViewProtocol.showLoadingIndicator. У MVVM у ViewModel може бути властивість isLoading. Шар перегляду за допомогою автоматичного прив'язки даних виявляє, коли це властивість змінюється та оновлюється. MVP більш імперативний, ніж MVVM, оскільки Ведучий дає накази.

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

MVVM простіше перевірити, ніж MVP, оскільки MVVM використовує шаблон дизайну спостерігача, який передає дані між компонентами нерозділеним способом.
Таким чином, ми можемо перевірити, лише переглянувши зміни в даних, просто порівнявши два об'єкти, а не створивши знущання над методами викликів для перевірки зв'язку між View і Presenter.

PS: Я зробив декілька оновлень статті, які змусили її зростати, тому потрібно було розділити її на три частини. Частину третю ви можете прочитати тут.

Частина друга закінчується тут. Всі відгуки вітаються. У частині третій буде говорити про VIPER, VIP, реактивне програмування, компроміси, обмеження та контекстний сенс.

Дякую за прочитання! Якщо вам сподобалась ця стаття, будь ласка, плескайте
так що інші люди теж можуть його читати :)