Bu benim için orta ve orta seviyedeki geliştiricilerin bir noktada karşılaştıkları oldukça yaygın bir sorun gibi görünüyor: katıldıkları sözleşmeleri bilmiyorlar ya da güvenmiyorlar ve null'ları defalarca kontrol ediyorlar. Ek olarak, kendi kodlarını yazarken, arayanın boş değerleri kontrol etmesini gerektiren bir şeyi belirtmek için boş değer döndürme eğilimindedirler.
Bunu başka bir deyişle, null kontrolün ortaya çıktığı iki durum vardır:
Null'un sözleşme açısından geçerli bir yanıt olduğu durumlarda; ve
Geçerli bir yanıt olmadığı durumlarda.
(2) kolaydır. assert
İfadeleri (iddialar) kullanın veya hataya izin verin (örneğin, NullPointerException ). İddialar 1.4'te eklenen oldukça az kullanılan bir Java özelliğidir. Sözdizimi:
assert <condition>
veya
assert <condition> : <object>
burada <condition>
bir boole ifadesi ve yönteminin çıktısı hataya dahil edilecek <object>
bir nesnedir toString()
.
Koşul doğru değilse bir assert
ifade bir Error
( AssertionError
) atar . Varsayılan olarak, Java iddiaları yoksayar. Seçeneği JVM'ye ileterek onaylamaları etkinleştirebilirsiniz -ea
. Bireysel sınıflar ve paketler için onaylamaları etkinleştirebilir ve devre dışı bırakabilirsiniz. Bu, testim iddialardan herhangi bir performans etkisi olmadığını göstermesine rağmen, kodu geliştirirken ve test ederken onaylarla doğrulayabileceğiniz ve bunları bir üretim ortamında devre dışı bırakabileceğiniz anlamına gelir.
Bu durumda iddiaları kullanmamak sorun değil çünkü kod sadece başarısız olur, bu da iddiaları kullanırsanız ne olur. Tek fark, iddialarla daha erken, daha anlamlı bir şekilde ve muhtemelen ekstra bilgi ile gerçekleşebilmesidir, bu da beklemediğinizde neden olduğunu anlamanıza yardımcı olabilir.
(1) biraz daha zor. Eğer aradığınız kod üzerinde hiçbir kontrolünüz yoksa o zaman sıkışıp kalırsınız. Null geçerli bir yanıtsa, bunu kontrol etmeniz gerekir.
Bununla birlikte, kontrol ettiğiniz kod ise (ve genellikle durum buysa), o zaman farklı bir hikaye. Yanıt olarak null değerlerini kullanmaktan kaçının. Koleksiyon döndüren yöntemlerle bu kolaydır: hemen hemen boş değerler yerine boş koleksiyonlar (veya diziler) döndürün.
Toplama yapılmadığında daha zor olabilir. Bunu örnek olarak düşünün: Bu arayüzlere sahipseniz:
public interface Action {
void doSomething();
}
public interface Parser {
Action findAction(String userInput);
}
Parser, ham kullanıcı girdisi alır ve yapılacak bir şey bulur; Artık uygun bir işlem yapılmazsa sözleşmenin hükümsüz kalmasını sağlayabilirsiniz. Bu, bahsettiğiniz boş denetime yol açar.
Alternatif bir çözüm hiçbir zaman null döndürmemek ve bunun yerine Null Object desenini kullanmaktır :
public class MyParser implements Parser {
private static Action DO_NOTHING = new Action() {
public void doSomething() { /* do nothing */ }
};
public Action findAction(String userInput) {
// ...
if ( /* we can't find any actions */ ) {
return DO_NOTHING;
}
}
}
Karşılaştırmak:
Parser parser = ParserFactory.getParser();
if (parser == null) {
// now what?
// this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
// do nothing
} else {
action.doSomething();
}
için
ParserFactory.getParser().findAction(someInput).doSomething();
bu çok daha iyi bir tasarıma sahiptir çünkü daha özlü koda yol açar.
Bununla birlikte, findAction () yönteminin anlamlı bir hata mesajıyla bir İstisna atması - özellikle de kullanıcı girişine bağlı olduğunuzda - tamamen uygun olduğunu söyledi. FindAction yönteminin bir istisna atması, çağıran yöntemin açıklamasız basit bir NullPointerException ile patlatmasından çok daha iyi olur.
try {
ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
userConsole.err(anfe.getMessage());
}
Ya da dene / yakala mekanizmasının Hiçbir Şey yapmak yerine çok çirkin olduğunu düşünüyorsanız, varsayılan eyleminiz kullanıcıya geri bildirim sağlamalıdır.
public Action findAction(final String userInput) {
/* Code to return requested Action if found */
return new Action() {
public void doSomething() {
userConsole.err("Action not found: " + userInput);
}
}
}