2010-01-13 2 views
5

AGGIORNAMENTO:controller <-> Servizio componente interazione

Ho un'applicazione desktop, con i seguenti componenti interagenti:

  • WinForms UI.
  • servizi (in-process C# classe che contiene la logica di business in realtà fare roba).
  • Controller (classe C# che coordina gli eventi generati dall'interfaccia utente e chiama i metodi di servizio).

Se un controllore chiede un servizio di fare qualcosa, ma che il servizio ha bisogno di qualcosa di più dal primo controller (cioè i dati che il controllore deve utilizzare un'interfaccia utente per ottenere da parte dell'utente), come si dovrebbe il servizio ottenere il controllore per farlo?


Sono comodo con il concetto che

  • utente comunica con
  • UI che comunica con
  • controller che comunica con
  • componente servizi (da non confondere con un servizio Web o un servizio out-of-process) che comunica con
  • Dati/Reposi Tories che comm ...

e così via.

Tuttavia, per quanto riguarda il Controller che comunica con il Servizio, quale metodo è migliore per questo? Dovrebbe:

  1. I metodi di servizio sono abbastanza raffinati e generano eccezioni se qualcosa non va bene in modo che il controllore sappia se andare avanti o dire all'utente che qualcosa è andato storto? Oppure ...
  2. I metodi di servizio restituiscono oggetti che il controllore può ispezionare per decidere cosa fare dopo?

Mi piace la prima opzione, perché la seconda potrebbe significare esplosione di classe, in cui è necessaria una classe di stile ServiceResult per ciascun metodo di servizio.

Chiedo perché ovviamente il componente Servizio non è in grado di dire all'interfaccia utente cosa fare, solo il controller può, ma il controller non sa cosa dire all'interfaccia utente senza ricevere feedback dal servizio.

Cosa ne pensi?

risposta

2

L'opzione migliore è probabilmente l'utilizzo di un modello di evento o delegato, ad esempio il controllore si iscrive a un evento "richiede più informazioni" e visualizza il modulo appropriato. Restituire i dati aggiuntivi al servizio potrebbe essere fatto in modi diversi, ma dipenderebbe in gran parte dalle specifiche del tuo progetto (ad esempio i tuoi servizi stateless ecc.)

Hai scritto test unitari per il tuo servizio? In caso contrario, questo processo probabilmente ti aiuterà a chiarire cosa vuoi dal tuo progetto.

2

La prima cosa che dovete tenere a mente quando si progetta il servizio di livello/classi è quello di renderli altamente riutilizzabile. Dovrebbero essere oggetti di servizio atomici che possono servire non solo il controller, ma anche altri client in futuro.

Ci sono alcune domande qui:

  1. Come funziona il controller trovare il servizio?
    Se si desidera disporre di oggetti di servizio altamente riutilizzabili, estendibili e ..., la dipendenza tra il controllore e le classi di servizio deve essere accoppiata liberamente. Evitare qualsiasi tecnica di accoppiamento stretto. Invece, provare a inject la classe di servizio sul controller (utilizzando un contenitore IOC) e inoltre è possibile utilizzare Service Locator Design Pattern.

  2. Come comunicare con il servizio?
    Bene, dipende dalla dimensione della vostra applicazione. Si può andare per tecnologie di servizi aziendali, come i servizi Web, basta usare i servizi applicativi. Sulla base di ciò, si definisce il protocollo tra il controller e il servizio.

  3. Quali dati devono essere restituiti al controller?
    Ricordare che il livello di servizio non deve sapere nulla sulla navigazione dell'interfaccia utente. È responsabilità del controllore decidere dove andare e cosa fare in base alla risposta dell'oggetto servizio. Perché? Immagina che questa classe di servizio debba essere utilizzata per un'altra interfaccia utente (diciamo dal web alla flex, all'argenteria o all'applicazione desktop). Se si aggiunge la logica di navigazione (come esempio estremo, logica di interfaccia utente/formattazione) nella classe di servizio, non sarà riutilizzabile per un altro sistema di interfaccia utente e inoltre non sarà riutilizzabile anche per altre classi di servizio e controller all'interno della stessa applicazione .

In conclusione, provare a mantenere la classe di servizio pulita da qualsiasi logica di navigazione. Il controller è davvero pensato per quello scopo.

+0

Il controller riceve il servizio tramite un contenitore IoC. Il trucco è che a volte i servizi non possono andare oltre perché ha bisogno di più informazioni, ma non può accedere all'interfaccia utente - ha bisogno del controller per farlo. Quindi, come dovrebbe il servizio informare il controller di cui ha bisogno per raccogliere più informazioni? –

+1

Se si pensa che il servizio sia un componente completo e indipendente con una certa responsabilità (mi ricorda semplicemente CRC), può avere uno scenario principale (riuscito) e alcune eccezioni (scenari alternativi). In questo caso stai parlando delle eccezioni. Questa è un'opinione di alto livello. Ora per l'implementazione, mi piace usare le eccezioni è un modo elegante. Sono auto-esplicativi e molto ben gestiti se usati correttamente nelle applicazioni. Anche se cambi controller o altri client per i tuoi servizi, funzionerà comunque. Spero che questa sia la risposta alla tua domanda. –

0

Vedi la mia domanda here

Ci sono alcuni dettagli mancanti per rispondere meglio si domanda:

Si tratta di una web o uno scenario desktop?

Se desktop: si tratta di uno scenario disconnessi? (ad esempio, rich client con servizi remoti) o fa il client e il servizio sulla stessa macchina?

Se web - è una classica applicazione Web 1.0? (la vista è creata come una pagina) o un cliente ricco? (AJAX, Flex, SilverLight) dove il controller a volte può essere nel client? (Flex)

Tutto ciò può influire in modo significativo sulle decisioni.

A proposito, hai omesso il modello di proposito?

+0

Desktop: vedere l'aggiornamento alla domanda. Questo è tutto in-process: il "servizio" in questo contesto indica un oggetto servizio che contiene la logica aziendale: il modello viene utilizzato dal servizio per eseguire il lavoro effettivo, ma l'interazione tra il controller e il servizio è ciò che mi interessa davvero in. –

0

Lavoro molto con MVC (anche se il mio è l'aroma della web app Java), e spesso mi sono imbattuto in alcune situazioni in cui sembra che il servizio debba in qualche modo interagire ulteriormente con il controller. Ma in ogni caso, è risultato che ho fatto qualcosa di sbagliato nel controller o l'interfaccia del mio servizio non è abbastanza flessibile (cioè, a grana fine).

Quando il servizio non riceve dati sufficienti, ciò è dovuto all'utente che fornisce un input non valido? In tal caso, il controllore deve eseguire la convalida sull'input e visualizzare il prompt o il messaggio di errore appropriato.

Se si prevede che l'utente non fornisca tutti i dati contemporaneamente, il controller deve essere consapevole che il servizio non accetterà i dati così come sono. Pertanto, il controller deve gestire la conversazione con l'utente tramite l'interfaccia utente, quindi alla fine passare tutto al servizio alla fine.

O forse il controller deve interrogare il servizio attraverso il flusso della procedura guidata. In tal caso, l'interfaccia del servizio probabilmente dovrebbe essere più fine.

Vorrei andare con l'opzione n. 1 che hai proposto. Se il controller è in grado di raccogliere tutti gli input richiesti dall'interfaccia utente e fornirli al servizio, ma non riesce a farlo, il servizio dovrebbe generare un'eccezione. L'utilizzo di un'eccezione è ragionevole perché stai tentando di trasferire dati non validi al servizio. (Ciò non cambia il fatto che le eccezioni non dovrebbero essere lanciate per controllare il flusso del programma, ma piuttosto per indicare che il controller si è effettivamente rovinato nel fornire alcuni dati non validi.)

0

Hai considerato l'utilizzo dello Model View Presenter?

Le tue visualizzazioni dell'interfaccia utente implementerebbero interfacce e queste interfacce sarebbero note ai tuoi servizi. In questo modo, i tuoi servizi potrebbero chiamare l'interfaccia utente per chiedere ulteriori informazioni per svolgere i loro compiti. Questo è un tipo di dependency inversion (pdf).