Lanciare un'eccezione è tipicamente la scelta canonica per errori che si verificano in un livello inferiore (come il DAL), ma deve essere gestita in un modo che dipende dal contesto dei livelli superiori (come la decisione su cosa sia "un descrittivo") messaggio "è o come dovrebbe essere visualizzato da un utente).
Tuttavia, un'eccezione potrebbe non essere appropriata quando si desidera solo segnalare un avviso, ma si desidera comunque restituire un risultato operativo da una funzione. Ad esempio, quando è stato raggiunto il "limite di 1000 righe risultato", è possibile che si desideri restituire i 1000 oggetti trovati finora. Se pensi a una chiamata di funzione come
List<MyObject> result=dal.SelectObjects(someCondition);
quindi lanciando un'eccezione, la funzione non otterrà nemmeno il risultato parziale di tale operazione. Pertanto, in questo caso, un messaggio di errore aggiuntivo potrebbe essere più appropriato, come questo:
List<MyObject> result=dal.SelectObjects(someCondition, out someErrorObject);
Funziona quando è bene ricevere i messaggi di errore o gli avvertimenti alla fine dell'operazione. (Naturalmente, puoi anche combinare il risultato della funzione e le informazioni sull'errore in un oggetto, come mostrato nella risposta di Jon Raynor ).
Ci sono situazioni in cui è necessario restituire avvertimenti o informazioni all'utente già durante l'operazione in esecuzione, non solo alla fine. Ad esempio, supponiamo che l'operazione possa rilevare quando la query consegna più di 1000 oggetti, ma non vuoi interrompere l'operazione, ma inviare un segnale all'interfaccia utente ogni volta che i prossimi 1000 oggetti (o un certo numero ) vengono elaborati, ad esempio per attivare un indicatore di avanzamento. Quindi puoi usare un delegato per restituire informazioni dal DAL a un livello superiore, con questa firma:
// "callback" will be called with the number of objects processed in some interval
List<MyObject> SelectObjects(string someCondition, Action<int> callBack)
Certo, sembra un po 'conteso. La scelta di design migliore per questo caso è di utilizzare la valutazione ritardata utilizzando IEnumerable
:
IEnumerable<MyObject> SelectObjects(string someCondition)
{
// some loop here, using "yield" to return the result
}
Ora il chiamante può decidere da solo se l'operazione deve essere interrotta dopo 1000 oggetti, o dopo 10 secondi, o se l'utente deve essere richiesto interattivamente in questo caso, se l'operazione deve essere continuata, o se qualcosa deve essere in mezzo.
Quindi, come vedete, ci sono diversi modi per mantenere il DAL completamente UI o BL agnostico, restituendo tuttavia condizioni di errore, avvertimenti o informazioni intermedie ai livelli superiori. Devi solo scegliere quali di queste tecniche sono appropriate per il tuo caso.