Ultimamente mi sono ritrovato a inserire numeri magici in codice per renderlo più leggibile. L'ho fatto in situazioni in cui il numero magico viene usato una sola volta e il suo scopo è ovvio dal contesto. Un esempio di un recente progetto:
/* Extract id from "/toClient/chat/id". */
String channelId = channelIdWithPath.split("/")[3];
Apparentemente, la "migliore pratica" è dichiarare il numero magico come una costante vicino all'inizio della classe, in questo modo:
private final int NUMBER_OF_DELIMITERS_BEFORE_ID_IN_CHAT_CHANNEL_PATH = 3;
... 100 lines of unrelated code ...
/* Extract id from "/toClient/chat/id". */
String channelId = channelIdWithPath.split("/")[NUMBER_OF_DELIMITERS_BEFORE_ID_IN_CHAT_CHANNEL_PATH];
Non vedo alcun vantaggio nel separare la dichiarazione della variabile dalla posizione in cui è stata utilizzata. Abbiamo praticamente raddoppiato il tempo necessario per comprendere questo codice e chiunque lo stia leggendo deve saltare oltre 100 righe per confermare che la variabile ha il valore corretto.
Potremmo dichiararlo come variabile locale appena prima che sia necessario, ma questo è ancora un "numero magico" almeno secondo CheckStyle. Questo è qualcosa che faccio spesso quando ritengo che il numero abbia bisogno di una descrizione (in questo caso una descrizione come "numero di delimitatori ..." è più difficile da capire rispetto al solo numero grezzo in uso).
Un'altra opzione è la logica di manipolazione separata in una funzione :
String channelId = getIdFrom(channelIdWithPath);
Questa astrazione nasconde i dettagli della manipolazione String e rimuove la necessità di un commento. Sfortunatamente dobbiamo ancora scrivere la funzione da qualche parte e lì vengono replicati i problemi originali (inclusa la necessità di documentare un percorso di esempio con un commento).
Se vogliamo dichiarare la variabile come costante E tenerla vicino alla funzione, dobbiamo creare un qualche tipo di classe StringManipulator per essa. Ora abbiamo aggiunto una classe per fare qualcosa che richiede 1 linea di codice. Mi sembra che questo tipo di approccio porti a programmi tentacolari dove
- i singoli componenti di un programma diventano più facili da capire
- la complessità strutturale e il flusso di esecuzione diventano più difficili da comprendere.
Ad esempio, se volessi leggere come viene recuperato channelId, dovrei prima passare a un altro metodo in un'altra classe, quindi dovrei saltare a dove è stata dichiarata la variabile. Tutto ciò potrebbe essere su un'unica riga di codice.
Modifica: questa risposta a una domanda simile si applica abbastanza bene per la mia particolare domanda.