VIPER-ontwerppatroon in Swift voor iOS-applicatieontwikkeling.

Alles wat een begin heeft, heeft een einde - Autama Boeddha. Afbeeldingsbron: screenshot uit de film

Ontwerppatronen zijn het geschenk van God aan softwareontwikkelaars. Dit zijn technieken die codeduplicatie minimaliseren, hoge koppeling voorkomen en een gebruikelijke manier van code schrijven standaardiseren die een algemene oplossing biedt voor terugkerende situaties tijdens het ontwikkelen van software. In dit verhaal zullen we bekend raken met een ontwerppatroon genaamd VIPER (View, Interactor, Presenter, Entity en Router.) Voor iOS-ontwikkeling.

Vereisten: zorg dat u, voordat u begint met VIPER, op de hoogte bent van het architecturale ontwerppatroon en het delegatiepatroon.

Wat is Viper?

Viper is een ontwerppatroon dat het paradigma van 'scheiding van zorgen' implementeert. Meestal zoals MVP of MVC volgt het een modulaire aanpak. Eén functie, één module. Voor elke module heeft VIPER vijf (soms vier) verschillende klassen met verschillende rollen. Geen klasse gaat verder dan zijn enige doel. Deze klassen volgen.

Beeld: Klasse die alle code heeft om de app-interface aan de gebruiker te tonen en hun antwoorden te krijgen. Na ontvangst van een reactie waarschuwt View de presentator.

Presentator: Nucleus van een module. Het krijgt gebruikersreactie van de weergave en werkt dienovereenkomstig. Alleen klasse om te communiceren met alle andere componenten. Roept de router op voor draadframing, Interactor om gegevens op te halen (netwerkoproepen of lokale gegevensoproepen), bekijken om de gebruikersinterface bij te werken.

Interactor: Heeft de bedrijfslogica van een app. Voer voornamelijk API-aanroepen uit om gegevens van een bron op te halen. Verantwoordelijk voor het maken van data-oproepen maar niet noodzakelijkerwijs van zichzelf.

Router: werkt de draadomlijsting. Luistert van de presentator over welk scherm hij moet presenteren en voert dat uit.

Entiteit: bevat gewone modelklassen die door de interactor worden gebruikt.

Hieronder ziet u een eenvoudig diagram van VIPER

Viper-architectuur

Viper met voorbeeld

Ik heb een eenvoudig project gemaakt om Adder uit te leggen. Het is te vinden op GitHub. Het is een zeer eenvoudige toepassing die een nieuwskop toont die is opgehaald van een externe API. (hoe nutteloos: p).

Viper is een door delegaties aangedreven architectuur. De meeste communicatie tussen verschillende lagen verloopt dus via delegatie. De ene laag roept een andere op via een protocol. Oproeplaag roept een functie uit een protocol op. De luisterlaag voldoet aan dat protocol en implementeert de functie.

Hieronder zal ik uitleggen hoe ik VIPER in een van mijn voorbeeldprojecten heb geïmplementeerd. Ik raad je aan om het project in github te openen en er doorheen te gaan terwijl je de uitleg leest.

protocollen

Ik heb een apart bestand gemaakt voor alle protocollen.

Een naamgevingsconventie wordt gevolgd om een ​​protocol een naam te geven. Bijvoorbeeld: 'viewToPresenterProtocol'. Het is dus een ‘protocol’ dat wordt geïmplementeerd door ‘de presentator’ om te luisteren naar wat de ‘weergave’ te zeggen heeft.

  • PresenterToViewProtocol: Presenter-oproepen, Luisteren bekijken. Presenter ontvangt een verwijzing van dit protocol voor toegang tot Weergave. Weergave voldoet aan het protocol.
  • ViewToPresenterProtocol: oproepen bekijken, presentator luistert.
  • InteractorToPresenterProtocol: Interactor-oproepen, Presenter luistert.
  • PresentorToInteractorProtocol: Presenter-aanroepen, Interactor luistert.
  • PresenterToRouterProtocol: Presenter-oproepen, router luistert.

App-stroom

Weergave heeft een verwijzing naar ‘ViewToPresenterProtocol’ voor toegang tot de ‘Presenter’ en voldoet aan ‘PresenterToViewProtocol’. In de viewDidLoad () wordt de functie updateView () van het protocol aangeroepen.

//Uitzicht
var presentator: ViewToPresenterProtocol?
vervang func viewDidLoad () {
   super.viewDidLoad ()
   presentator? .updateView ()
}

Presenter daarentegen voldoet aan ‘ViewToPresenterProtocol’. Het implementeert dus de functie updateView ().

//Presentator
var interactor: PresentorToInteractorProtocol ?;
func updateView () {
   interactor? .fetchLiveNews ()
}

Inside updateView () presentator vertelt de interactor om wat live nieuwsgegevens op te halen.

Interactor voldoet aan ‘PresentorToInteractorProtocol’. Het implementeert dus de functie fetchLiveNews (). Deze functie probeert een netwerkoproep te plaatsen en gegevens op te halen. Het heeft een referentie van ‘InteractorToPresenterProtocol’ voor toegang tot de ‘Presenter’.

// Interactor
var presentator: InteractorToPresenterProtocol?

Als de netwerkoproep de gegevens heeft opgehaald, wordt de volgende functie aangeroepen.

// Interactor
self.presenter? .liveNewsFetched (nieuws: (arrayObject? [0])!)

als niet

// Interactor
self.presenter? .liveNewsFetchedFailed ()

Presentator voldoet nu ook aan ‘InteractorToPresenterProtocol’. Het implementeert dus deze functies.

//presentator
func liveNewsFetched (nieuws: LiveNewsModel) {
        bekijk? .showNews (nieuws: nieuws);
}
func liveNewsFetchedFailed () {
        view? .showError ()
}

Dus het vertelt de weergave om nieuws te tonen of om de fout te tonen.

Nu voldoet View aan ‘PresenterToViewProtocol’. Het implementeert dus showNews () en showError (). In deze twee functies vult de weergave de weergave met de opgehaalde gegevens of de fout.

De entiteitslaag

Hierboven in de app-stroomsectie wordt entiteitslaag niet besproken. Het is niet direct verbonden met de app-stroom. Maar het is een integraal onderdeel voor de interactor. Entiteitslaag biedt een model dat interactor gebruikt om objecten te maken van de opgehaalde gegevens.

router

Router zorgt voor de draadomlijsting van een applicatie. Het veranderen van het scherm in een applicatie is een heel elementaire zaak. In VIPER is de routerlaag verantwoordelijk voor het uitvoeren daarvan.

We hebben eerder besproken dat in VIPER-architectuur elke functionaliteit een enkele module heeft en een module die vijf lagen bevat. Een presentator belt de router om een ​​nieuwe module te maken. Vervolgens start de router eerst alle lagenklasse en retourneert de module.

In mijn voorbeeldproject verandert de module niet in de app. Maar routing gebeurt wel wanneer de app voor het eerst wordt gestart. Dus binnen AppDelegate's ‘didFinishLaunchingWithOptions ()’ wordt de functie createModule () van de router genoemd. Het retourneert een module. De klasse UIWindow toont vervolgens het aanzicht van die module.

Waarom en wanneer VIPER te gebruiken

VIPER volgt een zeer schone architectuur. Het isoleert elke module van anderen. Het wijzigen of repareren van bugs is dus erg eenvoudig omdat u alleen een specifieke module hoeft bij te werken. Ook voor het hebben van een modulaire aanpak creëert VIPER een zeer goede omgeving voor het testen van eenheden. Omdat elke module onafhankelijk is van andere, blijft de koppeling zeer laag. Het verdelen van werk tussen mede-ontwikkelaars is dus vrij eenvoudig.

VIPER moet worden gebruikt wanneer de vereisten van een toepassing zeer goed zijn gevormd. Werken met voortdurend veranderende vereisten kan verwarring en verknoeide codes veroorzaken. Het mag dus niet worden gebruikt in een klein project, omdat MVP of MVC voldoende zijn. VIPER moet ook worden gebruikt als alle ontwikkelaars van het project het patroon volledig begrijpen.

VIPER-hulpmiddelen

Als je VIPER in een project wilt gebruiken, is het slimste om een ​​automatische module-structuurgenerator te gebruiken. Anders zal het maken van bestanden voor modules monotoon zijn. Er zijn maar weinig generators online beschikbaar.

  • Generamba
  • VIPER-code
  • VIPER Gen

Gevolgtrekking

Net als elk ander ontwerppatroon spreekt VIPER voor zichzelf. Je moet je handen vies maken om het hele plaatje te begrijpen. Mijn advies zal zijn om eerst te beginnen met het maken van een zeer eenvoudige app met VIPER en daarbij online bronnen te lezen. Mijn github-repo kan ook een goede referentie zijn.

Veel plezier met coderen :)

Lang leve het heilige Bangladesh.

Bangladesh is een wereld van metafoor, van hoog en laag theater, van grote poëzie en muziek. Je praat met een rijstboer en je vindt een dichter. Je leert een straatveger kennen en je vindt een opmerkelijke zanger.
Jean Houston

Referentie :

  1. https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52
  2. https://medium.com/@ankoma22/the-good-the-bad-and-the-ugly-of-viper-architecture-for-ios-apps-7272001b5347
  3. https://github.com/MindorksOpenSource/iOS-Viper-Architecture/tree/master/iOS-Viper-Architecture
  4. https://sourcemaking.com/design_patterns