Kaip pasirinkti tinkamą „iOS“ architektūrą (2 dalis)

MVC, MVP, MVVM, VIPER ar VIP

Su pirmąja dalimi galite susipažinti čia.

Pagrindinės „iOS“ architektūros

Trumpa apžvalga.

MVC

MVC sluoksniai yra šie:

M: Verslo logika, tinklo sluoksnis ir duomenų prieigos sluoksnis

V: UI sluoksnis (UIKit dalykai, siužetinės lentos, Xibs)

C: Koordinuoja tarpininkavimą tarp modelio ir vaizdo.

Norėdami suprasti MVC, turime suprasti kontekstą, kuriame jis buvo išrastas. MVC buvo išrastas senosiomis interneto kūrimo dienomis, kai „Views“ neturėjo valstybės. Senovėje kiekvieną kartą, kai reikia vizualiai pakeisti svetainę, naršyklė vėl įkelia visą HTML. Tuo metu nebuvo koncepcijos, kad vaizdas turėtų būti išlaikytas ir išsaugotas.

Pavyzdžiui, buvo keletas kūrėjų, kurie maišėsi tame pačiame HTML faile, PHP ir duomenų bazių prieigose. Taigi pagrindinė MVC motyvacija buvo atskirti „View“ ir „Model“ sluoksnius. Tai padidino modelio sluoksnio išbandomumą. Spėjama, kad MVC sluoksnis „Peržiūra“ ir „modelis“ neturėtų nieko žinoti apie vienas kitą. Kad tai būtų įmanoma, buvo išrastas tarpinis sluoksnis pavadinimu „Controller“. Tai buvo taikoma SRP.

MVC ciklo pavyzdys:

  1. Vartotojo veiksmas / įvykis peržiūros sluoksnyje (pvz .: Atnaujinti veiksmą) suaktyvinamas ir tas veiksmas perduodamas valdytojui
  2. Valdiklis, kuris prašo duomenų į modelio sluoksnį
  3. Modelio pagalba grąžina duomenis valdikliui
  4. Valdiklis sako, kad „View“ atnaujina savo būseną naujais duomenimis
  5. Peržiūrėti atnaujinti jo būseną

„Apple MVC“

„IOS“ rodinio valdiklis yra sujungtas su UIKit ir gyvavimo ciklo rodiniu, todėl tai nėra grynas MVC. Tačiau MVC apibrėžime nėra nieko, kas pasakytų, kad valdiklis negali žinoti konkretaus rodinio ar modelio diegimo. Jo pagrindinis tikslas yra atskirti modelio sluoksnį nuo peržiūros sluoksnio, kad galėtume jį naudoti pakartotinai ir išbandyti modelio sluoksnį atskirai.

„ViewController“ yra „View“ ir „Model“ savininkas. Problema ta, kad mes įpratome valdiklio kodą, taip pat rodinio kodą rašyti „ViewController“.

MVC dažnai sukuria vadinamąją masinio vaizdo valdiklio problemą, tačiau tai atsitinka ir tampa rimtu dalyku pakankamai sudėtingose ​​programose.

Yra keletas metodų, kuriuos kūrėjas gali naudoti, kad rodinių valdiklį būtų lengviau valdyti. Keletas pavyzdžių:

  • Ištraukite VC logiką kitoms klasėms, pavyzdžiui, lentelės peržiūros metodo duomenų šaltiniui, ir deleguokite kitiems failams, naudodami deleguotojo projektavimo modelį.
  • Sukurkite aiškesnį atsakomybės atskyrimą su kompozicija (pvz., Padalinkite rizikos vertinimą į vaikų peržiūros valdiklius).
  • Norėdami pašalinti atsakomybę už navigacijos logikos diegimą VC, naudokite koordinatoriaus dizaino modelį
  • Naudokite „DataPresenter“ apklotatoriaus klasę, kurioje aprašoma logika ir duomenų modelis paverčiamas duomenų išvestimi, atspindinčia duomenis, pateiktus galutiniam vartotojui.

MVC vs MVP

Kaip matote MVP schemą, labai panašu į MVC

MVC buvo žingsnis į priekį, tačiau jį vis tiek ženklino kai kurių dalykų nebuvimas ar tylėjimas.

Tuo tarpu populiarėjo žiniatinklis ir vystėsi daugybė dalykų kūrėjų bendruomenėje. Pavyzdžiui, programuotojai pradėjo naudoti „Ajax“ ir įkelti tik puslapių dalis, o ne visą HTML puslapį iš karto.

Manau, kad MVC nėra nieko, kas reikštų, kad kontrolierius neturėtų žinoti konkretaus „View“ (nebuvimo) diegimo.

HTML buvo „View“ sluoksnio dalis ir daugelis atvejų buvo nesąmoningi. Kai kuriais atvejais ji gauna tik įvykius iš vartotojo ir rodo vaizdinį GUI turinį.

Kai tinklalapių dalys buvo pradėtos krauti į dalis, šis segmentavimas leido išlaikyti rodinio būseną ir atsirado didesnis poreikis atskirti pateikimo logikos atsakomybę.

Pristatymo logika yra logika, valdanti, kaip turėtų būti rodoma vartotojo sąsaja ir kaip sąsajos elementai sąveikauja. Pavyzdys yra valdymo logika, kada pakrovimo indikatorius turėtų pradėti rodyti / animuoti, o kada jis turėtų nustoti rodyti / animuoti.

MVP ir MVVM rodinio sluoksnis turėtų būti niūrus kaip šūdas be jokios logikos ar intelekto, o „iOS“ - rodinių valdiklis turėtų būti rodinio sluoksnio dalis. Tai, kad „View“ yra kvailas, reiškia, kad net pateikimo logika nepatenka į „View“ sluoksnį.

Viena iš MVC problemų yra ta, kad neaišku, kur turėtų likti pateikimo logika. Apie tai jis tiesiog tyli. Ar pateikimo logika turėtų būti rodinio sluoksnyje arba modelio sluoksnyje?

Jei modelio vaidmuo yra tiesiog pateikti „neapdorotus“ duomenis, tai reiškia, kad rodinyje kodas bus:

Apsvarstykite šį pavyzdį: mes turime vartotoją su vardu ir pavarde. Rodinyje turime parodyti vartotojo vardą kaip „Pavardė, vardas“ (pvz., „Flores, Tiago“).

Jei modelio vaidmuo yra pateikti „neapdorotus“ duomenis, tai reiškia, kad rodinyje esantis kodas būtų:

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

Taigi tai reiškia, kad UI logikos tvarkymas bus „View“ pareiga. Bet dėl ​​to neįmanoma UI logikos patikrinti.

Kitas būdas yra tas, kad modelis atskleidžia tik tuos duomenis, kuriuos reikia parodyti, paslėpdamas bet kokią verslo logiką iš rodinio. Bet tada mes baigsime modeliais, kurie tvarko tiek verslo, tiek vartotojo sąsajos logiką. Tai būtų patikrinta vienetu, tačiau tada modelis baigiasi, netiesiogiai priklausydamas nuo Vaizdo.

tegul vardas = userModel.getDisplayName ()
nameLabel.text = vardas

MVP aiškiai supranta, kad pristatymo logika lieka „Presenter Layer“. Tai padidina „Presenter“ sluoksnio išbandomumą. Dabar „Model“ ir „Presenter Layer“ yra lengvai išbandomos.

Paprastai MVP diegimuose rodinys yra paslėptas už sąsajos / protokolo ir prezenteryje neturėtų būti nuorodų į UIKit.

Kitas dalykas, kurį reikia atsiminti, yra priklausomybės nuo pereinamojo laikotarpio.

Jei valdytojas turi verslo sluoksnį kaip priklausomybę, o verslo sluoksnis turi duomenų prieigos sluoksnį kaip priklausomybę, tada valdytojas turi pereinamąją duomenų prieigos sluoksnio priklausomybę. Kadangi MVP diegimai paprastai naudoja sutartį (protokolą) tarp visų sluoksnių, tai neturi pereinamųjų priklausomybių.

Skirtingi sluoksniai taip pat keičiasi dėl skirtingų priežasčių ir skirtingais tempais. Taigi, kai keičiate sluoksnį, nenorite, kad tai sukeltų antrinius efektus / problemas kituose sluoksniuose.

Protokolai yra stabilesni nei klasės. Protokoluose nėra išsamios informacijos apie įgyvendinimą ir sutarčių, todėl galima pakeisti informacijos apie sluoksnio įgyvendinimą nepaveikiant kitų sluoksnių.

Taigi sutartys (protokolai) sukuria atsiejimą tarp sluoksnių.

MVP vs MVVM

MVVM schema

Vienas pagrindinių skirtumų tarp MVP ir MVVM yra tas, kad MVP pateikėjas komunikuoja su vaizdu per sąsajas, o MVVM rodinys yra orientuotas į duomenų ir įvykių pokyčius.

Naudodami sąsajas / protokolus, MVP rankiniu būdu įpareigojame pateikėją ir rodinį.
MVVM automatinį duomenų įrišimą padarome naudodami kažką panašaus į „RxSwift“, KVO arba naudodamiesi mechanizmu su generiniais vaistais ir uždarymais.

MVVM mums net nereikia sutarties (pvz .: „Java“ sąsaja / „iOS“ protokolas) tarp „ViewModel“ ir „View“, nes paprastai mes bendraujame naudodamiesi „Observer Design Pattern“.

MVP naudoja Delegavimo modelį, nes „Presenter Layer“ deleguoja užsakymus peržiūros sluoksniui, todėl jis turi ką nors žinoti apie rodinį, net jei tai yra tik sąsajos / protokolo parašas. Pagalvokite apie skirtumą tarp pranešimų centro ir „TableView“ delegatų. Pranešimų centrui nereikia sąsajų, kad būtų galima sukurti komunikacijos kanalą, tačiau „TableView Delegates“ naudoja protokolą, kurį klasės turėtų įgyvendinti.

Pagalvokite apie krovimo indikatoriaus pateikimo logiką. MVP metu vedėjas atlieka „ViewProtocol.showLoadingIndicator“. „MVVM“ „ViewModel“ gali būti „isLoading“ savybė. „View“ sluoksnis per automatinį duomenų įrišimą nustato, kada ši savybė pasikeičia ir atnaujinama. MVP yra labiau būtinas nei MVVM, nes pranešėjas duoda nurodymus.

MVVM yra daugiau susijęs su duomenų pakeitimais nei tiesioginiais užsakymais, todėl mes susiejame duomenų pakeitimus ir peržiūrime atnaujinimus. Jei kartu su MVVM naudosime „RxSwift“ ir funkcinio reaktyviojo programavimo paradigmas, kodą padarėme dar mažiau imperatyvų ir deklaratyvesnį.

MVVM yra lengviau išbandyti nei MVP, nes MVVM naudoja „Observer Design Pattern“, kuris perduoda duomenis tarp komponentų atsietai.
Taigi mes galime išbandyti tik pažvelgę ​​į duomenų pokyčius, palygindami du objektus, o ne sukurdami pasityčiojimus iš metodų skambučių, norėdami išbandyti ryšį tarp „View“ ir „Presenter“.

PS: Aš šiek tiek atnaujinau straipsnį, kuris privertė jį daug augti, todėl reikėjo jį padalyti į tris dalis. Trečią dalį galite perskaityti čia.

Čia baigiasi antra dalis. Visi atsiliepimai laukiami. Trečiojoje dalyje bus kalbama apie VIPER, VIP, reaktyvųjį programavimą, kompromisus, suvaržymus ir kontekstinį pojūtį.

Ačiū, kad skaitėte! Jei jums patiko šis straipsnis, prašome apkabinti
Other kad kiti žmonės taip pat galėtų tai perskaityti :)