Utilizzo corretto di null
Esistono diversi modi di utilizzo null. Il modo più comune e semanticamente corretto è usarlo quando potresti avere o meno un singolo valore. In questo caso un valore è uguale nullo è qualcosa di significativo come un record dal database o qualcosa del genere.
In queste situazioni, lo usi principalmente in questo modo (in pseudo-codice):
if (value is null) {
doSomethingAboutIt();
return;
}
doSomethingUseful(value);
Problema
E ha un grosso problema. Il problema è che quando invochi doSomethingUsefulil valore potrebbe non essere stato verificato null! In caso contrario, probabilmente il programma si arresterà in modo anomalo. E l'utente potrebbe anche non vedere alcun buon messaggio di errore, rimanendo con qualcosa come "errore orribile: valore desiderato ma ottenuto nullo!" (dopo l'aggiornamento: anche se Segmentation fault. Core dumped.in alcuni casi potrebbe esserci un errore informativo ancora minore come , o peggio ancora, nessun errore e manipolazione errata su null)
Dimenticare di scrivere controlli nulle gestire nullsituazioni è un bug estremamente comune . Ecco perché Tony Hoare, che ha inventato, ha nulldichiarato in una conferenza sul software chiamata QCon London nel 2009 di aver commesso l'errore di un miliardo di dollari nel 1965:
https://www.infoq.com/presentations/Null-References-The-Billion-Dollar- errore-Tony-Hoare
Evitare il problema
Alcune tecnologie e lingue rendono nullimpossibile il controllo dell'oblio in diversi modi, riducendo la quantità di bug.
Ad esempio Haskell ha la Maybemonade invece di null. Supponiamo che DatabaseRecordsia un tipo definito dall'utente. In Haskell un valore di tipo Maybe DatabaseRecordpuò essere uguale Just <somevalue>o uguale a Nothing. È quindi possibile utilizzarlo in diversi modi, ma indipendentemente da come lo si utilizza non è possibile applicare alcune operazioni Nothingsenza saperlo.
Ad esempio questa funzione chiamata zeroAsDefaultrestituisce xper Just xe 0per Nothing:
zeroAsDefault :: Maybe Int -> Int
zeroAsDefault mx = case mx of
Nothing -> 0
Just x -> x
Christian Hackl afferma che C ++ 17 e Scala hanno i loro modi. Quindi potresti voler provare a scoprire se la tua lingua ha qualcosa del genere e usarla.
I null sono ancora ampiamente utilizzati
Se non hai niente di meglio, allora usare nullva bene. Continua a fare attenzione. Digitare le dichiarazioni nelle funzioni ti aiuterà comunque in qualche modo.
Inoltre, potrebbe non sembrare molto progressivo, ma dovresti controllare se i tuoi colleghi vogliono usare nullo qualcos'altro. Potrebbero essere prudenti e potrebbero non voler utilizzare nuove strutture dati per alcuni motivi. Ad esempio, supportando versioni precedenti di una lingua. Tali cose dovrebbero essere dichiarate negli standard di codifica del progetto e adeguatamente discusse con il team.
Sulla tua proposta
Suggerisci di usare un campo booleano separato. Ma devi comunque controllarlo e potresti ancora dimenticartene. Quindi non c'è niente vinto qui. Se puoi anche dimenticare qualcos'altro, come aggiornare entrambi i valori ogni volta, allora è anche peggio. Se il problema di dimenticare di verificare nullnon è risolto, non ha senso. Evitare nullè difficile e non dovresti farlo in modo da peggiorare le cose.
Come non usare null
Infine, ci sono modi comuni per utilizzare in nullmodo errato. Uno di questi è quello di usarlo al posto di strutture di dati vuote come array e stringhe. Un array vuoto è un array adeguato come qualsiasi altro! È quasi sempre importante e utile per le strutture di dati, che possono adattarsi a più valori, per poter essere vuoti, ovvero avere lunghezza 0.
Dal punto di vista dell'algebra una stringa vuota per le stringhe è molto simile a 0 per i numeri, ovvero identità:
a+0=a
concat(str, '')=str
La stringa vuota consente alle stringhe in generale di diventare un monoide:
https://en.wikipedia.org/wiki/Monoid
Se non lo ottieni non è così importante per te.
Ora vediamo perché è importante per la programmazione con questo esempio:
for (element in array) {
doSomething(element);
}
Se passiamo un array vuoto qui il codice funzionerà bene. Non farà proprio niente. Tuttavia, se passiamo un nullqui, probabilmente avremo un arresto anomalo con un errore del tipo "impossibile passare da null a, scusa". Potremmo avvolgerlo ifma è meno pulito e di nuovo, potresti dimenticare di controllarlo
Come gestire null
Ciò che doSomethingAboutIt()dovrebbe essere fatto e soprattutto se dovrebbe generare un'eccezione è un altro problema complicato. In breve, dipende dal fatto che nullfosse un valore di input accettabile per una determinata attività e da cosa ci si aspetta in risposta. Le eccezioni sono per eventi che non erano previsti. Non approfondirò questo argomento. Questa risposta è già molto lunga.
std::optionaloOption. In altre lingue, potresti dover creare tu stesso un meccanismo appropriato, oppure potresti effettivamente ricorrere anullqualcosa di simile perché è più idiomatico.