Kod incelemesinden sonra bir tasarım seçimi hakkında bir tartışma yaptım. Düşüncelerinizin ne olduğunu merak ediyorum.
Preferences
Anahtar-değer çiftleri için bir kova olan bu sınıf var . Boş değerler yasaldır (bu önemlidir). Bazı değerlerin henüz kaydedilmeyebileceğini düşünüyoruz ve talep edildiğinde bu vakaları önceden tanımlanmış varsayılan değerle başlatarak otomatik olarak ele almak istiyoruz.
Aşağıdaki modeli kullanılan tartışılan çözüm (NOT: Bu gerçek kod değil , açıkçası - açıklama amaçlı basitleştirilmiştir):
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();
}
}
}
Akışı kontrol altına almak için istismar edici istisnalar hariç tutuldu . KeyNotFoundException
- sadece bir kullanım durumu için hayata geçirildi - asla bu sınıfın kapsamı dışında görülmeyecek.
Sadece beraberinde bir şeyler iletmek için getirme oynayan iki yöntemdir.
Veritabanında bulunmayan anahtar, endişe verici bir durum değildir veya istisnai bir durum değildir - bunun, yeni bir tercih ayarı eklendiğinde gerçekleşmesini bekliyoruz;
Buna karşılık, şu getValueByKey
anda tanımlandığı gibi - özel yöntem - kamu yöntemini hem değer hakkında hem de anahtarın orada olup olmadığı konusunda bilgilendirmenin doğal bir yoluydu . (Değilse, değerin güncellenebilmesi için eklenmelidir).
Geri dönüş null
belirsiz olacaktır, çünkü null
tamamen yasal bir değerdir, dolayısıyla anahtarın orada olup olmadığı veya a olup olmadığına dair hiçbir şey söylenemez null
.
getValueByKey
Bir çeşit dönmek zorunda kalacak Tuple<Boolean, String>
biz ayırt edebilir böylece, anahtar zaten varsa, true olarak ayarlanır bool (true, null)
ve (false, null)
. (Bir out
parametre C # ile kullanılabilir, ancak bu Java'dır).
Bu daha iyi bir alternatif mi? Evet, bazı tek kullanımlık sınıfları bunun etkisine göre tanımlamak Tuple<Boolean, String>
zorunda kalacaksınız, fakat o zaman bu durumdan kurtulmak için bundan kurtulacağız KeyNotFoundException
. Ayrıca, bir istisna sorununu da önlüyoruz, ancak pratik açıdan anlamlı olmasa da - konuşacak performans kaygıları yok, bir istemci uygulaması ve kullanıcı tercihlerinin saniyede milyonlarca kez alınacağı gibi değil.
Bu yaklaşımın bir çeşitlemesi Optional<String>
bazı özel yerine Guava'yı (Guava zaten proje boyunca kullanılıyor) Tuple<Boolean, String>
kullanabilir ve ardından Optional.<String>absent()
"uygun" ile farklılaşabiliriz null
. Yine de, kolay anlaşılır nedenlerden ötürü çılgınca geliyor - iki seviyeli "sıfırlık" vermek Optional
, ilk başta s yaratmanın ardında yatan kavramı kötüye kullanıyor gibi görünüyor .
Başka bir seçenek, anahtarın var olup olmadığını açıkça kontrol etmek olacaktır (bir boolean containsKey(String key)
yöntem ekleyin ve getValueByKey
sadece zaten var olduğunu iddia ettiğimizde arayın ).
Sonunda, kişi özel yöntemi de satırlandırabilir, ancak gerçek getByKey
kod örneğimden biraz daha karmaşıktır, bu nedenle satır içi oluşturma işlemi oldukça kötü görünmesini sağlar.
Burada kılları ayırıyor olabilirim, ama bu durumda en iyi uygulamaya en yakın olmak için neye bahse gireceğinizi merak ediyorum. Oracle’ın veya Google’ın stil kılavuzlarında bir cevap bulamadım.
Kod örneğindeki gibi istisnalar anti-patern mi kullanıyor yoksa alternatiflerin de çok temiz olmadığı kabul edilebilir mi? Öyleyse, hangi koşullar altında iyi olurdu? Ve tam tersi?
getValueByKey
de kamuya açık olduğunda sorunun daha ilginç hale geldiğini düşünüyorum .