Varför MVC kanske inte är det bästa mönstret för kakaoapplikationer

MVC står för Model-View-Controller, och det är ett utbrett arkitektoniskt mönster för mjukvaruutveckling. Det är de facto designmönstret för kakaoutveckling, och det har varit i många år. De flesta av oss kan inte föreställa oss att bygga applikationer utan det. Både UIKit (iOS) och AppKit(macOS) gör ofta användning av MVC. Det verkar nästan som om vi inte har ett annat alternativ att bygga program för iOS, tvOS, macOS och watchOS.

Även om du inte känner till modell-View-Controller-mönstret, om du har ambitionen att utveckla applikationer för en av Apples plattformar, behöver du lära dig hur synpunkter (iOS) och windows (macOS) relaterar till controllers och vilken roll modell spelar i en typisk kakao ansökan. Lyckligtvis är MVC lätt att lära sig.

I den här korta serien förklarar jag vad MVC är, hur det ser ut i en typisk Cocoa-applikation, och varför det kanske inte är den bästa lösningen för kakaoutvecklare.

1. Ett exempel

Låt mig visa dig hur MVC-mönstret ser ut i en typisk Cocoa-applikation. Exemplet jag visar dig fokuserar på iOS, men allt vi diskuterar gäller även tvOS, macOS och watchOS. Öppna Xcode och skapa ett nytt iOS projekt baserat på Enkel visningsprogram mall.

Namn på projektet MVC, och ställa in Språk till Snabb och enheter till iPhone. Jag använder Xcode 8 för denna handledning. Projektets konfigurationsalternativ kan se lite annorlunda om du använder Xcode 9.

Som namnet antyder definierar modell-View-Controller-mönstret tre komponenter, modell, de se, och den kontrollant. Låt mig visa dig var du kan hitta dessa komponenter i ett typiskt iOS-projekt.

controllers

Styrenheterna i en iOS-applikation är visningsstyrare, instanser av UIViewController klass eller en underklass därav. De UIViewController klassen definieras i UIKit ramverk. Eftersom vi valde Enkel visningsprogram mall när vi satt upp projektet, skapade Xcode en kontroller för oss att börja med, ViewController klass, definierad i ViewController.Swift. Det ärar från UIViewController klass.

Som namnet antyder, a UIViewController Instans ansvarar för att styra en vy, en instans av UIView klass. Varje bildkontroll i ett iOS-projekt håller en stark referens till en vy, en annan komponent i modell-View-Controller-mönstret. De UIView klassen definieras också i UIKit ramverk.

Visningar

Vi kan hitta visningskomponenten i projektets huvudsakliga storyboard. Öppna Main.storyboard i Project Navigator till vänster och inspektera Visa kontrollerplats. Scenen innehåller en kontroller, en instans av ViewController klass, och det hanterar a UIView exempel.

Välj Se i storyboarden till vänster och öppna Identitetsinspektör till höger. De Klass Fältet för vyn är inställt på UIView. I en iOS-applikation är visningar typiskt exempel på UIKit UIView klass eller en underklass därav.

modeller

Hittills har vi utforskat kontrollerlagret och visningsskiktet. Men var kan vi hitta modellskiktet av projektet? Modellen är nästan alltid specifik för det projekt du arbetar på, och det är upp till dig att definiera, implementera och använda projektets modell. jag skriver modell, men du brukar ha flera modeller, beroende på projektets komplexitet.

Låt oss lägga till den sista delen av MVC-pusslet genom att skapa en modell. Skapa en ny Swift-fil och namnge den Person.swift.

Välj Person.swift i Project Navigator till vänster och definiera en struktur som heter Person. Vi definierar tre egenskaper: 

  • förnamn av typ Sträng
  • efternamn av typ Sträng
  • ålder av typ int
struct Person let firstName: String let lastName: String let age: Int

Du har nu en modell som du kan använda i ditt projekt. Låt oss hålla det enkelt och definiera en egendom, person, av typ Person? i ViewController klass. Vi skapar en Person instans i visningskontrollerns viewDidLoad () metod och tilldela den till person fast egendom.

importera UIKit klass ViewController: UIViewController // MARK: - Egenskaper var person: Person? // MARK: - Visa livscyklusöverstyrning func viewDidLoad () super.viewDidLoad () // Skapa person person = Person (förnamn: "John", efternamn: "Doe", ålder: 40)

Det vi ser i detta exempel är mycket vanligt i kakaoapplikationer som drivs av modell-View-Controller-mönstret. Utsiktskontrollen äger och hanterar modellen, och den använder modellen för att fylla sin syn. I en mer komplex applikation laddar du modellens data från en bestående butik eller hämtar den från en bakre bakre ände.

Låt oss definiera ett uttag för a UILabel instans i vykontrollen och, i huvudhistorikbrädet, lägg till en etikett till Visa kontrollerplats.

importera UIKit klass ViewController: UIViewController // MARK: - Egenskaper @IBOutlet var etikett: UILabel! ...

I visningsregulatorens viewDidLoad () metod, säkra vi säkert det värde som lagrats i person egendom och använd dess data för att ställa in text egenskapen hos UILabel exempel.

åsidosätta func viewDidLoad () super.viewDidLoad () // Skapa person person = Person (firstName: "John", efternamn: "Doe", ålder: 40) // Populär etikett om let person = person label.text = " \ (person.lastName), \ (person.firstName) (\ (person.age)) "

Resultatet är inte särskilt överraskande om du känner till kakaoutveckling. Så här slutar vi med.

2. Vad är Model View-Controller?

Model-View-Controller-mönstret är lätt att förstå och plocka upp. Trots sin enkelhet kan du hitta ett brett utbud av smaker av MVC-mönstret. MVC erbjuder bara en grundläggande ritning som kan ändras till plattformen den används på. 

Model-View-Controller-mönstret du känner till på iOS, tvOS, macOS och watchOS skiljer sig på subtila sätt från den ursprungliga definitionen. Medan skillnaderna jämfört med den ursprungliga definitionen är subtila, har de en signifikant inverkan på koden du skriver såväl som om projektets underhåll kan hållas.

Småprat

Modell-View-Controller mönstret är ett gammalt designmönster. Det gjorde sitt första utseende på 1970-talet i Smalltalk. Mönstret var tänkt av Trygve Reenskaug. Genom åren har Model-View-Controller-mönstret tagit sig in i många språk och ramar, inklusive Java, Rails och Django.

Jag nämnde tidigare att MVC-mönstret bryter programmen upp i tre olika komponenter: modell, se, och kontrollant. Den ursprungliga implementeringen av mönstret definierar att vyn är ansvarig för att visa modellens data för användaren. Användaren interagerar med applikationen genom visningsskiktet. Kontrollenheten ansvarar för hanteringen av användarinteraktion och manipulerar modellens data som ett resultat. Vyn visualiserar dessa ändringar för användaren. Som framgår av diagrammet nedan spelar modellen en nyckelroll i MVC-mönstret, som det utformades av Reenskaug.

MVC och kakao

Den implementering vi använder i kakaoutveckling skiljer sig från Reenskaugs ursprungliga design. Ta en titt på nedanstående diagram för att bättre förstå vad dessa skillnader medför.

Som jag nämnde tidigare delar utsikten och kontrollenheten en nära relation. I en typisk iOS-applikation har en kontroller en stark referens till den vy det hanterar. Vyn är ett dumt objekt som vet hur man visar data och svarar på användarens interaktion. Resultatet är en mycket återanvändbar komponent.

Styrenheten spelar en viktig roll i kakaoapplikationer som drivs av modell-View-Controller-mönstret. Det tar över några av modellens uppgifter i Reenskaugs ursprungliga MVC-implementering. Utsikten och modellen kommunicerar inte direkt med varandra. Istället ägs modellen vanligtvis av den registeransvarige, som den använder för att konfigurera och fylla i den vy det hanterar.

Jag hoppas att du kan se de subtila skillnaderna mellan Reenskaugs ursprungliga genomförande i Smalltalk och Kakaoproduktionen vi har blivit vana vid. Skillnaderna är små, men som jag kommer att diskutera i ett ögonblick, är den effekt de har är viktig.

3. The Good: Separation of Concerns and Reusability

Innan vi tittar på problemen MVC introducerar, skulle jag vilja visa dig varför modell-View-Controller-mönstret har blivit ett så populärt och utbrett mönster i mjukvaruutveckling. Model-View-Controller-mönstret vi använder i kakaoutveckling har ett antal tydliga fördelar som det ärat från Reenskaugs ursprungliga genomförande.

Den mest uppenbara fördelen med modell-View-Controller mönstret är a dela upp problemen. Visningsskiktet är till exempel ansvarigt för att presentera data för användaren. Modell- och kontrolllagren är inte oroade för datapresentation. Men om du har använt MVC i ett Kakao-projekt, vet du att det inte alltid är sant. Jag pratar mer om det på ett ögonblick.

En direkt fördel med denna uppdelning av problem är återanvändbarhet. Var och en av komponenterna i modell-View-Controller mönstret är inriktad på en specifik uppgift, vilket innebär att byggnadsblocken i en MVC-applikation ofta är lätta att återanvända. Det möjliggör också att dessa komponenter är löst kopplade, vilket ökar deras återanvändbarhet. Detta gäller dock inte för varje komponent. I ett kakaoprojekt är exempelvis kontroller ofta specifika för ansökan och inte bra kandidater för återanvändning.

Utsikten och modellerna för ett projekt är emellertid mycket återanvändbara om de är utformade korrekt. Tabell- och samlingsvyer är till exempel UIView underklasser som används i miljontals applikationer. Eftersom en tabellvy delegerar användarinteraktion till ett annat objekt och frågar en datakälla för de uppgifter som den behöver visas kan den fokusera uteslutande på datapresentation och användarinteraktion.

4. De dåliga: Massiva kontrollerna

De flesta utvecklare tar snabbt hänsyn till vad modell-View-Controller-mönstret tar med bordet och hur det ska implementeras. Tyvärr har modell-View-Controller mönstret också en ful sida. Jag skrev redan om återanvändning och separation av problem. Jag är säker på att jag inte behöver övertyga dig om dessa fördelar. En tabellvy är mycket återanvändbar och otroligt effektiv. Utvecklare kan använda vanliga UIKit-komponenter i sina applikationer utan att behöva subklassificeras eller anpassas.

Slår gränserna för MVC

Men det är bara en del av historien. Du vet när du börjar träffa gränserna för MVC när massiva kontrollerare har smugit in i ditt projekt. Det är dags för förändring när du plogar igenom hundratals eller tusentals linjer kod för att hitta den metod du letar efter. 

Dumpning i kontrollenheten

De flesta utvecklare vet vad som går in i visningen och modelllagret i en typisk Cocoa-applikation som drivs av modell-View-Controller-mönstret. Men vilken komponent ansvarar för att formatera data som visas för användaren? Kom ihåg att åsikter ska vara dumma och återanvändbara. Vyn ska inte behöva formatera data. Höger? Den bör bara veta hur man presenterar data och svarar på användarens interaktion. Skulle modellen vara orolig för dataformatering?

Och vad sägs om nätverk? Det är verkligen inte uppgiften att se. Ska det delegeras till modellen? Det låter inte rätt. Varför slipper vi inte den delkoden i regulatorn. Det känns inte rätt, men det kommer att göra för nu.

Efter många linjer med kod slutar du med en kontroller som är redo att brista och en mardröm att testa. Testning? Jag hör dig. Jag skulle inte vilja testa en kontrollenhet som lider av massiv kontroller syndromet antingen.

5. En bättre lösning

Du började med goda intentioner, men du slutade med ett projekt som har en samling överviktiga kontroller som är svåra att hantera och underhålla. Du ser inte fram emot att lägga till nya funktioner för det projekt du jobbar med, eftersom du öppnar upp de här kontrollerna gör att du är sjuk i magen. Lyder detta bekant?

Det är viktigt att inse att detta är ett vanligt scenario. Många utvecklare drabbade gränserna för Model-View-Controller-mönstret och inser att de behöver något bättre. Chansen är att du redan har tittat på flera alternativ, till exempel MVP (Model-View-Presenter) eller MVVM (Model-View-Viewmodel).

I nästa del av denna serie zoomar jag in på Model-View-Viewmodel mönster. Det känns känt bekant om du redan har arbetat med modell-View-Controller-mönstret. Men modell-View-ViewModel-mönstret ger några förbättringar till bordet som fungerar väldigt bra för kakaoutveckling.

Och medan du väntar, kolla in några av våra andra inlägg på Cocoa app utveckling!