A mio avviso, c'è una differenza tra la restituzione di NULL, la restituzione di un risultato vuoto (ad esempio la stringa vuota o un elenco vuoto) e il lancio di un'eccezione.
Normalmente prendo il seguente approccio. Considero una funzione o un metodo f (v1, ..., vn) come l'applicazione di una funzione
f : S x T1 x ... x Tn -> T
dove S è lo "stato del mondo" T1, ..., Tn sono i tipi di parametri di input e T è il tipo di ritorno.
Per prima cosa provo a definire questa funzione. Se la funzione è parziale (ovvero ci sono alcuni valori di input per i quali non è definita) restituisco NULL per segnalarlo. Questo perché voglio che il calcolo termini normalmente e mi dica che la funzione che ho richiesto non è definita sugli input dati. L'uso, ad esempio, di una stringa vuota come valore di ritorno è ambiguo perché potrebbe essere che la funzione è definita sugli input e la stringa vuota è il risultato corretto.
Penso che il controllo extra per un puntatore NULL nel codice chiamante sia necessario perché stai applicando una funzione parziale ed è compito del metodo chiamato dirti se la funzione se non definita per l'input dato.
Preferisco utilizzare eccezioni per errori che non consentono di eseguire il calcolo (ovvero non è stato possibile trovare alcuna risposta).
Ad esempio, supponiamo di avere un cliente di classe e di voler implementare un metodo
Customer findCustomer(String customerCode)
per cercare un cliente nel database dell'applicazione tramite il suo codice. Con questo metodo, lo farei
- Restituisce un oggetto di classe Cliente se la query ha esito positivo,
- Restituisce null se la query non trova alcun cliente.
- Generare un'eccezione se non è possibile connettersi al database.
I controlli extra per null, ad es
Customer customer = findCustomer("...");
if (customer != null && customer.getOrders() > 0)
{
...
}
fanno parte della semantica di ciò che sto facendo e non vorrei semplicemente "saltarli" per migliorare la lettura del codice. Non credo sia una buona pratica semplificare la semantica del problema a portata di mano solo per semplificare il codice.
Naturalmente, poiché il controllo per null si verifica molto spesso, è utile che la lingua supporti una sintassi speciale per esso.
Vorrei anche prendere in considerazione l'uso del modello Null Object (come suggerito da Laf) fintanto che posso distinguere l'oggetto null di una classe da tutti gli altri oggetti.