Bagi saya ini terdengar seperti masalah umum yang cenderung dihadapi oleh pengembang menengah ke menengah: mereka tidak tahu atau tidak mempercayai kontrak yang mereka ikuti dan secara defensif memeriksa nol. Selain itu, ketika menulis kode mereka sendiri, mereka cenderung mengandalkan pengembalian nol untuk menunjukkan sesuatu sehingga membutuhkan pemanggil untuk memeriksa nol.
Dengan kata lain, ada dua contoh di mana pemeriksaan nol muncul:
Di mana null adalah respons yang valid dalam hal kontrak; dan
Di mana itu bukan respons yang valid.
(2) mudah. Baik menggunakan assert
pernyataan (pernyataan) atau membiarkan kegagalan (misalnya, NullPointerException ). Pernyataan adalah fitur Java yang sangat kurang dimanfaatkan yang ditambahkan pada 1.4. Sintaksnya adalah:
assert <condition>
atau
assert <condition> : <object>
di mana <condition>
adalah ekspresi boolean dan <object>
merupakan objek yang toString()
keluaran metodenya akan dimasukkan dalam kesalahan.
Sebuah assert
pernyataan melempar Error
( AssertionError
) jika kondisi tidak benar. Secara default, Java mengabaikan pernyataan. Anda dapat mengaktifkan pernyataan dengan meneruskan opsi -ea
ke JVM. Anda dapat mengaktifkan dan menonaktifkan pernyataan untuk masing-masing kelas dan paket. Ini berarti bahwa Anda dapat memvalidasi kode dengan pernyataan sambil mengembangkan dan menguji, dan menonaktifkannya dalam lingkungan produksi, meskipun pengujian saya telah menunjukkan hampir tidak ada dampak kinerja dari pernyataan.
Tidak menggunakan pernyataan dalam kasus ini OK karena kode hanya akan gagal, yang akan terjadi jika Anda menggunakan pernyataan. Satu-satunya perbedaan adalah bahwa dengan pernyataan itu mungkin terjadi lebih cepat, dengan cara yang lebih bermakna dan mungkin dengan informasi tambahan, yang dapat membantu Anda untuk mengetahui mengapa hal itu terjadi jika Anda tidak mengharapkannya.
(1) sedikit lebih sulit. Jika Anda tidak memiliki kendali atas kode yang Anda panggil maka Anda mandek. Jika null adalah respons yang valid, Anda harus memeriksanya.
Namun, jika itu kode yang Anda kontrol (dan ini sering terjadi), maka itu adalah cerita yang berbeda. Hindari menggunakan nulls sebagai respons. Dengan metode yang mengembalikan koleksi, mudah: kembalikan koleksi kosong (atau array) alih-alih nulls sepanjang waktu.
Dengan non-koleksi mungkin lebih sulit. Pertimbangkan ini sebagai contoh: jika Anda memiliki antarmuka ini:
public interface Action {
void doSomething();
}
public interface Parser {
Action findAction(String userInput);
}
di mana Parser mengambil input pengguna mentah dan menemukan sesuatu untuk dilakukan, mungkin jika Anda mengimplementasikan antarmuka baris perintah untuk sesuatu. Sekarang Anda dapat membuat kontrak yang mengembalikan nol jika tidak ada tindakan yang sesuai. Itu mengarah nol memeriksa Anda bicarakan.
Solusi alternatif adalah tidak pernah mengembalikan null dan sebaliknya menggunakan pola Objek Null :
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;
}
}
}
Membandingkan:
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();
}
untuk
ParserFactory.getParser().findAction(someInput).doSomething();
yang merupakan desain yang jauh lebih baik karena mengarah ke kode yang lebih ringkas.
Yang mengatakan, mungkin itu sepenuhnya tepat untuk metode findAction () untuk membuang Pengecualian dengan pesan kesalahan yang bermakna - terutama dalam kasus ini di mana Anda mengandalkan input pengguna. Akan jauh lebih baik bagi metode findAction untuk melemparkan Exception daripada metode pemanggilan untuk meledakkan dengan NullPointerException sederhana tanpa penjelasan.
try {
ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
userConsole.err(anfe.getMessage());
}
Atau jika Anda berpikir mekanisme coba / tangkap terlalu jelek, daripada Jangan Melakukan apa pun, tindakan default Anda harus memberikan umpan balik kepada pengguna.
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);
}
}
}