Apakah mengembalikan desain buruk nol? [Tutup]

127

Saya pernah mendengar beberapa suara mengatakan bahwa memeriksa nilai null yang dikembalikan dari metode adalah desain yang buruk. Saya ingin mendengar beberapa alasan untuk ini.

kodesemu:

variable x = object.method()
if (x is null) do something
koen
sumber
13
Rumit: di mana orang-orang ini yang mengatakan itu buruk? Tautan?
jcollum
2
Jika metode ini adalah sesuatu yang Anda kontrol, Anda dapat memiliki unit test untuk memastikan tidak pernah mengembalikan nol, jika tidak, saya tidak melihat mengapa itu akan menjadi praktik yang buruk untuk memeriksa apakah itu nol, setelah panggilan itu; mungkin praktik buruk pada metode itu untuk mengembalikan nol, tetapi Anda harus melindungi kode Anda
BlackTigerX
9
Memunculkan pengecualian hanya karena tidak ada data yang dikembalikan sangat menjengkelkan. Alur program yang normal seharusnya tidak membuang pengecualian.
Thorarin
4
@ David: Itulah yang benar-benar saya katakan. Jika suatu metode mengembalikan data, tetapi tidak ada, itu berarti ada sesuatu yang salah. Itu tidak aliran program normal :)
Thorarin
2
@Torarin: alur program "normal" adalah konsep yang dapat diregangkan: bukan dasar yang kuat untuk sebuah argumen.
Tomislav Nakic-Alfirevic

Jawaban:

206

Alasan di balik tidak mengembalikan nol adalah bahwa Anda tidak perlu memeriksanya dan karenanya kode Anda tidak perlu mengikuti jalur yang berbeda berdasarkan nilai pengembalian. Anda mungkin ingin memeriksa Pola Objek Null yang memberikan informasi lebih lanjut tentang ini.

Misalnya, jika saya mendefinisikan metode di Jawa yang mengembalikan Koleksi, saya biasanya lebih suka mengembalikan koleksi kosong (yaitu Collections.emptyList()) daripada nol karena itu berarti kode klien saya lebih bersih; misalnya

Collection<? extends Item> c = getItems(); // Will never return null.

for (Item item : c) { // Will not enter the loop if c is empty.
  // Process item.
}

... yang lebih bersih dari:

Collection<? extends Item> c = getItems(); // Could potentially return null.

// Two possible code paths now so harder to test.
if (c != null) {
  for (Item item : c) {
    // Process item.
  }
}
Adamski
sumber
6
Ya, jauh lebih baik daripada mengembalikan nol dan berharap klien ingat untuk menangani kasus ini.
djna
10
Saya dengan senang hati setuju bahwa mengembalikan nol adalah gila ketika digunakan sebagai pengganti wadah kosong (atau string). Tapi itu bukan kasus umum.
MSalters
2
+1 untuk Pola Objek Null untuk saya juga. Juga ketika saya benar-benar ingin mengembalikan null, saya telah memberi nama metode seperti getCustomerOrNull () untuk membuatnya eksplisit. Saya pikir sebuah metode dinamai dengan baik ketika pembaca tidak ingin melihat implementasinya.
Mike Valenty
4
Komentar '// Dua kemungkinan jalur kode sekarang' tidak benar; Anda memiliki dua jalur kode dengan cara apa pun. Namun, dengan objek Koleksi nol dalam contoh pertama Anda, jalur kode 'null' lebih pendek. Anda masih memiliki dua jalur, dan Anda masih perlu menguji dua jalur.
Frerich Raabe
1
@MSalters - bisa dibilang setiap variabel dalam bahasa OO nulladalah "wadah", yang berisi nol atau satu pointer ke objek. (Yang pasti bagaimana itu secara eksplisit dimodelkan oleh Haskell Maybedalam kasus-kasus itu, dan semuanya lebih baik untuk melakukannya.)
Andrzej Doyle
71

Inilah alasannya.

Dalam Clean Code oleh Robert Martin ia menulis bahwa mengembalikan null adalah desain yang buruk ketika Anda dapat kembali, katakanlah, array kosong. Karena hasil yang diharapkan adalah array, mengapa tidak? Ini akan memungkinkan Anda untuk mengulangi hasil tanpa kondisi tambahan. Jika bilangan bulat, mungkin 0 akan cukup, jika hash, hash kosong. dll.

Premisnya adalah untuk tidak memaksa kode panggilan untuk segera menangani masalah. Kode panggilan mungkin tidak ingin peduli dengan mereka. Itu juga mengapa dalam banyak kasus pengecualian lebih baik daripada nol.

Max Chernyak
sumber
2
Ini adalah Pola Objek Null yang disebutkan dalam jawaban ini: stackoverflow.com/questions/1274792/...
Scott Dorman
Idenya di sini adalah bahwa pada kesalahan, Anda mengembalikan versi kosong / kosong dari jenis objek apa pun yang Anda akan kembali secara normal. Sebuah array atau string kosong akan berfungsi untuk kasus-kasus itu, misalnya. Mengembalikan "NULL" tepat ketika Anda biasanya mengembalikan pointer (karena NULL pada dasarnya adalah pointer kosong). Mengembalikan NULL pada kesalahan dari fungsi yang biasanya mengembalikan, katakanlah, hash dapat membingungkan. Beberapa bahasa menangani ini lebih baik daripada yang lain tetapi secara umum, konsistensi adalah praktik terbaik.
bta
Anda tidak perlu kembali kesalahan, kecuali kesalahannya entah bagaimana mengendalikan aliran (yang bukan praktik yang baik) atau diabstraksi dalam API atau antarmuka. Ada kesalahan untuk menyebar ke tingkat mana Anda memutuskan untuk menangkapnya, maka Anda tidak harus menghadapinya dalam konteks panggilan. Mereka secara default null-object-pattern-friendly.
Max Chernyak
Sayangnya, kode panggilan tidak selalu menganggap case koleksi kosong (seperti itu tidak mempertimbangkan case null). Itu mungkin atau mungkin tidak menjadi masalah.
Sridhar Sarnobat
38

Penggunaan kembali null dengan baik:

  • Jika null adalah hasil fungsional yang valid , misalnya: FindFirstObjectThatNeedsProcessing () dapat mengembalikan nol jika tidak ditemukan dan penelepon harus memeriksa sesuai.

Penggunaan buruk: Mencoba mengganti atau menyembunyikan situasi luar biasa seperti:

  • menangkap (...) dan mengembalikan nol
  • Inisialisasi dependensi API gagal
  • Kehabisan ruang disk
  • Parameter input tidak valid (kesalahan pemrograman, input harus disanitasi oleh pemanggil)
  • dll

Dalam kasus tersebut, melemparkan pengecualian lebih memadai karena:

  • Nilai pengembalian nol tidak memberikan info kesalahan yang berarti
  • Penelepon langsung kemungkinan besar tidak dapat menangani kondisi kesalahan
  • Tidak ada jaminan bahwa penelepon memeriksa hasil nol

Namun, Pengecualian tidak boleh digunakan untuk menangani kondisi operasi program normal seperti:

  • Nama pengguna / kata sandi salah (atau input yang disediakan pengguna)
  • Memutuskan loop atau sebagai goto non-lokal
ZeroConcept
sumber
7
"Nama pengguna tidak valid" tampaknya merupakan alasan yang bagus untuk Pengecualian.
Thilo
11
Pengguna yang memasukkan login / kata sandi yang tidak valid tidak boleh diperlakukan sebagai kondisi luar biasa, bagian dari operasi program normal. Namun, sistem otentikasi gagal merespons (misalnya direktori aktif) adalah kondisi yang luar biasa.
ZeroConcept
2
Saya akan mengatakan itu tergantung: boolean login(String,String)tampaknya baik-baik sajaAuthenticationContext createAuthContext(String,String) throws AuthenticationException
sfussenegger
1
Dalam contoh Anda, jika tidak ada objek pertama yang perlu diproses, maka ada dua cara yang masuk akal untuk menangani kasus itu. Yang pertama adalah pola Obyek Null. Buat subclass terakhir yang mewakili versi kelas yang tidak ada. Ini memiliki default yang wajar dan melempar pengecualian ketika diminta tindakan nonsense. Teknik lainnya adalah Opsi. Inilah yang tersedia di Java8 dan Scala. Salah satu dari ini menunjukkan niat pengembang. null tidak dapat menunjukkan niat karena memiliki banyak kemungkinan arti. ** Menunjukkan Intent ** adalah aspek kode yang paling penting.
scott m gardner
29

Ya, 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, bukan 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 . Lebih banyak di buku saya Elegant Objects , Bagian 4.1.

yegor256
sumber
2
Saya sangat setuju. Saya bahkan tidak suka pola objek nol yang tampaknya merupakan taktik penundaan 'kapur'. Entah metode Anda seharusnya selalu berhasil atau mungkin tidak. Jika harus selalu berhasil, maka lempar. Jika hal itu mungkin tidak berhasil, kemudian merancang metode sehingga konsumen tahu, misalnya bool TryGetBlah(out blah)atau FirstOrNull()atau MatchOrFallback(T fallbackValue).
Luke Puplett
Saya juga tidak suka mengembalikan null. Anda memisahkan akar penyebab dari gejala, mempersulit proses debug. Entah melempar pengecualian (gagal cepat), atau memanggil metode pemeriksa yang mengembalikan boolean terlebih dahulu (misalnya isEmpty()) dan hanya jika itu benar maka panggil metode tersebut. Orang-orang berdebat dengan yang ke-2 mengatakan itu adalah kinerja yang lebih buruk - tetapi seperti yang dikatakan Unix Philosophy, "nilai waktu manusia dari waktu ke waktu mesin" (yaitu, kinerja yang lebih lambat secara sepele menghabiskan waktu lebih sedikit daripada pengembang kode debugging yang memberikan kesalahan palsu).
Sridhar Sarnobat
22

Siapa bilang desain ini jelek?

Memeriksa nol adalah praktik yang umum, bahkan dianjurkan, jika tidak Anda berisiko NullReferenceExceptions di mana-mana. Lebih baik menangani kesalahan dengan anggun daripada melemparkan pengecualian saat Anda tidak perlu melakukannya.

Brandon
sumber
11
+1. Kode yang melempar pengecualian untuk masalah yang dapat dikurangi di tempat membuat saya sedih.
jkeys
6
Seberapa sedih Anda dapatkan ketika coders lupa memeriksa nol dan kemudian mendapatkan pengecualian null pointer misterius? Pengecualian diperiksa, di mana kompiler mengingatkan pengguna mereka tidak berurusan dengan kondisi kesalahan menghindari kelas kesalahan pengkodean.
djna
3
@djna: Saya kira ini juga menyedihkan tetapi saya telah menemukan bahwa jenis coders yang sama yang "lupa" untuk memeriksa null adalah orang-orang yang ketika berhadapan dengan pengecualian yang diperiksa sering berakhir dengan menelannya.
Randy mendukung Monica
5
Lebih mudah untuk menemukan keberadaan blok tangkap kosong daripada tidak adanya cek kosong.
Preston
20
@ Preston: Saya sangat tidak setuju. Tidak ada pemeriksaan nol yang akan Anda temukan segera, saat crash. Pengecualian yang tertelan dapat menyebabkan kesalahan misterius dan halus selama bertahun-tahun ...
Beska
18

Berdasarkan apa yang Anda katakan sejauh ini, saya pikir tidak ada informasi yang cukup.

Mengembalikan nol dari metode CreateWidget () tampaknya buruk.

Mengembalikan nol dari metode FindFooInBar () tampaknya baik-baik saja.

jcollum
sumber
4
Mirip dengan konvensi saya: Pertanyaan item tunggal - Create... mengembalikan instance baru, atau melempar ; Get...mengembalikan contoh yang ada yang ada, atau melempar ; GetOrCreate...mengembalikan instance yang ada, atau instance baru jika tidak ada, atau melempar ; Find...mengembalikan contoh yang ada, jika ada, ataunull . Untuk kueri koleksi - Get... selalu mengembalikan koleksi, yang kosong jika tidak ada item yang cocok ditemukan.
Johann Gerell
NULL buruk karena alasan yang diberikan dalam jawaban yegor256 & hakuinin, mengembalikan objek yang valid tetapi kosong menyederhanakan penalaran overal
Rob11311
12

Penemunya mengatakan ini adalah kesalahan satu miliar dolar!

Bahadır Yağan
sumber
10

Itu tergantung pada bahasa yang Anda gunakan. Jika Anda menggunakan bahasa seperti C # di mana cara idiomatis untuk menunjukkan kurangnya nilai adalah mengembalikan nol, maka mengembalikan nol adalah desain yang baik jika Anda tidak memiliki nilai. Atau, dalam bahasa seperti Haskell yang secara idiomatis menggunakan Mungkin monad untuk kasus ini, maka mengembalikan null akan menjadi desain yang buruk (jika itu mungkin).

Greg Beech
sumber
2
+1 untuk menyebutkan mungkin monad. Saya menemukan definisi nulldalam bahasa-bahasa seperti C # dan Java sering kelebihan beban dan diberi makna dalam domain. Jika Anda mencari nullkata kunci dalam spesifikasi bahasa, itu berarti "penunjuk yang tidak valid". Kemungkinan itu tidak ada artinya dalam domain masalah apa pun.
MattDavey
Masalahnya adalah Anda tidak tahu apakah itu "nilai yang hilang" nullatau "tidak diinisialisasi"null
CervEd
5

Jika Anda membaca semua jawaban, menjadi jelas jawaban untuk pertanyaan ini tergantung pada jenis metode.

Pertama, ketika sesuatu yang luar biasa terjadi (masalah IO dll), secara logis pengecualian dilemparkan. Ketika sesuatu yang luar biasa mungkin adalah sesuatu untuk topik yang berbeda ..

Setiap kali suatu metode diharapkan tidak memiliki hasil, ada dua kategori:

  • Jika mungkin untuk mengembalikan nilai netral, lakukanlah .
    Enumrables kosong, string dll adalah contoh yang bagus
  • Jika nilai netral seperti itu tidak ada, null harus dikembalikan .
    Seperti yang disebutkan, metode ini dianggap tidak memiliki hasil, sehingga tidak luar biasa, oleh karena itu tidak boleh membuang pengecualian. Nilai netral tidak dimungkinkan (misalnya: 0 tidak terutama merupakan hasil netral, tergantung pada program)

Sampai kita memiliki cara resmi untuk menyatakan bahwa suatu fungsi dapat atau tidak dapat mengembalikan nol, saya mencoba untuk memiliki konvensi penamaan untuk menyatakan demikian.
Seperti halnya Anda memiliki konvensi Try Something () untuk metode yang diharapkan gagal, saya sering memberi nama metode saya Safe Something () ketika metode mengembalikan hasil netral alih-alih nol.

Saya belum sepenuhnya setuju dengan namanya, tetapi tidak dapat menemukan yang lebih baik. Jadi saya menjalankannya untuk saat ini.

Boris Callens
sumber
4

Saya memiliki kebaktian di daerah ini yang sangat membantu saya

Untuk kueri item tunggal:

  • Create...mengembalikan contoh baru, atau melempar
  • Get...mengembalikan contoh yang ada yang ada, atau melempar
  • GetOrCreate...mengembalikan instance yang ada, atau instance baru jika tidak ada, atau melempar
  • Find...mengembalikan contoh yang ada, jika ada, ataunull

Untuk kueri koleksi:

  • Get... selalu mengembalikan koleksi, yang kosong jika tidak ada barang yang cocok [1] ditemukan

[1] diberi beberapa kriteria, eksplisit atau implisit, diberikan dalam nama fungsi atau sebagai parameter.

Johann Gerell
sumber
Mengapa GetOne dan FindOne kembali berbeda jika tidak ditemukan?
Vladimir Vukanac
Saya menggambarkan perbedaannya. Saya menggunakan Getketika saya mengharapkannya ada di sana, sehingga jika tidak ada di sana, maka itu adalah kesalahan dan saya lempar - saya tidak perlu memeriksa nilai kembali. Saya menggunakan Findjika saya benar-benar tidak tahu apakah itu ada atau tidak - maka saya perlu memeriksa nilai kembali.
Johann Gerell
3

Pengecualian adalah pengecualian untuk semua keadaan.

Jika fungsi Anda dimaksudkan untuk menemukan atribut yang terkait dengan objek yang diberikan, dan objek itu memang tidak memiliki atribut seperti itu, mungkin tepat untuk mengembalikan nol. Jika objek tidak ada, melempar pengecualian mungkin lebih tepat. Jika fungsi ini dimaksudkan untuk mengembalikan daftar atribut, dan tidak ada yang mengembalikan, mengembalikan daftar kosong masuk akal - Anda mengembalikan semua atribut nol.


sumber
1
Jika Anda mencoba menggunakan atribut tanpa nilai, itu pantas dikecualikan. (Saya berasumsi spec Anda mengatakan atributnya opsional.) Memiliki metode terpisah untuk memeriksa apakah nilainya telah ditetapkan.
Preston
3

Tidak apa-apa untuk mengembalikan nol jika hal itu bermakna dalam beberapa cara:

public String getEmployeeName(int id){ ..}

Dalam kasus seperti ini, sangat penting untuk mengembalikan nol jika id tidak sesuai dengan entitas yang ada, karena memungkinkan Anda untuk membedakan kasus di mana tidak ada kecocokan yang ditemukan dari kesalahan yang sah.

Orang mungkin berpikir ini buruk karena dapat disalahgunakan sebagai nilai pengembalian "khusus" yang menunjukkan kondisi kesalahan, yang tidak begitu baik, sedikit seperti mengembalikan kode kesalahan dari suatu fungsi tetapi membingungkan karena pengguna harus memeriksa pengembalian untuk null, alih-alih menangkap pengecualian yang sesuai, mis

public Integer getId(...){
   try{ ... ; return id; }
   catch(Exception e){ return null;}
}
Steve B.
sumber
3
Ya. Jika Anda memiliki kondisi kesalahan, berikan pengecualian.
David Thornley
3
Ini adalah satu kasus di mana pengecualian akan dibenarkan. Jika Anda meminta nama karyawan yang tidak ada, pasti ada yang salah.
Thorarin
Saya pikir itu agak harfiah, Thorarin - Anda dapat berdalih dengan contoh saya, tentu saja, tapi saya yakin Anda bisa membayangkan beberapa contoh fungsi yang mengembalikan nilai yang cocok, atau nol jika tidak ada yang cocok. Bagaimana jika mendapatkan nilai dari kunci dalam hashtable? (Seharusnya memikirkan contoh itu di tempat pertama).
Steve B.
1
Tabel hash yang mengembalikan null untuk kunci yang tidak ada buruk. Melakukannya secara otomatis berarti Anda tidak dapat menyimpan null sebagai nilai tanpa kode yang tidak konsisten.
RHSeeger
3

Ini belum tentu desain yang buruk - karena dengan begitu banyak keputusan desain, itu tergantung.

Jika hasil dari metode ini adalah sesuatu yang tidak akan memiliki hasil yang baik dalam penggunaan normal, mengembalikan null baik-baik saja:

object x = GetObjectFromCache();   // return null if it's not in the cache

Jika harus selalu ada hasil non-nol, maka mungkin lebih baik untuk melemparkan pengecualian:

try {
   Controller c = GetController();    // the controller object is central to 
                                      //   the application. If we don't get one, 
                                      //   we're fubar

   // it's likely that it's OK to not have the try/catch since you won't 
   // be able to really handle the problem here
}
catch /* ... */ {
}
Michael Burr
sumber
2
Meskipun Anda dapat mencatat kesalahan diagnostik di sana, maka mungkin perlu menguji kembali pengecualian. Kadang-kadang Pengambilan Data Kegagalan Pertama bisa sangat membantu.
djna
Atau bungkus pengecualian dalam RuntimeException dengan informasi diagnostik di string pesan. Simpan informasi bersama.
Thorbjørn Ravn Andersen
Sekarang (pada 2018) saya tidak bisa lagi setuju dan dalam kasus seperti itu kita harus mendukung kembaliOptional<>
Piotr Müller
2

Untuk skenario tertentu, Anda ingin melihat kegagalan segera setelah itu terjadi.

Memeriksa NULL dan tidak menyatakan (untuk kesalahan programmer) atau melempar (untuk kesalahan pengguna atau pemanggil) dalam kasus kegagalan dapat berarti bahwa crash kemudian lebih sulit untuk dilacak, karena kasus aneh asli tidak ditemukan.

Selain itu, mengabaikan kesalahan dapat menyebabkan eksploitasi keamanan. Mungkin ke-nol-an berasal dari fakta bahwa buffer ditimpa atau sejenisnya. Sekarang, Anda tidak menabrak, yang berarti pengeksploitasi memiliki kesempatan untuk mengeksekusi dalam kode Anda.

Drew Hoskins
sumber
2

Alternatif apa yang Anda lihat untuk mengembalikan nol?

Saya melihat dua kasus:

  • findAnItem (id). Apa yang harus dilakukan jika item tidak ditemukan

Dalam hal ini kita dapat: Mengembalikan Null atau melempar pengecualian (dicentang) (atau mungkin membuat item dan mengembalikannya)

  • listItemsMatching (kriteria) apa yang harus dikembalikan jika tidak ada yang ditemukan?

Dalam hal ini kita bisa mengembalikan Null, mengembalikan daftar kosong atau membuang Pengecualian.

Saya percaya bahwa pengembalian nol mungkin kurang baik daripada alternatif karena itu mengharuskan klien untuk ingat untuk memeriksa nol, programmer lupa dan kode

x = find();
x.getField();  // bang null pointer exception

Di Jawa, melempar pengecualian yang diperiksa, RecordNotFoundException, memungkinkan kompiler untuk mengingatkan klien untuk menangani kasus.

Saya menemukan bahwa pencarian kembali daftar kosong bisa sangat nyaman - hanya mengisi tampilan dengan semua isi daftar, oh itu kosong, kode "hanya berfungsi".

djna
sumber
3
Melontarkan pengecualian untuk menunjukkan suatu kondisi yang diperkirakan mungkin terjadi selama aliran normal program mengarah ke kode yang benar-benar jelek, dari jenis coba {x = find ()} catch (RecordNotFound e) {// do stuff}.
quant_dev
Mengembalikan daftar kosong adalah solusi yang baik tetapi hanya ketika metode ini dalam konteks yang dapat mengembalikan daftar. Untuk situasi "findById", Anda harus mengembalikan nol. Saya tidak suka pengecualian RecordNotFound.
Thilo
Jadi itulah inti dari perbedaan pendapat kita. Bagi mata saya tidak ada banyak perbedaan dalam keindahan antara x = find (); if (x = null) {work} else {do ​​stuff} dan coba tangkap. Dan, jika perlu saya siap mengorbankan kecantikan untuk kebenaran kode. Terlalu sering dalam hidup saya, saya menemukan kode di mana nilai kembali belum diperiksa.
djna
1

Kadang-kadang, mengembalikan NULL adalah hal yang benar untuk dilakukan, tetapi khususnya ketika Anda berurusan dengan urutan dari berbagai jenis (array, daftar, string, apa-apa), mungkin lebih baik mengembalikan urutan panjang nol, karena mengarah ke kode yang lebih pendek dan mudah-mudahan lebih dimengerti, sambil tidak mengambil lebih banyak tulisan pada bagian pelaksana API.

Vatine
sumber
1

Buat mereka memanggil metode lain setelah fakta untuk mencari tahu apakah panggilan sebelumnya adalah nol. ;-) Hei, itu cukup baik untuk JDBC

David Plumpton
sumber
1

Ide dasar di balik utas ini adalah memprogram secara defensif. Artinya, kode terhadap yang tak terduga. Ada serangkaian balasan yang berbeda:

Adamski menyarankan untuk melihat Pola Objek Null, dengan jawaban yang dipilih untuk saran itu.

Michael Valenty juga menyarankan konvensi penamaan untuk memberi tahu pengembang apa yang mungkin diharapkan. ZeroConcept menyarankan penggunaan Exception yang tepat, jika itu alasan untuk NULL. Dan lain-lain.

Jika kita membuat "aturan" bahwa kita selalu ingin melakukan pemrograman defensif maka kita dapat melihat bahwa saran ini valid.

Tetapi kami memiliki 2 skenario pengembangan.

Kelas "ditulis" oleh pengembang: Penulis

Kelas "dikonsumsi" oleh pengembang (mungkin) lain: Pengembang

Terlepas dari apakah suatu kelas mengembalikan NULL untuk metode dengan nilai pengembalian atau tidak, Pengembang perlu menguji apakah objek tersebut valid.

Jika pengembang tidak dapat melakukan ini, maka Kelas / metode itu tidak deterministik. Artinya, jika "metode panggilan" untuk mendapatkan objek tidak melakukan apa yang "diiklankan" (mis. GetEmployee), ia telah melanggar kontrak.

Sebagai penulis kelas, saya selalu ingin menjadi baik dan defensif (dan deterministik) ketika membuat metode.

Jadi mengingat bahwa NULL atau NULL OBJECT (misalnya jika (karyawan sebagai NullEmployee.ISVALID)) perlu diperiksa dan yang mungkin perlu terjadi dengan kumpulan Karyawan, maka pendekatan objek nol adalah pendekatan yang lebih baik.

Tapi saya juga suka saran Michael Valenty tentang penamaan metode yang HARUS mengembalikan nol misalnya getEmployeeOrNull.

Seorang Penulis yang melempar pengecualian sedang menghapus pilihan bagi pengembang untuk menguji validitas objek, yang sangat buruk pada kumpulan objek, dan memaksa pengembang ke dalam penanganan pengecualian ketika membuat kode konsumsi mereka yang bercabang.

Sebagai pengembang yang mengkonsumsi kelas, saya berharap penulis memberi saya kemampuan untuk menghindari atau memprogram untuk situasi nol yang mungkin dihadapi kelas / metode mereka.

Jadi sebagai pengembang saya akan memprogram pertahanan terhadap NULL dari suatu metode. Jika penulis telah memberi saya kontrak yang selalu mengembalikan objek (NULL OBJECT selalu melakukannya) dan objek itu memiliki metode / properti untuk menguji validitas objek, maka saya akan menggunakan metode / properti itu untuk terus menggunakan objek , kalau tidak objek tidak valid dan saya tidak bisa menggunakannya.

Intinya adalah bahwa Penulis Kelas / Metode harus menyediakan mekanisme yang dapat digunakan Pengembang dalam pemrograman defensif mereka. Artinya, niat yang lebih jelas dari metode ini.

Pengembang harus selalu menggunakan pemrograman defensif untuk menguji validitas objek yang dikembalikan dari kelas / metode lain.

salam

GregJF

GregJF
sumber
0

Pilihan lain untuk ini, adalah: mengembalikan beberapa nilai yang menunjukkan keberhasilan atau tidak (atau jenis kesalahan), tetapi jika Anda hanya perlu nilai boolean yang akan menunjukkan keberhasilan / gagal, mengembalikan nol untuk kegagalan, dan objek untuk sukses tidak akan kurang benar, lalu mengembalikan true / false dan mendapatkan objek melalui parameter.
Pendekatan lain akan menggunakan pengecualian untuk menunjukkan kegagalan, tetapi di sini - sebenarnya ada lebih banyak suara, yang mengatakan ini adalah praktik BAD (karena menggunakan pengecualian mungkin nyaman tetapi memiliki banyak kelemahan).
Jadi saya pribadi tidak melihat hal buruk dalam mengembalikan nol sebagai indikasi bahwa ada yang tidak beres, dan memeriksanya nanti (untuk mengetahui apakah Anda berhasil atau tidak). Juga, secara membabi buta berpikir bahwa metode Anda tidak akan mengembalikan NULL, dan kemudian mendasarkan kode Anda di atasnya, dapat menyebabkan kesalahan lain, kadang-kadang sulit ditemukan, (walaupun dalam kebanyakan kasus hanya akan merusak sistem Anda :), karena Anda akan merujuk ke 0x00000000 cepat atau lambat).

Marcin Deptuła
sumber
0

Fungsi nol yang tidak diinginkan dapat muncul selama pengembangan program yang kompleks, dan seperti kode mati, kejadian tersebut menunjukkan kelemahan serius dalam struktur program.

Fungsi atau metode nol sering digunakan sebagai perilaku default fungsi yang dapat direvisi atau metode yang dapat ditimpa dalam kerangka kerja objek.

Null_function @wikipedia

Script Juicy
sumber
0

Yah, itu pasti tergantung dari tujuan metode ... Kadang-kadang, pilihan yang lebih baik adalah dengan melemparkan pengecualian. Itu semua tergantung dari kasus ke kasus.

Denis Biondic
sumber
0

Jika kodenya seperti:

command = get_something_to_do()

if command:  # if not Null
    command.execute()

Jika Anda memiliki objek dummy yang mengeksekusi () metode tidak melakukan apa-apa, dan Anda mengembalikan itu alih-alih Null dalam kasus yang sesuai, Anda tidak perlu memeriksa untuk kasus Null dan sebaliknya bisa melakukan:

get_something_to_do().execute()

Jadi, di sini masalahnya bukan antara memeriksa NULL vs pengecualian, tetapi sebaliknya antara pemanggil harus menangani kasus khusus yang berbeda (dengan cara apa pun) atau tidak.

Segera
sumber
0

Untuk kasus penggunaan saya, saya perlu mengembalikan Peta dari metode dan kemudian mencari kunci tertentu. Tetapi jika saya mengembalikan Peta kosong, maka itu akan mengarah ke NullPointerException dan kemudian tidak akan jauh berbeda dengan mengembalikan null daripada Peta kosong. Tetapi dari Java8 dan seterusnya kita bisa menggunakan Opsional . Di atas adalah alasan mengapa konsep opsional diperkenalkan.

Aman Gupta
sumber
-3

Hari,

Mengembalikan NULL ketika Anda tidak dapat membuat objek baru adalah praktik standar untuk banyak API.

Kenapa itu desain yang buruk saya tidak tahu.

Sunting: Ini berlaku untuk bahasa di mana Anda tidak memiliki pengecualian seperti C yang telah menjadi konvensi selama bertahun-tahun.

HTH

'Sangat bahagia,

Rob Wells
sumber
2
Jika Anda tidak dapat membuat objek, Anda harus benar-benar melemparkan Pengecualian. Jika Anda tidak dapat menemukan objek yang cocok dengan beberapa permintaan, maka mengembalikan null adalah cara yang harus dilakukan.
Thilo
@ Thilo, tunjukkan padaku bagaimana melakukannya di C dan aku akan sangat tertarik.
Rob Wells
@RobWells C bukan bahasa berorientasi objek, tetapi pertanyaan ini ditandai sebagai "oop"
yegor256
@ yegor256 Anda benar. Dan saya melewatkan tag OOP asli. Tapi, seperti kata BS, kelas dalam C ++ hanyalah sebuah struct dengan beberapa fungsi anggota tambahan ditambahkan dan beberapa manajemen memori mewah terjadi secara internal. Tetapi jika API suuposed untuk mengembalikan struct, maka mengembalikan NUL ketika Anda tidak dapat membuat struct sering konvensi.
Rob Wells