Saya menganggap final
dalam parameter metode dan variabel lokal menjadi noise kode. Deklarasi metode Java bisa sangat panjang (terutama dengan obat generik) - tidak perlu membuatnya lagi.
Jika unit test ditulis dengan benar, menugaskan ke parameter yang "berbahaya" akan diambil, jadi seharusnya tidak pernah benar - benar menjadi masalah. Kejelasan visual lebih penting daripada menghindari kemungkinan bug yang tidak diambil karena unit test Anda memiliki cakupan yang tidak memadai.
Alat-alat seperti FindBugs dan CheckStyle yang dapat dikonfigurasikan untuk memecah bangunan jika tugas dibuat untuk parameter atau variabel lokal, jika Anda sangat peduli tentang hal-hal seperti itu.
Tentu saja, jika Anda perlu membuatnya final, misalnya karena Anda menggunakan nilai dalam kelas anonim, maka tidak ada masalah - itu solusi paling sederhana yang paling bersih.
Terlepas dari efek yang jelas dari menambahkan kata kunci tambahan ke parameter Anda, dan dengan demikian IMHO menyamarkannya, menambahkan parameter akhir ke metode sering dapat membuat kode dalam tubuh metode menjadi kurang mudah dibaca, yang membuat kode lebih buruk - menjadi "baik", kode harus mudah dibaca dan sesederhana mungkin. Sebagai contoh buat-buat, katakan saya punya metode yang perlu bekerja kasus tidak sensitif.
Tanpa final
:
public void doSomething(String input) {
input = input.toLowerCase();
// do a few things with input
}
Sederhana. Bersih. Semua orang tahu apa yang terjadi.
Sekarang dengan 'final', opsi 1:
public void doSomething(final String input) {
final String lowercaseInput = input.toLowerCase();
// do a few things with lowercaseInput
}
Sementara membuat parameter final
menghentikan kode menambahkan kode lebih jauh ke bawah dari berpikir dia bekerja dengan nilai asli, ada risiko yang sama bahwa kode lebih lanjut dapat menggunakan input
alih-alih lowercaseInput
, yang seharusnya tidak dan yang tidak dapat dilindungi, karena Anda bisa ' t membawanya keluar dari ruang lingkup (atau bahkan menetapkan null
untuk input
jika itu bahkan akan membantu pula).
Dengan 'final', opsi 2:
public void doSomething(final String input) {
// do a few things with input.toLowerCase()
}
Sekarang kami baru saja membuat lebih banyak noise kode dan memperkenalkan performa yang baik karena harus meminta toLowerCase()
n kali.
Dengan 'final', opsi 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
}
Bicara tentang kebisingan kode. Ini adalah kecelakaan kereta api. Kami punya metode baru, blok pengecualian yang diperlukan, karena kode lain mungkin salah memanggilnya. Lebih banyak unit test untuk mencakup pengecualian. Semua untuk menghindari satu garis sederhana, dan IMHO lebih disukai dan tidak berbahaya.
Ada juga masalah bahwa metode tidak boleh terlalu lama sehingga Anda tidak dapat dengan mudah menerimanya secara visual dan mengetahui sekilas bahwa penugasan ke parameter telah terjadi.
Saya pikir itu adalah praktik / gaya yang baik bahwa jika Anda menetapkan ke parameter Anda melakukannya setiap awal dalam metode, lebih disukai baris pertama atau langsung setelah pengecekan input dasar, secara efektif menggantikannya untuk seluruh metode, yang memiliki efek konsisten dalam metode. Pembaca tahu untuk mengharapkan penugasan apa pun menjadi jelas (dekat deklarasi tanda tangan) dan di tempat yang konsisten, yang sangat memitigasi masalah yang ingin dihindari dengan menambahkan tugas akhir. Sebenarnya saya jarang menetapkan parameter, tetapi jika saya melakukannya saya selalu melakukannya di bagian atas metode.
Perhatikan juga bahwa final
sebenarnya tidak melindungi Anda seperti itu mungkin pada awalnya tampak:
public void foo(final Date date) {
date.setTime(0);
// code that uses date
}
final
tidak sepenuhnya melindungi Anda kecuali tipe parameternya primitif atau tidak dapat diubah.