Jak vybrat vhodnou architekturu iOS (část 2)

MVC, MVP, MVVM, VIPER nebo VIP

První část si můžete prohlédnout zde.

Hlavní architektury iOS

Stručný přehled.

MVC

Vrstvy MVC jsou následující:

M: Business Logic, Network Layer a Data Access Layer

V: UI Layer (UIKit věci, Storyboards, Xibs)

C: Koordinuje zprostředkování mezi modelem a pohledem.

Abychom porozuměli MVC, musíme pochopit kontext, ve kterém byl vynalezen. MVC byl vynalezen ve starých Web vývojových dnech, kdy Views nemá žádný stav. Ve starých časech pokaždé, když potřebujeme vizuální změnu na webu, prohlížeč znovu načte celý HTML znovu. V té době neexistoval koncept udržovaného a zachovaného stavu pohledu.

Existovali například někteří vývojáři, kteří se mísili ve stejném souboru HTML, PHP a přístup k databázi. Hlavní motivací MVC bylo tedy oddělení vrstvy pohledu od vrstvy modelu. Tím se zvýšila testovatelnost vrstvy modelu. Údajně v MVC by vrstva View a Model neměla o sobě vědět nic. Aby to bylo možné, byla vynalezena prostřední vrstva s názvem Controller. Byl použit SRP.

Příklad cyklu MVC:

  1. Je spuštěna uživatelská akce / událost ve vrstvě pohledu (např. Refresh Action) a tato akce je sdělena Controlleru
  2. Řadič, který žádá data do vrstvy modelu
  3. Modelování návratových dat do Controlleru
  4. Řadič říká, že pro pohled aktualizuje svůj stav novými daty
  5. Zobrazit aktualizovat jeho stav

Apple MVC

V systému iOS je View Viewler spojen s pohledem UIKit a životním cyklem, takže to není čistě MVC. V definici MVC však nelze říci, že řadič nemůže znát implementaci specifickou pro pohled nebo model. Jeho hlavním účelem je oddělit odpovědnosti za vrstvu Model od vrstvy View, abychom ji mohli znovu použít a izolovat vrstvu Model.

ViewController obsahuje pohled a vlastní model. Problém je, že jsme v ViewControlleru zapisovali kód kontroléru i kód zobrazení.

MVC často vytváří problém zvaný Massive View Controller, ale to se stává a stává se vážnou věcí v aplikacích s dostatečnou komplexností.

Existuje několik metod, které může vývojář použít k tomu, aby byl ovladač zobrazení lépe spravovatelný. Nějaké příklady:

  • Extrahování logiky VC pro jiné třídy, jako je zdroj dat metody zobrazení tabulky, a delegování pro jiné soubory pomocí návrhového vzoru delegáta.
  • Vytvořte zřetelnější oddělení odpovědností se složením (např. Rozdělte VC na řadiče podřízeného pohledu).
  • Použijte návrhový vzor koordinátora k odstranění odpovědnosti za implementaci navigační logiky ve VC
  • Použijte třídu wrapperů DataPresenter, která zapouzdřuje logiku a transformuje datový model do datového výstupu představujícího data prezentovaná koncovému uživateli.

MVC vs MVP

Jak vidíte schéma MVP je velmi podobné MVC

MVC byl o krok vpřed, ale stále se vyznačoval nepřítomností nebo mlčením o některých věcech.

Mezitím World Wide Web rostl a mnoho věcí v komunitě vývojářů se vyvinulo. Například programátoři začali používat Ajax a načítali pouze části stránek namísto celé stránky HTML najednou.

V MVC si myslím, že nic nenasvědčuje tomu, že by Controller neměl znát konkrétní implementaci View (absence).

HTML bylo součástí vrstvy View a mnoho případů bylo hloupých jako kurva. V některých případech přijímá pouze události od uživatele a zobrazuje vizuální obsah GUI.

Když se části webových stránek začaly načítat do částí, vedla tato segmentace směrem k udržování stavu zobrazení a větší potřebě oddělení logiky odpovědnosti za prezentaci.

Prezentační logika je logika, která řídí, jak by se mělo UI zobrazovat a jak prvky UI spolu interagují. Příkladem je logika řízení, kdy by se měl indikátor načítání začít zobrazovat / animovat a kdy by se měl přestat zobrazovat / animovat.

V MVP a MVVM by vrstva pohledu měla být hloupá jako kurva bez jakékoli logiky nebo inteligence v ní a v systému iOS by měl být řadič pohledu součástí vrstvy pohledu. Skutečnost, že je View hloupý, znamená, že i prezentační logika zůstává mimo vrstvu Zobrazit.

Jedním z problémů MVC je, že není jasné, kde by logika prezentace měla zůstat. O tom prostě mlčí. Měla by být logika prezentace ve vrstvě Zobrazit nebo ve vrstvě modelu?

Pokud je úlohou modelu poskytovat pouze „nezpracovaná“ data, znamená to, že kód v zobrazení by byl:

Vezměme si následující příklad: máme uživatele s křestním jménem a příjmením. V zobrazení musíme uživatelské jméno zobrazit jako „Příjmení, Křestní jméno“ (např. „Flores, Tiago“).

Pokud je úlohou modelu poskytovat „nezpracovaná“ data, znamená to, že kód v zobrazení by byl:

let firstName = userModel.getFirstName ()
let lastName = userModel.getLastName ()
nameLabel.text = lastName + „,“ + firstName

To znamená, že za zpracování logiky uživatelského rozhraní by odpovídal pohled. Ale to znemožňuje logiku uživatelského rozhraní pro testování jednotky.

Druhým přístupem je nechat Model vystavit pouze data, která je třeba zobrazit, a skrýt jakoukoli obchodní logiku z pohledu. Nakonec však skončíme s modely, které zvládají obchodní i logiku uživatelského rozhraní. Bylo by to testovatelné jednotkou, ale model nakonec skončí, implicitně je závislý na pohledu.

let name = userModel.getDisplayName ()
nameLabel.text = name

MVP je o tom jasné a logika prezentace zůstává ve vrstvě Presenter. To zvyšuje testovatelnost vrstvy Presenter. Nyní jsou snadno testovatelná vrstva Model a Presenter.

V implementacích MVP je zobrazení skryto za rozhraním / protokolem a v prezentátoru by neměly být žádné odkazy na UIKit.

Další věcí, kterou je třeba mít na paměti, jsou tranzitivní závislosti.

Pokud má Controller jako vrstvu závislost Business Layer a Business Layer má jako závislost vrstvu Data Access Layer, pak má Controller přechodnou závislost pro vrstvu Data Access Layer. Protože implementace MVP běžně používají smlouvu (protokol) mezi všemi vrstvami, nemá přechodné závislosti.

Různé vrstvy se také mění z různých důvodů a různou rychlostí. Takže když změníte vrstvu, nechcete, aby to způsobovalo sekundární efekty / problémy v ostatních vrstvách.

Protokoly jsou stabilnější než třídy. Protokoly neobsahují podrobnosti o implementaci a se smlouvami, takže je možné změnit podrobnosti o implementaci vrstvy bez ovlivnění ostatních vrstev.

Proto smlouvy (protokoly) vytvářejí oddělení mezi vrstvami.

MVP vs MVVM

MVVM diagram

Jedním z hlavních rozdílů mezi MVP a MVVM je to, že v MVP Presenter komunikuje s rozhraním Zobrazit prostřednictvím rozhraní a v MVVM je Pohled orientován na změny dat a událostí.

V MVP vytváříme ruční vazby mezi Presenter a View pomocí rozhraní / protokolů.
V MVVM provádíme automatické vázání dat pomocí něco jako RxSwift, KVO nebo používáme mechanismus s generiky a uzávěry.

V MVVM nepotřebujeme ani smlouvu (např. Java rozhraní / protokol iOS) mezi ViewModel a View, protože obvykle komunikujeme prostřednictvím vzorového vzoru pozorovatele.

MVP používá vzor delegátů, protože vrstva Presenter Layer deleguje objednávky do vrstvy pohledu, takže potřebuje něco vědět o pohledu, i když se jedná pouze o podpis rozhraní / protokolu. Přemýšlejte o rozdílu mezi Centrem oznámení a delegáty TableView. Centrum oznámení nepotřebuje rozhraní k vytvoření komunikačního kanálu, ale delegáti TableView používají protokol, který by třídy měly implementovat.

Přemýšlejte o prezentační logice indikátoru zatížení. V MVP předvádí moderátor ViewProtocol.showLoadingIndicator. V MVVM může být v ViewModel vlastnost isLoading. Vrstva Zobrazit prostřednictvím automatické vazby dat zjistí, když se tato vlastnost změní a obnoví sama. MVP je naléhavější než MVVM, protože předvádějící dává příkazy.

MVVM je více o změnách dat než o přímých objednávkách a provádíme asociace mezi změnami dat a aktualizacemi zobrazení. Pokud použijeme RxSwift a funkční reaktivní programovací paradigma společně s MVVM, kód jsme učinili ještě méně imperativnější a deklarativnější.

Testování MVVM je snazší než testování MVP, protože MVVM používá návrhový vzor pozorovatele, který přenáší data mezi komponenty odděleným způsobem.
Můžeme tedy otestovat pouhým pohledem na změny v datech pouhým porovnáním těchto dvou objektů, namísto vytváření falešných metod, které volání metod otestuje komunikaci mezi View a Presenter.

PS: Udělal jsem několik aktualizací článku, díky kterému se hodně rozrostl, takže bylo nutné jej rozdělit na tři části. Zde si můžete přečíst třetí část.

Část druhá zde končí. Veškerá zpětná vazba je vítána. Třetí část bude hovořit o VIPER, VIP, reaktivním programování, kompromisech, omezeních a kontextuálním smyslu.

Děkuji za přečtení! Pokud se vám tento článek líbil, tleskejte
aby si to mohli přečíst i další lidé :)