C # WPF: architettura pulita

3

Sto cercando di implementare Uncle Bob's Clean Architecture nella mia applicazione C # WPF . Attualmente la mia vista ( form ) chiama presenter e presenter chiama interactor .

Se interactor restituisce un valore (se presente) direttamente o invoca un metodo presenter . In quest'ultimo caso, il presenter è collegato a interactor prima del richiamo di interactor ?

So che è una domanda sciocca, ma sono confuso.

    
posta Jaseem Abbas 20.09.2016 - 08:43
fonte

3 risposte

7

Le architetture Model-View-Presenter cercano di sganciare l'interfaccia utente (vista) dalla logica dell'applicazione (presentatore) e dalla logica aziendale (modello). L '"interactor" tipicamente estrae i dati dall'archiviazione dei dati e non vi è quasi nessuna logica aziendale associata.

Con WPF, Model-View-ViewModel è lo stile tipico. La vista (interfaccia utente) conosce il suo ViewModel (che contiene la logica di interazione e notifica la vista sulle modifiche alle proprietà tramite INotifyPropertyChanged) e ViewModel conosce il suo modello (dati, logica aziendale, convalida). L'interazione tra View e ViewModel è gestita da "binding".

Con Asp.net, Model-View-Controller è lo stile tipico. Il controller conosce sia la vista che il modello e controlla direttamente la vista.

    
risposta data 21.09.2016 - 10:40
fonte
2

È più facile da spiegare con un breve esempio. È anche meglio se Presenter e Conttroller sono separati come nella spiegazione dello zio Bos. È comunque necessario se si desidera implementare Dependency Injection con un contenitore IoC.

Supponiamo che tu abbia un semplice caso d'uso in cui l'utente può cercare un cliente dall'ID e visualizzarne il nome, oppure un messaggio di errore se il client non viene trovato.

La classe View ha un Controller e un Presenter nel suo costruttore. Ha un TextBox per l'ID da cercare e un pulsante per avviare la ricerca. Ha anche 2 TextBlocks per il nome del cliente e il messaggio di errore. Questi 2 sono associati alle proprietà nel Presenter.

Quando l'utente fa clic sul pulsante, la vista ottiene il contenuto TextBox e chiama controller.Search(id) .

In definitiva, UseCaseInteractor controlla completamente il comportamento, sia che scelga di visualizzare il client o un messaggio di errore (o qualsiasi altra cosa ...).

Alcuni pseudo-codice per C #:

class Controller {
    Controller(IUseCaseInput){ }
    Search(clientId){ input.Search(clientId); }
}

interface IUseCaseInput { Search(clientId); }

class UseCaseInteractor : IUseCaseInput {
    UseCaseInteractor(IUseCaseOutput) { }
    Search(clientId){ 
        client = ...
        if (client == null) {
            output.SetError("Argh!.";
        } else {
            output.SetClient(client);
        }
    }
}

interface IUseCaseOutput {
    SetError(message);
    SetClient(client);
}

class Presenter : IUseCaseOutput {
    string Error { get; set; }
    string Name { get; set }
    SetError(message) { Error = message; }
    SetClient(client) { Name = client.Name; }
}

Non molto naturale quando si è abituati a MVVM, ma fa perfettamente il lavoro per rinviare tutte le decisioni al caso d'uso. Assomiglia molto più a ciò che fa un framework MVC per il Web.

    
risposta data 21.09.2016 - 20:01
fonte
0

Poiché l'interattore vive nel cerchio "usecases" e il relatore è un "adattatore di interfaccia", la regola di dipendenza risponde chiaramente: l'interactor NON deve chiamare alcuna API sul relatore.

L'immagine di Zio Bob - mostrata nell'articolo collegato alla domanda - mostra che l'intereatore definisce le porte di input e di output. che potrebbero essere classi (DTO) o interfacce che vengono poi implementate su "interfaccia interfaccia" livello / cerchio.

    
risposta data 04.02.2018 - 13:35
fonte

Leggi altre domande sui tag