Perché MVC potrebbe non essere il modello migliore per le app Cocoa

MVC sta per Model-View-Controller, ed è un modello architettonico diffuso per lo sviluppo del software. È il modello di design de facto per lo sviluppo del cacao, ed è stato per molti, molti anni. La maggior parte di noi non può immaginare di costruire applicazioni senza di essa. Sia UIKit (iOS) che AppKit(macOS) fare uso frequente di MVC. Sembra quasi che non abbiamo un'altra opzione per creare applicazioni per iOS, tvOS, macOS e watchOS.

Anche se non hai familiarità con il modello Model-View-Controller, se hai l'ambizione di sviluppare applicazioni per una delle piattaforme Apple, devi imparare come le viste (iOS) e windows (macOS) si riferiscono ai controller e quale ruolo il il modello suona in una tipica applicazione Cocoa. Fortunatamente, MVC è facile da imparare.

In questa breve serie, spiego cosa è MVC, come appare in una tipica applicazione Cocoa e perché potrebbe non essere la soluzione migliore per gli sviluppatori di Cocoa.

1. Un esempio

Lascia che ti mostri come appare il pattern MVC in una tipica applicazione Cocoa. L'esempio che ti mostrerò si concentra su iOS, ma tutto ciò che discutiamo vale anche per tvOS, macOS e watchOS. Apri Xcode e creane uno nuovo iOS progetto basato sul Applicazione vista singola modello.

Assegna un nome al progetto MVC, e impostare linguaggio a veloce e dispositivi a i phone. Sto usando Xcode 8 per questo tutorial. Le opzioni di configurazione del progetto potrebbero sembrare un po 'diverse se stai usando Xcode 9.

Come suggerisce il nome, il modello Model-View-Controller definisce tre componenti, il modello, il vista, e il controllore. Lascia che ti mostri dove puoi trovare questi componenti in un tipico progetto iOS.

Controller

I controller di un'applicazione iOS sono controller di visualizzazione, istanze di UIViewController classe o una sua sottoclasse. Il UIViewController la classe è definita nel UIKit struttura. Perché abbiamo scelto il Applicazione vista singola modello quando abbiamo impostato il progetto, Xcode ha creato un controller per noi con cui iniziare ViewController classe, definita in ViewController.Swift. Eredita dal UIViewController classe.

Come suggerisce il nome, a UIViewController l'istanza è responsabile del controllo di una vista, un'istanza di UIView classe. Ogni controller di vista in un progetto iOS mantiene un forte riferimento a una vista, un altro componente del modello Model-View-Controller. Il UIView la classe è anche definita nel UIKit struttura.

Visualizzazioni

Possiamo trovare il componente di visualizzazione nello storyboard principale del progetto. Aperto Main.storyboard nel Project Navigator a sinistra e ispezionare il Visualizza scena controller. La scena contiene un controller di visualizzazione, un'istanza di ViewController classe, e gestisce a UIView esempio.

Selezionare vista nello storyboard a sinistra e apri il Identity Inspector sulla destra. Il Classe il campo della vista è impostato su UIView. In un'applicazione iOS, le viste sono in genere istanze di UIKit UIView classe o una sua sottoclasse.

Modelli

Finora abbiamo esplorato il livello controller e il livello vista. Ma dove possiamo trovare il modello del progetto? Il modello è quasi sempre specifico per il progetto su cui stai lavorando e spetta a te definire, implementare e utilizzare il modello del progetto. Scrivo io modello, ma di solito hai più modelli, a seconda della complessità del tuo progetto.

Aggiungiamo il pezzo finale del puzzle MVC creando un modello. Crea un nuovo file Swift e chiamalo Person.swift.

Selezionare Person.swift nel Project Navigator a sinistra e definire una struttura denominata Persona. Definiamo tre proprietà: 

  • nome di battesimo di tipo Stringa
  • cognome di tipo Stringa
  • età di tipo Int
struct Person let firstName: String let lastName: String let age: Int

Ora hai un modello che puoi usare nel tuo progetto. Manteniamolo semplice e definire una proprietà, persona, di tipo Persona? nel ViewController classe. Creiamo a Persona istanza nel controller della vista viewDidLoad () metodo e assegnarlo al persona proprietà.

importare la classe UIKit ViewController: UIViewController // MARK: - Properties var person: Person? // MARK: - Visualizza Life Cycle Override func viewDidLoad () super.viewDidLoad () // Crea Person person = Person (firstName: "John", lastName: "Doe", età: 40)

Quello che vediamo in questo esempio è molto comune nelle applicazioni Cocoa basate sul modello Model-View-Controller. Il controller della vista possiede e gestisce il modello e utilizza il modello per popolare la sua vista. In un'applicazione più complessa, si caricano i dati del modello da un archivio persistente o lo si preleva da un back-end remoto.

Definiamo uno sbocco per a UILabel istanza nel controller della vista e, nello storyboard principale, aggiungere un'etichetta al Visualizza scena controller.

importare la classe UIKit ViewController: UIViewController // MARK: - Proprietà @IBOutlet label var: UILabel! ...

Nel controller della vista viewDidLoad () metodo, scartiamo in modo sicuro il valore memorizzato nel file persona proprietà e utilizzare i suoi dati per impostare il testo proprietà del UILabel esempio.

override func viewDidLoad () super.viewDidLoad () // Crea persona persona = Persona (firstName: "John", lastName: "Doe", età: 40) // Popola etichetta se let person = person label.text = " \ (person.lastName), \ (person.firstName) (\ (person.age)) "

Il risultato non è molto sorprendente se hai familiarità con lo sviluppo di Cocoa. Questo è ciò con cui finiamo.

2. Che cos'è Model-View-Controller?

Il pattern Model-View-Controller è facile da capire e da raccogliere. Nonostante la sua semplicità, puoi trovare un'ampia gamma di sapori del pattern MVC. MVC offre solo un progetto base che può essere modificato sulla piattaforma su cui è utilizzato. 

Il pattern Model-View-Controller con cui hai familiarità su iOS, tvOS, macOS e watchOS differisce in modo sottile dalla definizione originale. Sebbene le differenze rispetto alla definizione originale siano sottili, hanno un impatto significativo sul codice che scrivi e sulla manutenibilità del progetto.

Smalltalk

Il modello Model-View-Controller è un vecchio modello di progettazione. Ha fatto la sua prima apparizione negli anni '70 in Smalltalk. Il modello è stato concepito da Trygve Reenskaug. Nel corso degli anni, il modello Model-View-Controller si è fatto strada in molti linguaggi e framework, inclusi Java, Rails e Django.

Ho accennato in precedenza che il pattern MVC suddivide le applicazioni in tre componenti distinte: modello, vista, e controllore. L'implementazione originale del pattern definisce che la vista è responsabile della visualizzazione dei dati del modello all'utente. L'utente interagisce con l'applicazione attraverso il livello di vista. Il controller è incaricato di gestire l'interazione dell'utente e di manipolare i dati del modello come risultato. La vista visualizza queste modifiche all'utente. Come illustrato nel diagramma sottostante, il modello gioca un ruolo chiave nel modello MVC così come è stato progettato da Reenskaug.

MVC e cacao

L'implementazione che utilizziamo nello sviluppo di Cocoa differisce dal design originale di Reenskaug. Dai uno sguardo al diagramma sottostante per capire meglio che cosa comportano queste differenze.

Come ho detto prima, la vista e il controller condividono una stretta relazione. In una tipica applicazione iOS, un controller mantiene un forte riferimento alla vista che gestisce. La vista è un oggetto stupido che sa come visualizzare i dati e rispondere all'interazione dell'utente. Il risultato è un componente altamente riutilizzabile.

Il controller svolge un ruolo fondamentale nelle applicazioni Cocoa basate sul modello Model-View-Controller. Prende in carico alcune delle attività del modello nell'implementazione MVC originale di Reenskaug. La vista e il modello non comunicano direttamente tra loro. Invece, il modello è solitamente di proprietà del controllore, che utilizza per configurare e popolare la vista che gestisce.

Spero che tu possa vedere le sottili differenze tra l'implementazione originale di Reenskaug in Smalltalk e l'implementazione Cocoa a cui siamo abituati. Le differenze sono minori, ma, come discuterò tra un momento, l'impatto che hanno è importante.

3. Il bene: separazione delle preoccupazioni e riusabilità

Prima di dare un'occhiata ai problemi introdotti da MVC, vorrei mostrarvi perché il pattern Model-View-Controller è diventato un modello così diffuso e diffuso nello sviluppo di software. Il pattern Model-View-Controller che utilizziamo nello sviluppo di Cocoa ha una serie di chiari vantaggi ereditati dall'implementazione originale di Reenskaug.

Il vantaggio più ovvio del modello Model-View-Controller è a separazione degli interessi. Il livello di vista, ad esempio, è responsabile della presentazione dei dati all'utente. I livelli del modello e del controller non sono interessati alla presentazione dei dati. Ma se stai usando MVC in un progetto Cocoa, allora sai che questo non è sempre vero. Ne parlerò di più in un momento.

Un beneficio diretto di questa separazione di preoccupazioni è riutilizzabilità. Ciascuno dei componenti del modello Model-View-Controller è focalizzato su un'attività specifica, il che significa che i blocchi costitutivi di un'applicazione MVC sono spesso facili da riutilizzare. Consente inoltre di accoppiare liberamente questi componenti, aumentandone la riusabilità. Questo non è vero per ogni componente, però. In un progetto Cocoa, ad esempio, i controllori sono spesso specifici dell'applicazione e non i buoni candidati per il riutilizzo.

Le viste e i modelli di un progetto, tuttavia, sono altamente riutilizzabili se progettati correttamente. Le visualizzazioni di tabelle e raccolte, ad esempio, sono UIView sottoclassi utilizzate in milioni di applicazioni. Poiché una vista tabella delega l'interazione dell'utente con un altro oggetto e richiede un'origine dati per i dati che deve visualizzare, può concentrarsi esclusivamente sulla presentazione dei dati e sull'interazione dell'utente.

4. The Bad: Massive View Controller

La maggior parte degli sviluppatori coglie rapidamente ciò che il modello Model-View-Controller porta in tavola e come dovrebbe essere implementato. Sfortunatamente, anche il pattern Model-View-Controller ha un lato brutto. Ho già scritto sulla riusabilità e sulla separazione delle preoccupazioni. Sono sicuro che non ho bisogno di convincerti di questi benefici. Una vista tabella è altamente riutilizzabile e incredibilmente performante. Gli sviluppatori possono utilizzare i componenti UIKit standard nelle loro applicazioni senza necessità di sottoclassi o personalizzazione.

Colpire i limiti di MVC

Ma questa è solo una parte della storia. Sai quando inizi a colpire i limiti di MVC quando enormi controllori di vista si sono introdotti di nascosto nel tuo progetto. È tempo di cambiare quando stai scavando centinaia o migliaia di righe di codice per trovare quel metodo che stai cercando. 

Scaricarlo nel controller

La maggior parte degli sviluppatori sa cosa va nella vista e nei livelli del modello di una tipica applicazione Cocoa alimentata dal modello Model-View-Controller. Ma quale componente è responsabile della formattazione dei dati visualizzati all'utente? Ricorda che le opinioni dovrebbero essere stupide e riutilizzabili. La vista non dovrebbe essere necessario formattare i dati. Destra? Dovrebbe solo sapere come presentare i dati e rispondere all'interazione dell'utente. Il modello dovrebbe essere interessato alla formattazione dei dati?

E che dire della rete? Questo non è certamente il compito della vista. Dovrebbe essere delegato al modello? Non sembra giusto. Perché non inseriamo quel pezzo di codice nel controller. Non sembra giusto, ma lo farà per ora.

Dopo molte righe di codice, si finisce con un controller pronto a scoppiare e un incubo da testare. Prove? Ti sento. Non vorrei provare un controller di visualizzazione che soffre sindrome da controller di vista massiva o.

5. Una soluzione migliore

Hai iniziato con buone intenzioni, ma sei finito con un progetto che ha una collezione di controller sovrappeso che sono difficili da gestire e mantenere. Non sei ansioso di aggiungere nuove funzionalità al progetto su cui stai lavorando perché aprire quei controller di visualizzazione ti fa star male allo stomaco. Questo suona familiare?

È importante rendersi conto che questo è uno scenario comune. Molti sviluppatori raggiungono i limiti del modello Model-View-Controller e si rendono conto che hanno bisogno di qualcosa di meglio. Le probabilità sono che hai già visto diverse alternative, come ad esempio MVP (Model-View-Presenter) o MVVM (Model-View-ViewModel).

Nella prossima puntata di questa serie, eseguirò uno zoom in avanti Model-View-ViewModel modello. Sarà stranamente familiare se hai già lavorato con il modello Model-View-Controller. Ma il modello Model-View-ViewModel apporta alcuni miglioramenti alla tabella che funzionano molto bene per lo sviluppo di Cocoa.

E mentre aspetti, consulta alcuni dei nostri altri post sullo sviluppo di app Cocoa!