Apakah lebih baik mengembalikan nilai NULL atau kosong dari fungsi / metode yang nilai kembaliannya tidak ada?

135

Saya mencari rekomendasi di sini. Saya berjuang dengan apakah lebih baik mengembalikan NULL atau nilai kosong dari suatu metode ketika nilai kembali tidak ada atau tidak dapat ditentukan.

Ambil dua metode berikut sebagai contoh:

string ReverseString(string stringToReverse) // takes a string and reverses it.
Person FindPerson(int personID)    // finds a Person with a matching personID.

Dalam ReverseString(), saya akan mengatakan mengembalikan string kosong karena tipe kembali adalah string, jadi pemanggil mengharapkan itu. Selain itu, dengan cara ini, penelepon tidak perlu memeriksa untuk melihat apakah NULL dikembalikan.

Dalam FindPerson(), mengembalikan NULL sepertinya lebih cocok. Terlepas dari apakah NULL atau Objek Orang kosong ( new Person()) dikembalikan, pemanggil harus memeriksa untuk melihat apakah Objek Orang NULL atau kosong sebelum melakukan sesuatu untuk itu (seperti menelepon UpdateName()). Jadi mengapa tidak mengembalikan NULL di sini dan kemudian penelepon hanya perlu memeriksa NULL.

Apakah ada orang lain yang berjuang dengan ini? Bantuan atau wawasan apa pun dihargai.

PB
sumber
2
Itu akan bervariasi. Anda juga bisa berpendapat bahwa metode ini harus menghentikan nilai yang salah di muka, misalnya parameter stringToReverse Anda diteruskan sebagai kosong atau nol. Jika Anda melakukan pemeriksaan itu (mengembalikan pengecualian), itu akan selalu mengembalikan sesuatu selain nol.
Aaron McIver
Fowler POEAA - hlm. 496 Pola Dasar - Kasus Khusus (objek nol) Bloch Java yang Efektif, Edisi ke-2 Butir 43: Kembalikan array atau koleksi kosong, bukan null
Boris Treukhov
1
@ Boris Saya tidak melihat komentar Anda. Saya sebenarnya hanya memposting Kasus Khusus sebagai jawaban.
Thomas Owens
@ Thomas Saya tidak melihat ada masalah di dalamnya :). Adapun pertanyaan itu masalah akal sehat pula.
Boris Treukhov
Sebuah komentar menarik adalah bahwa dalam database Oracle NULL dan string kosong adalah sama
WuHoUnited

Jawaban:

77

StackOverflow memiliki diskusi yang baik tentang topik yang tepat ini di T&J ini . Dalam pertanyaan berperingkat teratas, Krono mencatat:

Mengembalikan nol biasanya merupakan ide terbaik jika Anda bermaksud menunjukkan bahwa tidak ada data yang tersedia.

Objek kosong menyiratkan data telah dikembalikan, sedangkan pengembalian nol dengan jelas menunjukkan bahwa tidak ada yang dikembalikan.

Selain itu, mengembalikan nol akan menghasilkan pengecualian nol jika Anda mencoba mengakses anggota di objek, yang dapat berguna untuk menyoroti kode kereta - mencoba mengakses anggota yang tidak ada artinya tidak masuk akal. Mengakses anggota objek kosong tidak akan gagal berarti bug tidak dapat ditemukan.

Secara pribadi, saya suka mengembalikan string kosong untuk fungsi yang mengembalikan string untuk meminimalkan jumlah penanganan kesalahan yang perlu dilakukan. Namun, Anda harus memastikan bahwa grup yang bekerja dengan Anda akan mengikuti konvensi yang sama - jika tidak, manfaat dari keputusan ini tidak akan tercapai.

Namun, seperti yang dicatat oleh poster dalam jawaban SO, nulls mungkin harus dikembalikan jika suatu objek diharapkan sehingga tidak ada keraguan tentang apakah data sedang dikembalikan.

Pada akhirnya, tidak ada satu pun cara terbaik untuk melakukan sesuatu. Membangun konsensus tim pada akhirnya akan mendorong praktik terbaik tim Anda.

JW8
sumber
8
Secara pribadi, saya suka mengembalikan string kosong untuk fungsi yang mengembalikan string untuk meminimalkan jumlah penanganan kesalahan yang perlu dilakukan. Tidak pernah mengerti argumen ini. Cek nol adalah apa, paling banyak <10 karakter? Kenapa kita bersikap seperti ini yang kembali menekuk kerja?
Aaron McIver
19
Tidak ada yang mengatakan itu kembali menekuk kerja. Tapi itu adalah tenaga kerja. Itu menambah kasus khusus pada kode yang berarti satu cabang lagi untuk diuji. Plus, itu mengganggu aliran kode. for x in list_of_things() {...}bisa dibilang lebih cepat untuk grokl = list_of_things(); if l != null {...}
Bryan Oakley
5
@Bryan: ada perbedaan besar antara daftar nilai kosong, dan string kosong. String jarang mewakili daftar karakter.
kevin cline
3
@kevin cline: tentu saja. Tetapi dalam kasus string, Anda mungkin ingin string itu muncul di log apakah itu nol atau tidak. Harus memeriksa apakah itu nol sehingga Anda dapat mencetak string kosong mengaburkan maksud sebenarnya. Atau mungkin itu seperti bidang database yang berisi konten kontribusi pengguna yang ingin Anda tambahkan ke halaman web. Ini lebih mudah dilakukan emit(user.hometown)daripadaif user.hometown == null { emit("") else {emit(user.hometown)}
Bryan Oakley
1
Tidak hanya mengetik ekstra (bukan masalah besar), tetapi juga mempengaruhi keterbacaan. Saya pribadi menemukan kode dengan banyak cek yang mengganggu.
ToddR
82

Di semua kode yang saya tulis, saya menghindari kembali nulldari suatu fungsi. Saya membacanya di Clean Code .

Masalah dengan menggunakan nulladalah bahwa orang yang menggunakan antarmuka tidak tahu apakah nullitu hasil yang mungkin, dan apakah mereka harus memeriksanya, karena tidak ada not nulljenis referensi.

Di F # Anda dapat mengembalikan optiontipe, yang bisa some(Person)atau none, jadi jelas bagi pemanggil bahwa mereka harus memeriksa.

Pola C # (anti-) analog adalah Try...metode:

public bool TryFindPerson(int personId, out Person result);

Sekarang aku tahu orang mengatakan mereka membenci satu Try...pola karena memiliki parameter output istirahat ide-ide dari fungsi murni, tapi itu benar-benar tidak berbeda dari:

class FindResult<T>
{
   public FindResult(bool found, T result)
   {
       this.Found = found;
       this.Result = result;
   }

   public bool Found { get; private set; }
   // Only valid if Found is true
   public T Result { get; private set;
}

public FindResult<Person> FindPerson(int personId);

... dan jujur ​​Anda dapat mengasumsikan bahwa setiap programmer. NET tahu tentang Try...pola karena digunakan secara internal oleh .NET framework. Itu berarti mereka tidak perlu membaca dokumentasi untuk memahami apa yang dilakukannya, yang lebih penting bagi saya daripada berpegang pada pandangan beberapa fungsi purist (memahami itu resultadalah outparameter, bukan refparameter).

Jadi saya akan pergi TryFindPersonkarena Anda tampaknya menunjukkan itu sangat normal untuk tidak dapat menemukannya.

Jika, di sisi lain, tidak ada alasan logis bahwa penelepon akan memberikan personIdyang tidak ada, saya mungkin akan melakukan ini:

public Person GetPerson(int personId);

... dan kemudian saya akan melemparkan pengecualian jika itu tidak valid. The Get...awalan menyiratkan bahwa si penelepon tahu itu harus berhasil.

Scott Whitlock
sumber
28
+1, saya akan menjawab pertanyaan ini dengan referensi ke Kode Bersih jika Anda belum melakukannya. Saya suka mantra: "JIKA FUNGSI ANDA TIDAK BISA MELAKUKAN NAMA YANG DIKATAKAN, KEMUDIAN LALU PENGECUALIAN." Muuuch lebih baik daripada memeriksa null setiap lusin baris atau lebih ....
Graham
13
Saya sudah menyerah dengan asumsi apa pun tentang pengetahuan orang.
CaffGeek
5
"Masalah dengan menggunakan null adalah bahwa orang yang menggunakan antarmuka tidak tahu apakah null adalah hasil yang mungkin, dan apakah mereka harus memeriksanya, karena tidak ada jenis referensi bukan nol." Karena tipe referensi bisa nol, tidak dapatkah Anda selalu menganggap bahwa nol adalah hasil yang mungkin?
Tommy Carlier
4
Jika suatu fungsi mengembalikan sebuah pointer (C / C ++) atau referensi ke suatu objek (Java), saya selalu berasumsi bahwa itu mungkin mengembalikan null.
Giorgio
7
"Masalah dengan menggunakan null adalah bahwa orang yang menggunakan antarmuka tidak tahu apakah null adalah hasil yang mungkin, dan apakah mereka harus memeriksanya, [...]" Jika suatu metode dapat mengembalikan nol, itu harus secara eksplisit disebutkan sebagai bagian dari kontrak API.
Zsolt Török
28

Anda dapat mencoba pola Kasus Khusus Martin Fowler , dari Paterns of Enterprise Application Architecture :

Nulls adalah hal yang aneh dalam program berorientasi objek karena mereka mengalahkan polimorfisme. Biasanya Anda dapat memanggil foo secara bebas pada referensi variabel dari jenis yang diberikan tanpa khawatir tentang apakah item tersebut adalah tipe yang tepat atau sub-kelas. Dengan bahasa yang sangat diketik Anda bahkan dapat memiliki kompiler memeriksa bahwa panggilan sudah benar. Namun, karena variabel dapat berisi null, Anda dapat mengalami kesalahan runtime dengan memunculkan pesan pada null, yang akan memberi Anda jejak stack yang ramah dan bersahabat.

Jika mungkin variabel menjadi nol, Anda harus ingat untuk mengelilinginya dengan kode uji nol sehingga Anda akan melakukan hal yang benar jika ada nol. Seringkali hal yang benar sama dalam banyak konteks, sehingga Anda akhirnya menulis kode yang sama di banyak tempat - melakukan dosa duplikasi kode.

Nulls adalah contoh umum dari masalah seperti itu dan yang lainnya muncul secara teratur. Dalam sistem bilangan Anda harus berurusan dengan tak terhingga, yang memiliki aturan khusus untuk hal-hal seperti penambahan yang mematahkan invarian bilangan real yang biasa. Salah satu pengalaman awal saya dalam perangkat lunak bisnis adalah dengan pelanggan utilitas yang tidak sepenuhnya dikenal, disebut sebagai "penghuni." Semua ini secara tidak langsung mengubah perilaku tipe biasa.

Alih-alih mengembalikan nol, atau nilai ganjil, kembalikan Kasus Khusus yang memiliki antarmuka yang sama dengan apa yang diharapkan penelepon.

Thomas Owens
sumber
Saya mengalami skenario ini, tetapi hanya setelah perangkat lunak dirilis. Data pengujian saya tidak pernah memicunya, jadi agak keluar tiba-tiba dan sulit untuk debug. Meskipun saya tidak menyelesaikannya dengan pola Kasus Khusus, ada baiknya untuk menyadarinya.
samis
14

Saya akan berpikir ReverseString()akan mengembalikan string yang terbalik dan itu akan melempar IllegalArgumentExceptionjika dilewatkan dalam Null.

Saya pikir FindPerson()harus mengikuti Pola NullObject atau menaikkan pengecualian yang tidak dicentang tentang tidak menemukan sesuatu jika Anda harus selalu dapat menemukan sesuatu.

Harus berurusan Nulladalah sesuatu yang harus dihindari. Memiliki Nulldalam bahasa telah disebut Kesalahan Miliaran Dolar oleh penemunya!

Saya menyebutnya kesalahan miliaran dolar saya. Itu adalah penemuan referensi nol pada tahun 1965. Pada waktu itu, saya sedang merancang sistem tipe komprehensif pertama untuk referensi dalam bahasa berorientasi objek (ALGOL W).

Tujuan saya adalah untuk memastikan bahwa semua penggunaan referensi harus benar-benar aman, dengan pengecekan dilakukan secara otomatis oleh kompiler. Tapi saya tidak bisa menahan godaan untuk memasukkan referensi nol, hanya karena itu sangat mudah diimplementasikan.

Ini telah menyebabkan kesalahan yang tak terhitung banyaknya, kerentanan, dan crash sistem, yang mungkin telah menyebabkan satu miliar dolar rasa sakit dan kerusakan dalam empat puluh tahun terakhir.

Dalam beberapa tahun terakhir, sejumlah penganalisa program seperti PREfix dan PREfast di Microsoft telah digunakan untuk memeriksa referensi, dan memberikan peringatan jika ada risiko mereka mungkin tidak nol. Bahasa pemrograman yang lebih baru seperti Spec # telah memperkenalkan deklarasi untuk referensi bukan nol. Ini solusinya, yang saya tolak pada tahun 1965.

Tony Hoare


sumber
11

Kembalikan Opsi . Semua manfaat mengembalikan nilai tidak valid yang berbeda (seperti dapat memiliki nilai kosong di koleksi Anda) tanpa risiko NullPointerException.

hugomg
sumber
1
Menarik. Bagaimana cara mengimplementasikan opsi di Java? Dan di C ++?
Giorgio
1
@ Giorgio, Untuk Java, perpustakaan Guava, dari Google, memiliki kelas yang disebut Opsional .
Otavio Macedo
1
Untuk C ++, adaboost::optional<T>
MSalters
8

Saya melihat kedua sisi argumen ini, dan saya menyadari beberapa suara yang agak berpengaruh (misalnya, Fowler) menganjurkan tidak mengembalikan nol untuk menjaga kode tetap bersih, menghindari blok penanganan kesalahan tambahan, dll.

Namun, saya cenderung memihak pendukung untuk mengembalikan nol. Saya menemukan ada perbedaan penting dalam memohon suatu metode dan itu menanggapi dengan saya tidak punya data dan menanggapi dengan saya punya String kosong ini .

Karena saya telah melihat beberapa diskusi yang mereferensikan kelas Person, pertimbangkan skenario di mana Anda berusaha mencari instance kelas. Jika Anda memasukkan beberapa atribut finder (mis. ID), klien dapat segera memeriksa nol untuk melihat apakah tidak ada nilai yang ditemukan. Ini tidak selalu luar biasa (karenanya tidak perlu pengecualian), tetapi juga harus didokumentasikan dengan jelas. Ya, ini membutuhkan kekakuan dari pihak klien, dan tidak, saya tidak berpikir itu hal yang buruk sama sekali.

Sekarang pertimbangkan alternatif tempat Anda mengembalikan objek Orang yang valid ... yang tidak memiliki apa-apa di dalamnya. Apakah Anda meletakkan nulls di semua nilainya (nama, alamat, favoriteDrink), atau apakah Anda sekarang mengisi yang dengan objek yang valid tetapi kosong? Bagaimana klien Anda sekarang menentukan bahwa tidak ada Orang yang sebenarnya ditemukan? Apakah mereka perlu memeriksa apakah nama itu adalah String kosong dan bukan null? Bukankah hal semacam ini benar-benar akan menyebabkan sebanyak atau lebih kode kekacauan dan pernyataan kondisional daripada jika kita hanya memeriksa nol dan pindah?

Sekali lagi, ada poin di kedua sisi argumen ini yang bisa saya setujui, tetapi saya menemukan ini paling masuk akal bagi kebanyakan orang (membuat kode lebih dapat dipertahankan).

RonU
sumber
Perbedaannya adalah, "apakah FindPersonatau GetPersonmengembalikan null atau melemparkan pengecualian jika kunci tidak ada?" Sebagai pengguna API saya tidak tahu dan saya harus memeriksa dokumentasinya. Di sisi lain, bool TryGetPerson(Guid key, out Person person)tidak mengharuskan saya untuk memeriksa dokumentasi dan saya tahu pengecualian tidak dilemparkan dalam jumlah yang merupakan keadaan yang agak tidak biasa. Itulah poin yang saya coba sampaikan dalam jawaban saya.
Scott Whitlock
4
Saya pikir orang terlalu terikat pada pengecualian. Pengecualian itu buruk dan menghabiskan sumber daya. Belum lagi orang mencoba dan menangkap pernyataan tanpa menyelesaikan apa pun. Pengecualian adalah pertanda jelas bahwa ada yang salah secara fundamental. Misalnya, referensi nol melempar pengecualian, karena jelas salah untuk referensi objek nol. Adalah salah untuk menggunakannya untuk memeriksa apakah orang itu ditemukan atau tidak.
Vladimir Kocjancic
1
@VladimirKocjancic: Saya sangat setuju: pengecualian harus digunakan untuk situasi luar biasa, seperti bug perangkat lunak, kegagalan perangkat keras, kesalahan konfigurasi sistem. Jika Anda menghitung fungsi parsial (seperti findPerson) itu benar-benar normal untuk kembali tanpa hasil. Ini seharusnya tidak mengarah pada pengecualian.
Giorgio
6

Kembalikan nol jika Anda perlu tahu apakah item itu ada atau tidak. Jika tidak, kembalikan tipe data yang diharapkan. Ini terutama benar jika Anda mengembalikan daftar item. Biasanya aman untuk mengasumsikan jika penelepon menginginkan daftar, mereka ingin mengulangi daftar itu. Banyak (kebanyakan? Semua?) Bahasa gagal jika Anda mencoba untuk mengulang lebih dari nol tetapi tidak ketika Anda mengulangi daftar yang kosong.

Saya merasa frustrasi untuk mencoba dan menggunakan kode seperti ini, tetapi gagal:

for thing in get_list_of_things() {
    do_something_clever(thing)
}

Saya tidak perlu menambahkan kasus khusus untuk kasus ini ketika tidak ada barang .

Bryan Oakley
sumber
7
Dalam kasus di mana daftar atau kelompok nilai lain diharapkan, saya selalu memilih untuk mengembalikan daftar kosong, untuk alasan ini. Tindakan default (beralih melintasi daftar kosong) hampir selalu benar, dan jika tidak, pemanggil dapat secara eksplisit memeriksa untuk melihat apakah daftar itu kosong.
TMN
5

Itu tergantung pada semantik metode. Anda mungkin dapat menentukan, metode Anda hanya menerima "Bukan null". Di Java, Anda dapat menyatakan bahwa menggunakan beberapa penjelasan metadata:

string ReverseString(@NotNull String stringToReverse)

Entah bagaimana Anda harus menentukan nilai kembali. Jika Anda menyatakan, Anda hanya menerima nilai NotNull, Anda terikat untuk mengembalikan string kosong (jika inputnya juga string kosong).

Kasus kedua sedikit rumit dalam semantiknya. Jika metode ini mengembalikan seseorang dengan kunci utama (dan orang tersebut diharapkan ada), cara yang lebih baik adalah dengan melemparkan pengecualian.

Person FindPerson(int personID)

Jika Anda mencari orang dengan id tebakan (yang menurut saya aneh), Anda sebaiknya mendeklarasikan metode itu sebagai @Nullable.

Martin Vejmelka
sumber
3

Saya akan merekomendasikan menggunakan pola Obyek Null bila memungkinkan. Ini menyederhanakan kode ketika memanggil metode Anda, dan Anda tidak bisa membaca kode yang jelek

if (someObject != null && someObject.someMethod () != whateverValue)

Misalnya, jika suatu metode mengembalikan koleksi objek yang cocok dengan beberapa pola, maka mengembalikan koleksi kosong lebih masuk akal daripada kembali null, dan mengulangi koleksi kosong ini akan hampir tidak ada penalti kinerja. Kasus lain adalah metode yang mengembalikan instance kelas yang digunakan untuk mencatat data, mengembalikan objek Null daripada lebih nulldisukai menurut pendapat saya, karena tidak memaksa pengguna untuk selalu memeriksa apakah referensi yang dikembalikan adalah null.

Dalam kasus di mana pengembalian nullmasuk akal (memanggil findPerson ()metode misalnya), saya akan mencoba setidaknya memberikan metode yang mengembalikan jika objek hadir ( personExists (int personId)misalnya), contoh lain adalah containsKey ()metode pada a Mapdi Jawa). Itu membuat kode penelepon lebih bersih, karena Anda dapat dengan mudah melihat bahwa ada kemungkinan bahwa objek yang diinginkan mungkin tidak tersedia (orang tidak ada, kunci tidak ada di peta). Terus-menerus memeriksa apakah suatu referensi nullmengaburkan kode menurut pendapat saya.

Laf
sumber
3

null adalah hal terbaik untuk kembali jika dan hanya jika ketentuan berikut ini berlaku:

  • hasil nol diharapkan dalam operasi normal . Bisa diharapkan bahwa Anda mungkin tidak dapat menemukan seseorang dalam beberapa keadaan yang masuk akal, jadi findPerson () mengembalikan nol tidak masalah. Namun jika itu adalah kegagalan yang benar-benar tidak terduga (misalnya dalam fungsi yang disebut saveMyImportantData ()) maka Anda harus melempar Pengecualian. Ada petunjuk dalam namanya - Pengecualian untuk keadaan luar biasa!
  • null digunakan untuk berarti "tidak ditemukan / tidak ada nilai" . Jika Anda bermaksud sesuatu yang lain, maka kembalikan sesuatu yang lain! Contoh yang baik adalah operasi floating point yang mengembalikan Infinity atau NaN - ini adalah nilai dengan makna tertentu sehingga akan sangat membingungkan jika Anda mengembalikan nol di sini.
  • Fungsi ini dimaksudkan untuk mengembalikan nilai tunggal , seperti findPerson (). Jika itu dirancang untuk mengembalikan koleksi misalnya findAllOldPeople () maka koleksi kosong adalah yang terbaik. Akibat dari hal ini adalah bahwa fungsi yang mengembalikan koleksi tidak boleh mengembalikan nol .

Selain itu, pastikan bahwa Anda mendokumentasikan fakta bahwa fungsi tersebut dapat mengembalikan nol.

Jika Anda mengikuti aturan ini, nulls sebagian besar tidak berbahaya. Perhatikan bahwa jika Anda lupa untuk memeriksa nol, Anda biasanya akan mendapatkan NullPointerException segera setelah itu, yang biasanya merupakan bug yang cukup mudah untuk diperbaiki. Pendekatan cepat gagal ini jauh lebih baik daripada memiliki nilai balik palsu (mis. String kosong) yang disebarkan secara diam-diam di sekitar sistem Anda, mungkin merusak data, tanpa melemparkan pengecualian.

Akhirnya, jika Anda menerapkan aturan-aturan ini ke dua fungsi yang tercantum dalam pertanyaan:

  • FindPerson - akan sesuai jika fungsi ini mengembalikan nol jika orang tersebut tidak ditemukan
  • ReverseString - sepertinya tidak akan pernah gagal untuk menemukan hasil jika melewati string (karena semua string dapat dibalik, termasuk string kosong). Jadi seharusnya tidak pernah mengembalikan nol. Jika ada yang salah (kehabisan memori?) Maka itu harus membuang pengecualian.
mikera
sumber
1

Menurut pendapat saya ada perbedaan antara mengembalikan NULL, mengembalikan beberapa hasil kosong (mis. String kosong atau daftar kosong), dan melempar pengecualian.

Saya biasanya mengambil pendekatan berikut. Saya menganggap panggilan fungsi atau metode f (v1, ..., vn) sebagai aplikasi fungsi

f : S x T1 x ... x Tn -> T

di mana S itu "keadaan dunia" T1, ..., Tn adalah jenis parameter input, dan T adalah tipe pengembalian.

Saya pertama kali mencoba mendefinisikan fungsi ini. Jika fungsi ini parsial (yaitu ada beberapa nilai input yang tidak didefinisikan) saya mengembalikan NULL untuk memberi sinyal ini. Ini karena saya ingin penghentian normal dan memberi tahu saya bahwa fungsi yang saya minta tidak didefinisikan pada input yang diberikan. Menggunakan, misalnya, string kosong sebagai nilai kembali bersifat mendua karena bisa jadi fungsi tersebut didefinisikan pada input dan string kosong adalah hasil yang benar.

Saya pikir pemeriksaan tambahan untuk pointer NULL dalam kode panggilan diperlukan karena Anda menerapkan fungsi parsial dan itu adalah tugas dari metode yang dipanggil untuk memberi tahu Anda jika fungsi jika tidak didefinisikan untuk input yang diberikan.

Saya lebih suka menggunakan pengecualian untuk kesalahan yang tidak memungkinkan untuk melakukan perhitungan (yaitu tidak mungkin menemukan jawaban apa pun).

Sebagai contoh, misalkan saya memiliki Pelanggan kelas dan saya ingin menerapkan metode

Customer findCustomer(String customerCode)

untuk mencari pelanggan dalam database aplikasi dengan kodenya. Dalam metode ini, saya akan melakukannya

  • Kembalikan objek Pelanggan kelas jika kueri berhasil,
  • Kembalikan nol jika kueri tidak menemukan pelanggan.
  • Lempar pengecualian jika tidak mungkin terhubung ke database.

Pemeriksaan tambahan untuk null, misalnya

Customer customer = findCustomer("...");
if (customer != null && customer.getOrders() > 0)
{
    ...
}

adalah bagian dari semantik dari apa yang saya lakukan dan saya tidak akan hanya "melewatkannya" untuk membuat kode lebih baik dibaca. Saya tidak berpikir itu adalah praktik yang baik untuk menyederhanakan semantik masalah yang ada hanya untuk menyederhanakan kode.

Tentu saja, karena pemeriksaan untuk null sangat sering terjadi, ada baiknya jika bahasa tersebut mendukung beberapa sintaks khusus untuk itu.

Saya juga akan mempertimbangkan untuk menggunakan pola Objek Null (seperti yang disarankan oleh Laf) selama saya dapat membedakan objek nol kelas dari semua objek lainnya.

Giorgio
sumber
0

Metode mengembalikan koleksi harus dikembalikan kosong tetapi yang lain bisa mengembalikan nol, karena untuk koleksi itu mungkin terjadi bahwa Anda akan memiliki objek tetapi tidak ada elemen di dalamnya, sehingga penelepon akan memvalidasi untuk ukuran yang adil, bukan keduanya.

Phani
sumber
0

Bagi saya ada dua kasus di sini. Jika Anda mengembalikan semacam daftar, Anda harus selalu mengembalikan daftar itu bagaimanapun caranya, kosongkan jika Anda tidak memiliki apa pun untuk dimasukkan ke dalamnya.

Satu-satunya kasus di mana saya melihat perdebatan adalah ketika Anda mengembalikan satu item. Saya menemukan diri saya lebih memilih untuk mengembalikan nol jika terjadi kegagalan dalam situasi seperti itu atas dasar membuat semuanya gagal dengan cepat.

Jika Anda mengembalikan objek nol dan penelepon membutuhkan objek nyata, mereka mungkin melanjutkan dan mencoba menggunakan objek nol yang menghasilkan perilaku tak terduga. Saya pikir lebih baik bagi rutinitas untuk menjadi booming jika mereka lupa berurusan dengan situasi. Jika ada yang salah, saya ingin pengecualian ASAP. Anda cenderung mengirimkan bug dengan cara ini.

Loren Pechtel
sumber
0

Menambahkan apa yang sudah dikatakan orang tentang Maybekonstruktor tipe:

Keuntungan besar lainnya, selain tidak membahayakan NPE, adalah keuntungan semantik. Di dunia fungsional, di mana kita berurusan dengan fungsi murni, kami ingin mencoba membuat fungsi yang ketika diterapkan persis sama dengan nilai pengembaliannya . Pertimbangkan kasus String.reverse(): Ini adalah fungsi yang diberikan string tertentu mewakili versi terbalik dari string itu. Kita tahu bahwa string ini ada, karena setiap string dapat dibalik (string pada dasarnya adalah kumpulan karakter yang diatur).

Sekarang bagaimana findCustomer(int id)? Fungsi ini mewakili pelanggan yang memiliki ID yang diberikan. Ini adalah sesuatu yang mungkin ada atau tidak ada. Tapi ingat, fungsi memiliki nilai pengembalian tunggal, jadi Anda tidak bisa mengatakan "fungsi ini mengembalikan pelanggan dengan ID yang diberikan ATAU mengembalikan null.

Ini adalah masalah utama saya baik dengan mengembalikan nulldan mengembalikan objek nol. Mereka menyesatkan. nulljuga bukan pelanggan, dan juga bukan "tidak adanya pelanggan". Tidak adanya APA SAJA. Ini hanya pointer yang tidak berguna untuk TIDAK ADA. Tingkat sangat rendah dan sangat jelek dan sangat rawan kesalahan. Objek nol juga cukup menyesatkan di sini saya pikir. Pelanggan nol adalah pelanggan. Ini bukan tidak adanya satu, itu bukan pelanggan dengan ID yang diminta, jadi mengembalikannya hanya SALAH. Ini BUKAN pelanggan yang saya minta, tapi tetap saja Anda mengklaim telah mengembalikan pelanggan. Ini memiliki ID yang salah, jelas ini adalah bug. Itu melanggar kontrak yang disarankan oleh nama metode dan tanda tangan. Ini memerlukan kode klien untuk mengasumsikan hal-hal tentang desain Anda, atau membaca dokumentasi.

Kedua masalah ini diselesaikan oleh a Maybe Customer. Tiba-tiba, kami tidak mengatakan "fungsi ini mewakili pelanggan dengan ID yang diberikan". Kami mengatakan "fungsi ini mewakili pelanggan dengan ID yang diberikan jika ada . Sekarang sangat jelas dan eksplisit tentang apa yang dilakukannya. Jika Anda meminta pelanggan dengan ID yang tidak ada, Anda akan menerima Nothing. Bagaimana ini lebih baik daripada null? Bukan hanya untuk risiko NPE, tetapi juga karena jenisnya Nothingtidak adil Maybe. Itu Maybe Customermemiliki makna semantik. Secara khusus berarti "tidak adanya pelanggan", menunjukkan bahwa pelanggan seperti itu tidak ada.

Masalah lain dengan null tentu saja adalah ambigu. Apakah itu karena Anda tidak menemukan pelanggan, atau adakah kesalahan koneksi db atau saya hanya tidak diizinkan untuk melihat pelanggan itu?

Jika Anda memiliki beberapa kasus kesalahan seperti ini untuk ditangani, Anda bisa melempar pengecualian untuk versi tersebut atau (dan saya lebih suka cara ini) Anda bisa mengembalikan Either CustomerLoadError Customer, mewakili sesuatu yang salah atau pelanggan yang kembali. Ini memiliki semua kelebihan Maybe Customerdan juga memungkinkan Anda menentukan apa yang salah.

Hal utama yang saya kejar adalah untuk menangkap kontrak fungsi dalam tanda tangan itu. Jangan menganggap hal-hal, jangan mengandalkan konvensi singkat, menjadi eksplisit.

sara
sumber
0

1) Jika semantik fungsi adalah bahwa ia tidak dapat mengembalikan apa-apa, pemanggil HARUS menguji untuk itu, kalau tidak ia akan misalnya. ambil uangmu dan berikan kepada siapa pun.

2) Ada baiknya membuat fungsi yang secara semantik selalu mengembalikan sesuatu (atau melempar).

Dengan logger , masuk akal untuk mengembalikan logger yang tidak mencatat jika tidak ada logger yang didefinisikan. Saat mengembalikan koleksi, hampir tidak pernah masuk akal (kecuali pada "level cukup rendah", di mana koleksi itu sendiri adalah data, bukan apa yang dikandungnya) untuk tidak mengembalikan apa-apa, karena set kosong adalah set, bukan apa-apa.

Dengan contoh orang , saya akan pergi "hibernate" cara (dapatkan vs load, IIRC, tetapi ada rumit oleh objek proxy untuk pemuatan malas) memiliki dua fungsi, satu yang mengembalikan nol dan yang kedua melempar.

pengguna470365
sumber
-1
  • NULL harus dikembalikan jika aplikasi mengharapkan data tersedia tetapi datanya tidak tersedia. Misalnya, layanan yang mengembalikan CITY berdasarkan kode pos harus mengembalikan nol jika kota tidak ditemukan. Penelepon kemudian dapat memutuskan untuk menangani null atau meledak.

  • Daftar kosong harus dikembalikan jika ada dua kemungkinan. Data tersedia atau TIDAK ada data. Misalnya layanan yang mengembalikan KOTA jika populasinya lebih besar dari jumlah tertentu. Ini dapat mengembalikan daftar kosong jika Tidak ada data yang memenuhi kriteria yang diberikan.

java_mouse
sumber
-2

Mengembalikan NULL adalah desain yang mengerikan , di dunia berorientasi objek. Singkatnya, penggunaan NULL mengarah ke:

  • penanganan kesalahan ad-hoc (bukan pengecualian)
  • semantik ambigu
  • lambat bukannya gagal cepat
  • pemikiran komputer vs pemikiran objek
  • benda yang bisa berubah dan tidak lengkap

Periksa posting blog ini untuk penjelasan terperinci: http://www.yegor256.com/2014/05/13/why-null-is-bad.html

yegor256
sumber