2010-10-17 12 views
5

Ultimamente mi sono imbattuto in pattern di progettazione Null Object e i miei colleghi dicono che può essere utilizzato per eliminare i controlli con puntatore nullo che si incontrano nel codice.Modello oggetto nullo per evitare i controlli Null?

per esempio, supponiamo che una classe DAO restituisca informazioni sul Cliente (in un oggetto valore chiamato CustomerVO). La mia classe principale dovrebbe estrarre firstName e emailId e inviare email al cliente.

... 
CustomerVO custVO = CustomerDAO.getCustomer(customerID); 
if(custVO != null) { // imp, otherwise we may get null ptr exception in next line 
    sendEmail(custVO.getFirstName(), custVO.getEmailID()); 
} 
... 

questo è molto semplice esempio, ma tali controlli nulli può diffondersi rapidamente in tutto il codice in base alla complessità degli oggetti di valore.

ho due problemi con il controllo nullo, - tendono tmake il codice brutto e difficile da leggere - minore sviluppatori esperti messi controlli nulli inutili quando in realtà dovrebbero generare eccezioni. per es. nel codice sopra, sarebbe meglio gettare un'eccezione da getCustomer() stesso perché se non è in grado di trovare informazioni sul cliente per un determinato CustID, indica che il CustID non era valido.

okay, tornando al modello di oggetto nullo, è possibile utilizzare un oggetto CustomerVO "null" per nascondere il controllo null?

CustomerVO { 
    String firstName = ""; 
    String emailID = ""; 
} 

Non avrebbe senso. cosa ne pensi?

E quali sono le cose che segui per ridurre i controlli null nella tua app.

risposta

2

In questo caso, un oggetto nullo potrebbe non essere appropriato poiché l'impostazione predefinita potrebbe nascondere quella che in realtà è un'eccezione. Se ti ritrovi a dover controllare se hai il nulla sicuro per eseguire qualche altra attività, il modello nullo non ti sta comprando nulla.

Come hai affermato, molti nuovi sviluppatori trascorrono del tempo cercando di proteggere il loro codice da situazioni di eccezione che sono peggio di un programma di arresto.

3

Mentre il modello di oggetto nullo ha i suoi usi, sarà comunque necessario fare un controllo qui, altrimenti proverai a sendEmail() a un indirizzo email che è la stringa vuota (o premi il check in sendEmail(), che potrebbe facilmente controllare null).

dove il modello oggetto null sarebbe veramente utile qui è se la classe CustomerVO implementato il metodo sendEmail(). allora si può semplicemente concatenare le chiamate, dato che il contratto di getCustomer() farebbe sì che un riferimento null non sarebbe tornato:

CustomerDAO.getCustomer(customerID).sendEmail(); 

In questo caso il metodo sendEmail() controllerebbe che il suo stato chiesto di agire sulla speciale 'oggetto nullo' e semplicemente non fare nulla (o qualsiasi cosa sia appropriata).

+1

+1, anche se non vorrei che i miei clienti di avere metodi SendEmail.È solo dare troppe responsabilità a una classe di clienti. È come dare a ogni classe un metodo di "stampa" e ora dover implementare la logica di stampa ovunque o rendere ogni classe dipendente da qualche gestore di stampa, mentre potrebbe essere limitato a un gestore di stampa e ai moduli/classi che effettivamente avviano la stampa dando al manager di stampa le classi da stampare. Laddove il pattern nullo è davvero bello, è in fase di testing unitario, ad esempio, fornire una classe di log che non esegue nulla in modo da non dover modificare il codice in fase di test. –

1

Il tuo metodo getCustomer dovrebbe generare un'eccezione se il cliente non viene trovato, anziché restituire null?

La risposta, ovviamente, è che dipende: dovrebbe quasi mai nel caso che un ID cliente non esista? In altre parole, è una circostanza eccezionale? Se è così, un'eccezione è appropriata.

Tuttavia, in un livello di accesso ai dati è spesso normale che qualcosa non esista.In tal caso, è meglio non gettare poiché non è una circostanza inaspettata, eccezionale.

Il "restituire un oggetto non null con campi vuoti" non è probabilmente migliore. Come fai a sapere se l'oggetto restituito è "valido" o meno senza aggiungere un codice di controllo che è probabilmente peggio del controllo nulla?

Quindi, se potrebbe essere uno stato normale che qualcosa che viene recuperato non esiste, il modello di controllo nullo è probabilmente il migliore. Se si tratta di qualcosa di inaspettato, il fatto che il metodo di accesso ai dati genera un'eccezione NotFound è probabilmente migliore.

+0

Vedere la mia risposta, se qualcosa non può esistere, avere un metodo che controlla se esiste. In questo modo devi solo generare eccezioni dove è eccezionale. – nicodemus13

1

Ho un problema con questo tipo di codice, che è un modello comune. Non hai affatto bisogno dei controlli nulli se decomponi ciò che stai effettivamente facendo. Il problema qui, a mio avviso, è che stai violando SRP.

Il metodo CustomerVO custVO = CustomerDAO.getCustomer(customerID); fa due cose.

In primo luogo restituisce un cliente, se il cliente esiste e in secondo luogo restituisce null se non esiste tale cliente. Queste sono due operazioni distinte e dovrebbero essere codificate come tali.

Un approccio migliore potrebbe essere:

bool customerExists = CustomerDAO.exists(customerID); 

if (customerExists) 
{ 
    CustomerVO custVO = CustomerDAO.getCustomer(customerID); 
    sendEmail(custVO.getFirstName(), custVO.getEmailID()); 
} 
else 
{ 
    // Do whatever is appropriate if there is no such customer. 
} 

}

Quindi, dividere il metodo in due, uno che verifica se esiste l'oggetto richiesto e il secondo che in realtà lo recupera. Non c'è bisogno di eccezioni e il design e la semantica sono molto chiari (il che, a mio parere, con un modello non-esiste-ritorna-null non lo è). Inoltre, in questo approccio, il metodo CustomerDAO.getCustomer(customerID) genera un ArgumentException, se il cliente richiesto non esiste. Dopo tutto, hai chiesto uno Customer e non ce n'è uno.

Inoltre, a mio avviso, nessun metodo deve restituire null. Null è esplicitamente: "Non so quale sia la risposta corretta, non ho alcun valore da restituire". Null non è un significato, è uno mancanza di significato. Chiediti: 'perché sto restituendo qualcosa che so che non dovrebbe accadere davvero? Il tuo metodo GetCustomer dovrebbe restituire un Customer ovviamente. Se restituisci null, stai semplicemente spingendo la responsabilità di cosa fare per eseguire il backup della catena di chiamate e interrompere il contratto. Se c'è un valore predefinito, usalo, ma lanciare un'eccezione potrebbe farti pensare un po 'più a cosa sia il design corretto.

0

Il nome è NULL object design pattern e non NULL check design pattern. L'oggetto nullo indica l'assenza di un oggetto. Questo dovrebbe essere usato quando hai oggetti che lavorano in COLLABORAZIONE. Nel tuo caso stai controllando l'esistenza di un oggetto per il quale il controllo NULL dovrebbe andare bene.

Il modello di progettazione NULL non è destinato a sostituire la gestione delle eccezioni NULL. È uno dei vantaggi collaterali del modello di progettazione NULL, ma l'intenzione è fornire un comportamento predefinito.

controlli NULL non devono essere sostituiti con oggetti di design pattern NULL in quanto può portare a difetti silenziose applicazione.

fare vedere l'articolo qui sotto che va nei dettagli di fare e Donts di design pattern NULL.

http://www.codeproject.com/Articles/1042674/NULL-Object-Design-Pattern

Problemi correlati