Saya baru saja berdiskusi tentang pilihan desain setelah ulasan kode. Saya ingin tahu apa pendapat Anda.
Ada Preferences
kelas ini , yang merupakan ember untuk pasangan nilai kunci. Nilai kosong adalah legal (itu penting). Kami berharap bahwa nilai-nilai tertentu mungkin belum disimpan, dan kami ingin menangani kasus-kasus ini secara otomatis dengan menginisialisasi mereka dengan nilai default yang telah ditentukan saat diminta.
Solusi yang dibahas menggunakan pola berikut (CATATAN: ini bukan kode aktual, jelas - ini disederhanakan untuk tujuan ilustrasi):
public class Preferences {
// null values are legal
private Map<String, String> valuesFromDatabase;
private static Map<String, String> defaultValues;
class KeyNotFoundException extends Exception {
}
public String getByKey(String key) {
try {
return getValueByKey(key);
} catch (KeyNotFoundException e) {
String defaultValue = defaultValues.get(key);
valuesFromDatabase.put(key, defaultvalue);
return defaultValue;
}
}
private String getValueByKey(String key) throws KeyNotFoundException {
if (valuesFromDatabase.containsKey(key)) {
return valuesFromDatabase.get(key);
} else {
throw new KeyNotFoundException();
}
}
}
Itu dikritik sebagai anti-pola - pengecualian menyalahgunakan untuk mengontrol aliran . KeyNotFoundException
- dihidupkan hanya untuk satu kasus penggunaan saja - tidak akan pernah terlihat di luar lingkup kelas ini.
Ini pada dasarnya adalah dua metode bermain ambil dengannya hanya untuk berkomunikasi sesuatu satu sama lain.
Kunci yang tidak ada dalam database bukanlah sesuatu yang mengkhawatirkan, atau luar biasa - kami berharap ini terjadi setiap kali pengaturan preferensi baru ditambahkan, karenanya mekanisme yang dengan anggun menginisialisasi dengan nilai default jika diperlukan.
Argumen adalah bahwa getValueByKey
- metode swasta - seperti yang didefinisikan sekarang tidak memiliki cara alami menginformasikan metode masyarakat tentang kedua nilai, dan apakah kunci itu ada. (Jika tidak, itu harus ditambahkan agar nilainya dapat diperbarui).
Pengembalian null
akan ambigu, karena null
merupakan nilai legal sempurna, jadi tidak ada yang tahu apakah itu berarti bahwa kuncinya tidak ada di sana, atau jika ada null
.
getValueByKey
harus mengembalikan semacam a Tuple<Boolean, String>
, bool diatur ke true jika kuncinya sudah ada, sehingga kita dapat membedakan antara (true, null)
dan (false, null)
. ( out
Parameter dapat digunakan dalam C #, tapi itu Java).
Apakah ini alternatif yang lebih baik? Ya, Anda harus mendefinisikan beberapa kelas penggunaan tunggal untuk efek Tuple<Boolean, String>
, tetapi kemudian kita menyingkirkan KeyNotFoundException
, sehingga saldo keluar. Kami juga menghindari overhead penanganan pengecualian, meskipun tidak signifikan dalam hal praktis - tidak ada pertimbangan kinerja untuk dibicarakan, ini adalah aplikasi klien dan tidak seperti preferensi pengguna akan diambil jutaan kali per detik.
Variasi dari pendekatan ini dapat menggunakan Jambu Biji Optional<String>
(Jambu sudah digunakan di seluruh proyek) alih-alih beberapa kebiasaan Tuple<Boolean, String>
, dan kemudian kita dapat membedakan antara Optional.<String>absent()
dan "tepat" null
. Meski begitu, masih terasa retas karena alasan yang mudah dilihat - memperkenalkan dua tingkat "ketidakberesan" tampaknya menyalahgunakan konsep yang berdiri di belakang penciptaan Optional
di tempat pertama.
Pilihan lain adalah dengan memeriksa secara eksplisit apakah kunci tersebut ada (tambahkan boolean containsKey(String key)
metode dan panggil getValueByKey
saja jika kami telah menyatakan bahwa kunci itu ada).
Akhirnya, kita juga bisa sebaris metode pribadi, tetapi sebenarnya getByKey
agak lebih kompleks daripada sampel kode saya, sehingga inlining akan membuatnya terlihat sangat buruk.
Saya mungkin membelah rambut di sini, tapi saya ingin tahu apa yang Anda bertaruh untuk menjadi yang paling dekat dengan praktik terbaik dalam kasus ini. Saya tidak menemukan jawaban dalam panduan gaya Oracle atau Google.
Apakah menggunakan pengecualian seperti dalam contoh kode merupakan anti-pola, atau apakah itu dapat diterima mengingat bahwa alternatif juga tidak terlalu bersih? Jika ya, dalam keadaan apa akan baik-baik saja? Dan sebaliknya?
getValueByKey
juga publik.