Sto scrivendo una piccola applicazione usando il pattern model-view-presenter (rinunciando completamente al modello dato che è piuttosto semplice). Ho iniziato con una visione passiva, in cui il presentatore ha fatto tutta la logica dell'interazione e l'elaborazione dei dati. Il mio relatore ha tenuto un riferimento all'interfaccia vista e ha gestito gli eventi dalla vista e ottenuto i dati dalla vista tramite proprietà e metodi in quell'interfaccia. Abbastanza normale finora.
Ho quindi voluto generare l'elaborazione su un thread in modo da poter mantenere l'interfaccia utente reattiva. Utilizzando questa risposta SO come guida, ho ricablato la mia vista per mantenere un riferimento al presentatore, reso un metodo pubblico nel presentatore per avviare l'elaborazione dei dati (che era essenzialmente il gestore eventi esistente per l'evento OK
della vista) e impostarlo nell'esecuzione come attività nel gestore di clic del pulsante OK (con alcuni indicatori di avanzamento):
// In View.cs
private async void OkButton_Click(object sender, EventArgs e)
{
Progress<string> status = new Progress<string>(s => _toolStripStatusLabel.Text = s);
Progress<int> progress = new Progress<int>(i => _toolStripProgressBar.Value = i);
_isProcessingCancelled = false;
EnableControlsWhileRunning(false);
_toolStripProgressBar.Maximum = _sourceTargetMatches.Count;
_toolStripProgressBar.Value = 0;
_toolStripProgressBar.Visible = true;
_toolStripStopButton.Visible = true;
await Task.Factory.StartNew(() => _presenter.ProcessMatches(progress, status));
EnableControlsWhileRunning(true);
_toolStripStopButton.Visible = false;
_toolStripProgressBar.Visible = false;
_toolStripStatusLabel.Text = "Processing complete";
}
Ho lasciato tutte le altre cose "di supervisione" nel presentatore, inizializzate dagli eventi dalla vista, mentre funzionava. Ho rimosso l'evento OK
dalla vista poiché non era più necessario ed è invece preso in considerazione chiamando ProcessMatches
nel presentatore.
Tutto funziona bene, ma sembra un kludge solo perché l'elaborazione viene eseguita su un thread separato. Questa risposta di SE.SE indica che la vista e il presentatore che contengono ciascuno un riferimento all'altro non rappresentano un problema, ma indica anche che la vista risponde agli eventi chiamando metodi nel presentatore, cosa che faccio solo in un caso.
Entrambi i disegni sembrano (approssimativamente) ugualmente testabili, ma nel caso multithreading la vista ha più logica nel gestore di clic OK (impostazione barre di avanzamento, abilitazione / disabilitazione dei controlli, impostazione della visibilità, ecc.) che probabilmente non saranno testati . Certamente la maggior parte dei casi può essere testata in entrambi i progetti, ma sto pensando troppo a questo? Si tratta di una progettazione errata o è accettata a causa della necessità di un'elaborazione asincrona per mantenere un'interfaccia utente reattiva?