Considero i final
parametri del metodo e le variabili locali come rumore da codice. Le dichiarazioni del metodo Java possono essere piuttosto lunghe (specialmente con i generici) - non è necessario renderle più lunghe.
Se i test unitari vengono scritti correttamente, l'assegnazione a parametri "dannosi" verrà presa, quindi non dovrebbe mai essere effettivamente un problema. La chiarezza visiva è più importante che evitare un possibile bug che non viene rilevato perché i test delle unità hanno una copertura insufficiente.
Strumenti come FindBugs e CheckStyle che possono essere configurati per interrompere la compilazione se l'assegnazione viene effettuata a parametri o variabili locali, se ti interessano profondamente di queste cose.
Naturalmente, se avete bisogno di farli finale, ad esempio perché si sta utilizzando il valore in una classe anonima, quindi non è un problema - che è la soluzione più pulita più semplice.
Oltre all'ovvio effetto dell'aggiunta di parole chiave extra ai tuoi parametri e quindi alla mimetizzazione di IMHO, l'aggiunta di parametri finali ai parametri del metodo può spesso rendere meno leggibile il codice nel corpo del metodo, il che peggiora il codice - essere "buono", codice deve essere il più leggibile e il più semplice possibile. Per un esempio inventato, supponiamo che io abbia un metodo che deve lavorare in modo insensibile al caso.
Senza final
:
public void doSomething(String input) {
input = input.toLowerCase();
// do a few things with input
}
Semplice. Pulito. Tutti sanno cosa sta succedendo.
Ora con 'final', opzione 1:
public void doSomething(final String input) {
final String lowercaseInput = input.toLowerCase();
// do a few things with lowercaseInput
}
Mentre la creazione dei parametri final
impedisce al programmatore di aggiungere codice più in basso dal pensare che stia lavorando con il valore originale, c'è un rischio uguale che il codice più in basso potrebbe usare al input
posto di lowercaseInput
, che non dovrebbe e da cui non può essere protetto, perché puoi " t prenderlo dal campo di applicazione (o anche assegnare null
a input
se ciò potrebbe aiutare comunque).
Con 'final', opzione 2:
public void doSomething(final String input) {
// do a few things with input.toLowerCase()
}
Ora abbiamo appena creato ancora più rumore di codice e introdotto un successo in termini di prestazioni che devono invocare toLowerCase()
n volte.
Con 'final', opzione 3:
public void doSomething(final String input) {
doSomethingPrivate(input.toLowerCase());
}
/** @throws IllegalArgumentException if input not all lower case */
private void doSomethingPrivate(final String input) {
if (!input.equals(input.toLowerCase())) {
throw new IllegalArgumentException("input not lowercase");
}
// do a few things with input
}
Parla del rumore del codice. Questo è un disastro ferroviario. Abbiamo un nuovo metodo, un blocco di eccezioni richiesto, perché altri codici potrebbero invocarlo in modo errato. Più unit test per coprire l'eccezione. Tutto per evitare una linea semplice, preferibile e innocua per IMHO.
C'è anche il problema che i metodi non dovrebbero essere così lunghi che non è possibile visualizzarli facilmente e sapere a colpo d'occhio che un'assegnazione al parametro ha avuto luogo.
Penso che sia una buona pratica / stile che se si assegna a un parametro lo si fa all'inizio del metodo, preferibilmente prima riga o subito dopo il controllo di input di base, sostituendolo efficacemente per l' intero metodo, che ha un effetto coerente all'interno del metodo. I lettori sanno di aspettarsi che qualsiasi compito sia ovvio (vicino alla dichiarazione della firma) e in un posto coerente, il che mitiga notevolmente il problema che l'aggiunta di final sta cercando di evitare. In realtà raramente lo assegno ai parametri, ma se lo faccio lo faccio sempre all'inizio di un metodo.
Nota anche che in final
realtà non ti protegge come potrebbe sembrare a prima vista:
public void foo(final Date date) {
date.setTime(0);
// code that uses date
}
final
non ti protegge completamente a meno che il tipo di parametro non sia primitivo o immutabile.