Suggerimenti per le prestazioni per il modello MVVM e il linguaggio

Questo argomento illustra alcune considerazioni sulle prestazioni correlate alla scelta dei modelli di progettazione software e dei linguaggi di programmazione.

Modello Model-View-ViewModel (MVVM)

Il modello Model-View-ViewModel (MVVM) è comune in un gran numero di app XAML. È molto simile alla descrizione fatta da Fowler del modello Model-View-Presenter (MVP), ma questo modello è adattato a XAML. Il problema derivante dal modello MVVM è che il suo uso può far sì che inavvertitamente le app siano caratterizzate da un numero eccessivo di livelli e allocazioni. Le motivazioni a favore del modello MVVM sono descritte di seguito.

  • Separazione delle attività. È sempre utile suddividere un problema in elementi più piccoli. Un modello quale, ad esempio, MVVM o MVC, consente di suddividere un'app o persino un singolo controllo in elementi più piccoli: la visualizzazione effettiva, un modello logico della visualizzazione (modello di visualizzazione) e la logica dell'app indipendente dalla visualizzazione (il modello). In particolare, il tradizionale flusso di lavoro prevede che i progettisti gestiscano la visualizzazione con uno strumento, gli sviluppatori gestiscano il modello usando un altro strumento mentre i responsabili dell'integrazione della progettazione gestiscano il modello di visualizzazione usando entrambi gli strumenti.
  • Esecuzione di unit test. È possibile sottoporre a unit test il modello di visualizzazione (e di conseguenza il modello) indipendentemente dalla visualizzazione, ovvero non avvalendosi della creazione di finestre, l'immissione di input e così via. Se la visualizzazione è di piccole dimensioni, puoi sottoporre a test gran parte della tua app senza dover creare una finestra.
  • Possibilità di modifica dell'esperienza utente. La visualizzazione è soggetta alle modifiche più frequenti, e a quelle più tardive in quanto l'esperienza utente viene personalizzata in base ai feedback degli utenti finali. Mantenendo separate le visualizzazioni puoi gestire queste modifiche più velocemente e con meno impatto per l'app.

Sono disponibili più definizioni del modello MVVM e dei framework di terze parti che consentono di implementarlo. Tuttavia, una rigida conformità a qualsiasi variazione di tale modello potrebbe portare ad app con molto più overhead di quanto giustificabile.

  • Il data binding XAML (l'estensione di markup {Binding}) è stato progettato in parte per consentire pattern modello/visualizzazione. Ma {Binding} comporta un working set non semplice e un sovraccarico della CPU. La creazione di un {Binding} causa una serie di allocazioni e l'aggiornamento di una destinazione di associazione può causare reflection e boxing. Questi problemi vengono gestiti mediante l'estensione di markup {x:Bind}, che compila le associazioni in fase di building. Suggerimento: usa {x:Bind}.
  • Nel modello MVVM è comune connettere Button.Clic al modello di visualizzazione mediante un'interfaccia ICommand, ad esempio gli helper DelegateCommand o RelayCommand. Questi comandi sono però allocazioni aggiuntive, che includono il listener di eventi CanExecuteChanged, l'aggiunta al working set e l'incremento del tempo di avvio/spostamento per la pagina. Raccomandazione: come alternativa all'uso dell'interfaccia ICommand pratica, è consigliabile inserire gestori eventi nel code-behind e collegarli agli eventi di visualizzazione e chiamare un comando nel modello di visualizzazione quando vengono generati tali eventi. Devi inoltre aggiungere altro codice per disabilitare il pulsante quando il comando non è disponibile.
  • Nel modello MVVM è comune creare una pagina contenente tutte le possibili configurazioni dell'interfaccia utente e quindi comprimere le parti dell'albero mediante il binding tra la proprietà Visibility e le proprietà nella VM. Ciò potrebbe incrementare inutilmente il tempo di avvio ed eventualmente sovraccaricare il working set in quanto alcune parti dell'albero potrebbero non venire mai visualizzate. Raccomandazioni: utilizzare la funzionalità attributo x:Load o attributo x:DeferLoadStrategy per rinviare parti non necessarie dell'albero al di fuori dell'avvio. Inoltre, creare controlli utente separati per le diverse modalità della pagina e usare code-behind per mantenere caricati solo i controlli necessari.

Suggerimenti per C++/CX

  • Usa la versione più recente. Il compilatore C++/CX è soggetto a continui miglioramenti delle prestazioni. Verifica di usare il set di strumenti più recenti per lo sviluppo dell'app.
  • Disabilita RTTI (/GR-). L'opzione RTTI è abilitata per impostazione predefinita nel compilatore. Per tale motivo, a meno che l'ambiente di compilazione non la abbia disabilitata, è possibile che la si stia usando. L'opzione RTTI genera un overhead significativo e a meno che il codice non dipenda massicciamente da tale opzione, consigliamo di disattivarla. Il framework XAML non richiede l'uso dell'opzione RTTI da parte del codice.
  • Evitare un uso eccessivo delle attività PPL. Le attività PPL risultano molto utili in caso di chiamata di API WinRT asincrone, ma sono caratterizzate da un overhead significativo delle dimensioni del codice. Il team C++/CX sta lavorando su una funzionalità del linguaggio (await) che garantirà prestazioni decisamente migliori. Nel frattempo utilizzare con molta parsimonia le attività PPL nei percorsi critici del codice.
  • Evitare l'uso di C++/CX nella "logica di business" dell’app. C++/CX è progettato come uno strumento pratico per accedere alle API WinRT dalle app C++. Fa uso di wrapper, che sono caratterizzati da overhead. È consigliabile evitare l'uso di C++/CX all'interno del modello/logica di business della classe, riservandone l'uso ai limiti tra il codice e WinRT.