Come decidere se l'oggetto deve essere passato come parametro o essere un membro della classe

1

Avere un servizio che ad es. scarica dati, la cui responsabilità è ProgressReporter ? Dovrebbe essere la responsabilità del chiamante passare una valida, come in CodeSample1, o sarebbe meglio se fosse la responsabilità del creatore dell'oggetto come in CodeSample2? La prima opzione offre maggiore flessibilità in merito al possibile riutilizzo di questo oggetto funzione con diversa implementazione di IProgressReporter, mentre la seconda elimina la necessità di ripetere e passare attorno all'oggetto IProgressReporter.

CodeSample1:

public class WebClientDownloader : IDownloader
{
    private IProgressReporter ProgressReporter { get; set; }

    private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        // ...
    }

    private void DownloadCompleted(object sender, DownloadDataCompletedEventArgs e)
    {
        ProgressReporter?.Stop();
    }

    public Task<byte[]> GetBytesAsync(Uri uniqueResourceIdentifier, 
IProgressReporter progress)
    {
        ProgressReporter = progress;
        using (var client = new WebClient())
        {
            client.DownloadProgressChanged += ProgressChanged;
            client.DownloadDataCompleted += DownloadCompleted;
            return client.DownloadDataTaskAsync(uniqueResourceIdentifier);
        }
    }

CodeSample2:

public class WebClientDownloader : IDownloader
{
    public IProgressReporter ProgressReporter { get; }
    public WebClientDownloader(IProgressReporter progress)
    {
        ProgressReporter = progress;
    }

    private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        //...
    }

    private void DownloadCompleted(object sender, DownloadDataCompletedEventArgs e)
    {
        ProgressReporter?.Stop();
    }

    public Task<byte[]> GetBytesAsync(Uri uniqueResourceIdentifier)
    {
        ProgressReporter.Restart();
        using (var client = new WebClient())
        {
            client.DownloadProgressChanged += ProgressChanged;
            client.DownloadDataCompleted += DownloadCompleted;
            return client.DownloadDataTaskAsync(uniqueResourceIdentifier);
        }
    }
}
    
posta Piotr Falkowski 13.11.2016 - 23:10
fonte

2 risposte

2

Preferirei il primo, con alcune modifiche.

Poiché ProgressReporter è responsabile dello stato di avanzamento di una singola chiamata GetBytesAsync , è corretto impostarla come argomento della funzione. Ma dal momento che è responsabile dello stato di avanzamento di una singola chiamata GetBytesAsync , è improprio assegnarla a una variabile di livello di classe. rapidamente corri nei problemi di concorrenza se usi questo downloader due volte poiché la seconda chiamata eseguirà il comando su quella variabile, uccidendo l'avanzamento del primo download.

Invece, dovresti lasciarlo in ambito locale e usare lambdas per i callback dell'evento.

    
risposta data 14.12.2016 - 15:49
fonte
1

Penso che dipenda in gran parte dal fatto che ProgressReporter rappresenti lo stato di WebClientDownloader o se rappresenti lo stato di un determinato download in corso. Non sono chiaro sul tuo esempio di codice se intendi creare una sola WebClientDownloader da istanziare per download o meno. Se esiste una correlazione uno a uno tra download e istanze dell'oggetto, il progresso viene misurato come una modifica nello stato dell'istanza, quindi è logico che ProgressReporter venga passato attraverso l'istanza e immutabile dopo. Dovresti solo distruggere questa istanza e crearne una nuova dopo il download.

Penso che sia importante anche ciò che ritieni che le condizioni sotto con un ProgressReporter cambieranno. Dal tuo codice è chiaro che non pensi che cambierà nel bel mezzo di un download, ma dovresti pensare a quando cambierà in modo da avere una migliore percezione di quando consentire a detto modificare.

    
risposta data 14.11.2016 - 12:12
fonte

Leggi altre domande sui tag