Le problematiche più comuni di un'architettura M-V-VM con WPF

di Cristian Civera, in Windows Presentation Foundation,

Nell'articolo di introduzione al pattern Model-View-ViewModel si è visto qual è l'idea che sta alla base di questo nuovo modo di creare applicazioni. Basandosi su tutte le funzionalità di Windows Presentation Foundation, si può trarre il massimo da esso e allo stesso tempo mantenere un'architettura pulita che permette di aumentare la superficie di codice che si può testare portandola sempre più vicina all'interfaccia grafica.

Purtroppo oltre ai tanti vantaggi che si ottengono, si può inciampare in problematiche che con un approccio classico risultano semplici e di facile risoluzione. In questi casi può risultare impossibile trovare una soluzione senza sporcare l'architettura, scoraggiando lo sviluppatore e portandolo addirittura ad abbandonare l'adozione del pattern M-V-VM.

In questo articolo si vuole quindi analizzare queste problematiche e offrire alcune possibili soluzioni senza voler indicare un'unica strada giusta, ma mantenendo un approccio che mostri pro e contro al fine di scegliere quella più adatta ad ogni esigenza.

I framework a supporto

Quando si inizia un progetto che sfrutti il pattern M-V-VM, il programmatore si scontra prima di tutto con il dover scrivere codice ripetitivo e partire da una base di funzionalità comune a tutte le applicazioni. Facendo riferimento all'articolo introduttivo menzionato all'inizio, classi come ViewModelBase, Delegate/RelayCommand rientrano tra i requisiti minimi per iniziare. Fortunatamente in rete stanno nascendo parecchi framework a supporto che includono le classi prima citate, snippet di codice, template per Visual Studio e alcune implementazioni di pattern che possono essere d'aiuto nello sviluppo.

Alcuni di questi vengono presi in considerazione in questo articolo perché sono semplici, ma anche perchè allo stesso tempo risolvono facilmente problematiche; lo dimostra la grande diffusione che stanno avendo.

I framework più comuni e attualmente disponibili sono:

  • WPF Toolkit: rilasciato dal team ufficiale di WPF, contiene le classi principali e un piccolo esempio di applicazione messenger che ne fa uso;
  • MVVM Light Toolkit: un toolkit che contiene le classiche classi, ma implementa anche il mediator pattern. Fornisce template per Visual Studio e snippet di codice per creare attached/dependency property e proprietà che supportano il data binding;
  • WPF Onyx: implementa le classiche classi e fornisce inoltre un meccanismo di Inversion of Control, basato su Dependency Injection o Service Locator (spiegati più avanti);
  • MVVM Foundation: contiene le casi basi del M-V-VM e implementa i pattern Mediator ed Observer.
  • PRISM: non è semplicemente un toolkit, ma un framework completo di esempi che fa uso di molteplici pattern per gestire gli errori, il caricamento dinamico, l'interfaccia e la localizzazione.

Tutti questi toolkit sono disponibili con i sorgenti e possono quindi essere inglobati e modificati nei propri assembly. Non sono gli unici ed è probabile che alcuni di questi evolvano o muoiano, come spesso accade. Le idee che stanno comunque alla base sono simili e sono presentate in questo articolo.

Gestire gli aspetti della View

Quando si sposa il pattern M-V-VM, le prime problematiche che si incontrano riguardano gli aspetti di gestione della View. Avviare un'animazione, impostare il focus su un elemento o effettuare calcoli sono tipiche operazioni che si devono scatenare in seguito ad un evento oppure ad un comando e si possono conseguire in più modi. L'errore che spesso si fa è pensare che il code-behind di un file XAML non sia utilizzabile per questi scopi e di sfruttare al massimo le funzioni messe spesso a disposizione da WPF e il markup XAML.

La prima parte dell'affermazione è vera dato che in molte circostanze lo strumento è già messo a disposizione da WPF attraverso il motore di data binding, converter, trigger e attached property. Non è altrettanto vero per la seconda parte, dato che il markup XAML è solo un modo alternativo per definire l'interfaccia ed è sottoposta agli stessi difetti della compilazione del codice. Infatti da essa si ottiene un controllo della sintassi, ma non una verifica della funzionalità del codice e si è perciò scoperti per il testing di questo strato. Di fatto poi il risultato della compilazione è un un'unica classe che mischia il code-behind con il markup, rendendoli quindi un componente tutt'uno: la View.

E' lecito quindi scrivere del codice per interagire con gli oggetti del markup a patto che questo sia il più minimale possibile e non svolga logiche che competano al ViewModel. Laddove invece si dovesse presentare più volte la stessa esigenza o si voglia rendere riutilizzabile e versatile tale funzionalità, vale la pena considerare la creazione di un attached behavior, come visto nello script #66. Con questa tecnica si componentizza e si creano piccole funzionalità da agganciare facilmente ai controlli, direttamente dal markup XAML ed eventualmente da testare con piccole applicazioni; inoltre essa permette di mantenere più organizzato il codice a micro moduli così da essere identificati facilmente rendendo l'applicazione più solida nel tempo, resistendo alle modifiche che si possono apportare.

L'ultima scelta ricade infine sulla creazione di controlli ad hoc per una specifica esigenza, la quale necessita forzatamente di sovrascrivere alcuni comportamenti degli elementi predefiniti di WPF. Difficilmente si opta però per questa scelta, dato che la versatilità di questo framework permette nella maggior parte dei casi di risolvere il problema con un attached property.

5 pagine in totale: 1 2 3 4 5

Attenzione: Questo articolo contiene un allegato.

Contenuti dell'articolo

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti