Itu semacam pertanyaan umum (tapi saya menggunakan C #), apa cara terbaik (praktik terbaik), apakah Anda mengembalikan koleksi kosong atau kosong untuk metode yang memiliki koleksi sebagai tipe pengembalian?
Itu semacam pertanyaan umum (tapi saya menggunakan C #), apa cara terbaik (praktik terbaik), apakah Anda mengembalikan koleksi kosong atau kosong untuk metode yang memiliki koleksi sebagai tipe pengembalian?
Jawaban:
Koleksi kosong. Selalu.
Ini menyebalkan:
if(myInstance.CollectionProperty != null)
{
foreach(var item in myInstance.CollectionProperty)
/* arrgh */
}
Ini dianggap sebagai praktik terbaik untuk TIDAK PERNAH kembali null
ketika mengembalikan koleksi atau dihitung. SELALU mengembalikan enumerable / koleksi kosong. Ini mencegah omong kosong yang disebutkan di atas, dan mencegah mobil Anda diganggu oleh rekan kerja dan pengguna kelas Anda.
Saat berbicara tentang properti, selalu atur properti Anda sekali dan lupakan
public List<Foo> Foos {public get; private set;}
public Bar() { Foos = new List<Foo>(); }
Di .NET 4.6.1, Anda bisa memadatkan ini cukup banyak:
public List<Foo> Foos { get; } = new List<Foo>();
Saat berbicara tentang metode yang mengembalikan enumerable, Anda dapat dengan mudah mengembalikan enumerable kosong daripada null
...
public IEnumerable<Foo> GetMyFoos()
{
return InnerGetFoos() ?? Enumerable.Empty<Foo>();
}
Menggunakan Enumerable.Empty<T>()
dapat dilihat sebagai lebih efisien daripada mengembalikan, misalnya, koleksi atau array kosong baru.
IEnumerable
atau ICollection
tidak. Ngomong-ngomong, jika kamu memilih sesuatu yang bertipe ICollection
mereka juga kembali null
... Aku ingin mereka mengembalikan koleksi kosong, tapi aku bertemu mereka kembali null
, jadi kupikir aku akan menyebutkannya di sini. Saya akan mengatakan bahwa koleksi default enumerable kosong, bukan null. Saya tidak tahu itu subjek yang sensitif.
Dari Framework Design Guidelines 2nd Edition (hal 256):
JANGAN mengembalikan nilai nol dari properti koleksi atau dari metode pengembalian koleksi. Kembalikan koleksi kosong atau array kosong sebagai gantinya.
Inilah artikel menarik lainnya tentang manfaat tidak mengembalikan nol (saya mencoba menemukan sesuatu di blog Brad Abram, dan dia menautkan ke artikel itu).
Sunting - seperti Eric Lippert sekarang telah mengomentari pertanyaan awal, saya juga ingin menautkan ke artikelnya yang sangat bagus .
Tergantung pada kontrak Anda dan kasing beton Anda . Umumnya yang terbaik adalah mengembalikan koleksi kosong , tetapi kadang-kadang ( jarang ):
null
mungkin berarti sesuatu yang lebih spesifik;null
.Beberapa contoh nyata:
null
artinya elemen tersebut hilang, sementara koleksi kosong akan membuat redundan (dan mungkin salah)<collection />
Ada satu hal lain yang belum disebutkan. Pertimbangkan kode berikut:
public static IEnumerable<string> GetFavoriteEmoSongs()
{
yield break;
}
Bahasa C # akan mengembalikan enumerator kosong saat memanggil metode ini. Oleh karena itu, agar konsisten dengan desain bahasa (dan, dengan demikian, harapan programmer) koleksi kosong harus dikembalikan.
Kosong jauh lebih ramah konsumen.
Ada metode yang jelas untuk membuat enumerable kosong:
Enumerable.Empty<Element>()
Tampak bagi saya bahwa Anda harus mengembalikan nilai yang secara semantik benar dalam konteks, apa pun itu. Aturan yang mengatakan "selalu kembalikan koleksi kosong" tampaknya sedikit sederhana bagi saya.
Misalkan dalam, katakanlah, sebuah sistem untuk rumah sakit, kami memiliki fungsi yang seharusnya mengembalikan daftar semua rawat inap sebelumnya selama 5 tahun terakhir. Jika pelanggan belum masuk rumah sakit, masuk akal untuk mengembalikan daftar kosong. Tetapi bagaimana jika pelanggan membiarkan bagian dari formulir penerimaan itu kosong? Kami membutuhkan nilai yang berbeda untuk membedakan "daftar kosong" dari "tidak ada jawaban" atau "tidak tahu". Kita bisa melempar pengecualian, tetapi itu tidak selalu merupakan kondisi kesalahan, dan itu tidak serta merta membuat kita keluar dari aliran program normal.
Saya sering frustrasi oleh sistem yang tidak dapat membedakan antara nol dan tidak ada jawaban. Saya sudah beberapa kali di mana suatu sistem meminta saya untuk memasukkan beberapa angka, saya memasukkan nol, dan saya mendapatkan pesan kesalahan yang memberi tahu saya bahwa saya harus memasukkan nilai dalam bidang ini. Saya baru saja melakukannya: Saya memasukkan nol! Tetapi itu tidak akan menerima nol karena tidak dapat membedakannya dari tidak ada jawaban.
Balas ke Saunders:
Ya, saya berasumsi bahwa ada perbedaan antara "Orang tidak menjawab pertanyaan" dan "Jawabannya nol." Itulah poin paragraf terakhir dari jawaban saya. Banyak program tidak dapat membedakan "tidak tahu" dari kosong atau nol, yang menurut saya merupakan potensi kesalahan serius. Sebagai contoh, saya berbelanja untuk rumah sekitar setahun yang lalu. Saya pergi ke situs web real estat dan ada banyak rumah terdaftar dengan harga $ 0. Kedengarannya cukup bagus bagi saya: Mereka memberikan rumah-rumah ini secara gratis! Tapi saya yakin kenyataan menyedihkannya adalah mereka belum memasukkan harganya. Dalam hal ini Anda dapat berkata, "Yah, SANGAT nol berarti mereka tidak memasukkan harga - tidak ada yang akan memberikan rumah secara gratis." Tetapi situs tersebut juga mencantumkan harga jual dan permintaan rata-rata rumah di berbagai kota. Saya bertanya-tanya apakah rata-rata tidak termasuk nol, sehingga memberikan rata-rata rendah yang salah untuk beberapa tempat. yaitu berapa rata-rata $ 100.000; $ 120.000; dan "tidak tahu"? Secara teknis jawabannya adalah "tidak tahu". Yang mungkin ingin kami lihat adalah $ 110.000. Tapi yang mungkin akan kita dapatkan adalah $ 73.333, yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tapi saya yakin Anda pernah melihatnya melakukannya untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"? sehingga memberikan rata-rata rendah yang salah untuk beberapa tempat. yaitu berapa rata-rata $ 100.000; $ 120.000; dan "tidak tahu"? Secara teknis jawabannya adalah "tidak tahu". Yang mungkin ingin kami lihat adalah $ 110.000. Tapi yang mungkin akan kita dapatkan adalah $ 73.333, yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tetapi saya yakin Anda telah melihatnya dilakukan untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"? sehingga memberikan rata-rata rendah yang salah untuk beberapa tempat. yaitu berapa rata-rata $ 100.000; $ 120.000; dan "tidak tahu"? Secara teknis jawabannya adalah "tidak tahu". Yang mungkin ingin kami lihat adalah $ 110.000. Tapi yang mungkin akan kita dapatkan adalah $ 73.333, yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tetapi saya yakin Anda telah melihatnya dilakukan untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"? yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tapi saya yakin Anda pernah melihatnya melakukannya untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"? yang akan sepenuhnya salah. Juga, bagaimana jika kami memiliki masalah ini di situs tempat pengguna dapat memesan secara online? (Tidak mungkin untuk real estat, tetapi saya yakin Anda telah melihatnya dilakukan untuk banyak produk lain.) Apakah kita benar-benar ingin "harga belum ditentukan" diartikan sebagai "gratis"?
RE memiliki dua fungsi terpisah, "apakah ada?" dan "jika demikian, apa itu?" Ya, Anda tentu bisa melakukan itu, tetapi mengapa Anda mau? Sekarang program panggilan harus membuat dua panggilan, bukan satu. Apa yang terjadi jika seorang programmer gagal memanggil "any?" dan langsung menuju ke "apa itu?" ? Apakah program akan mengembalikan nol salah arah? Melempar pengecualian? Kembalikan nilai yang tidak ditentukan? Ini menciptakan lebih banyak kode, lebih banyak pekerjaan, dan lebih banyak kesalahan potensial.
Satu-satunya manfaat yang saya lihat adalah memungkinkan Anda untuk mematuhi aturan arbitrer. Apakah ada manfaat dari aturan ini yang membuatnya sepadan dengan kesulitan mematuhinya? Jika tidak, mengapa repot-repot?
Balas ke Jammycakes:
Pertimbangkan seperti apa kode yang sebenarnya. Saya tahu pertanyaan kata C # tetapi maafkan saya jika saya menulis Java. C # saya tidak terlalu tajam dan prinsipnya sama.
Dengan pengembalian nol:
HospList list=patient.getHospitalizationList(patientId);
if (list==null)
{
// ... handle missing list ...
}
else
{
for (HospEntry entry : list)
// ... do whatever ...
}
Dengan fungsi terpisah:
if (patient.hasHospitalizationList(patientId))
{
// ... handle missing list ...
}
else
{
HospList=patient.getHospitalizationList(patientId))
for (HospEntry entry : list)
// ... do whatever ...
}
Ini sebenarnya satu atau dua kode lebih sedikit dengan pengembalian nol, jadi tidak lebih banyak beban pada pemanggil, itu lebih sedikit.
Saya tidak melihat bagaimana ini menciptakan masalah KERING. Bukannya kita harus melakukan panggilan dua kali. Jika kita selalu ingin melakukan hal yang sama ketika daftar tidak ada, mungkin kita bisa mendorong penanganan ke fungsi daftar daripada meminta penelepon melakukannya, dan dengan demikian menempatkan kode di penelepon akan menjadi pelanggaran KERING. Tapi kita hampir pasti tidak ingin selalu melakukan hal yang sama. Dalam fungsi di mana kita harus memiliki daftar untuk diproses, daftar yang hilang adalah kesalahan yang mungkin menghentikan pemrosesan. Tetapi pada layar edit, kami pasti tidak ingin menghentikan pemrosesan jika mereka belum memasukkan data: kami ingin mereka memasukkan data. Jadi penanganan "no list" harus dilakukan di level pemanggil dengan satu atau lain cara. Dan apakah kita melakukan itu dengan pengembalian nol atau fungsi terpisah tidak ada bedanya dengan prinsip yang lebih besar.
Tentu, jika penelepon tidak memeriksa null, program bisa gagal dengan pengecualian null-pointer. Tetapi jika ada fungsi "punya" yang terpisah dan penelepon tidak memanggil fungsi itu tetapi secara buta memanggil fungsi "dapatkan daftar", lalu apa yang terjadi? Jika ia melempar pengecualian atau gagal, yah, itu hampir sama dengan apa yang akan terjadi jika ia mengembalikan nol dan tidak memeriksanya. Jika mengembalikan daftar kosong, itu hanya salah. Anda gagal membedakan antara "Saya punya daftar dengan nol elemen" dan "Saya tidak punya daftar". Ini seperti mengembalikan nol untuk harga ketika pengguna tidak memasukkan harga apa pun: itu hanya salah.
Saya tidak melihat bagaimana melampirkan atribut tambahan ke koleksi membantu. Penelepon masih harus memeriksanya. Bagaimana itu lebih baik daripada memeriksa null? Sekali lagi, hal terburuk yang dapat terjadi adalah programmer lupa untuk memeriksanya, dan memberikan hasil yang salah.
Sebuah fungsi yang mengembalikan null bukanlah kejutan jika programmer akrab dengan konsep makna nol "tidak memiliki nilai", yang saya pikir setiap programmer yang kompeten seharusnya pernah mendengar, apakah dia pikir itu ide yang bagus atau tidak. Saya pikir memiliki fungsi terpisah lebih merupakan masalah "kejutan". Jika seorang programmer tidak terbiasa dengan API, ketika dia menjalankan tes tanpa data, dia akan dengan cepat menemukan bahwa kadang-kadang dia kembali nol. Tetapi bagaimana ia menemukan keberadaan fungsi lain kecuali jika terlintas dalam benaknya bahwa mungkin ada fungsi semacam itu dan ia memeriksa dokumentasinya, dan dokumentasinya lengkap dan dapat dipahami? Saya lebih suka memiliki satu fungsi yang selalu memberi saya respons yang bermakna, daripada dua fungsi yang harus saya ketahui dan ingat untuk memanggil keduanya.
Jika koleksi kosong masuk akal secara semantik, itulah yang saya inginkan untuk dikembalikan. Mengembalikan koleksi kosong untuk GetMessagesInMyInbox()
berkomunikasi "Anda benar-benar tidak memiliki pesan di kotak masuk Anda", sedangkan pengembalian null
mungkin berguna untuk berkomunikasi bahwa data yang tidak memadai tersedia untuk mengatakan seperti apa daftar yang mungkin dikembalikan seharusnya terlihat.
null
nilai pasti tidak tampak masuk akal, saya berpikir secara umum tentang hal itu. Pengecualian juga bagus untuk mengomunikasikan fakta bahwa ada yang tidak beres, tetapi jika "data tidak mencukupi" yang dimaksud sesuai dengan yang diharapkan, maka melemparkan pengecualian akan ada desain yang buruk. Saya agak memikirkan skenario di mana itu sangat mungkin dan tidak ada kesalahan sama sekali untuk metode untuk kadang-kadang tidak dapat menghitung respons.
Mengembalikan null bisa lebih efisien, karena tidak ada objek baru yang dibuat. Namun, itu juga sering membutuhkannull
pemeriksaan (atau penanganan pengecualian).
Secara semantik, null
dan daftar kosong tidak berarti hal yang sama. Perbedaannya halus dan satu pilihan mungkin lebih baik daripada yang lain dalam hal tertentu.
Apa pun pilihan Anda, dokumentasikan untuk menghindari kebingungan.
Orang dapat berargumen bahwa alasan di balik Pola Objek Null mirip dengan yang mendukung pengembalian koleksi kosong.
Tergantung situasinya. Jika ini adalah kasus khusus, maka kembalikan nol. Jika fungsi hanya mengembalikan koleksi kosong, maka jelas mengembalikan itu ok. Namun, mengembalikan koleksi kosong sebagai kasus khusus karena parameter yang tidak valid atau alasan lain BUKAN ide yang baik, karena menutupi kondisi kasus khusus.
Sebenarnya, dalam hal ini saya biasanya lebih suka melempar pengecualian untuk memastikan itu BENAR-BENAR tidak diabaikan :)
Mengatakan itu membuat kode lebih kuat (dengan mengembalikan koleksi kosong) karena mereka tidak harus menangani kondisi nol adalah buruk, karena hanya menutupi masalah yang harus ditangani oleh kode panggilan.
Saya berpendapat bahwa null
itu tidak sama dengan koleksi kosong dan Anda harus memilih yang terbaik mewakili apa yang Anda kembalikan. Dalam kebanyakan kasus null
tidak ada apa-apa (kecuali dalam SQL). Koleksi kosong adalah sesuatu, meskipun sesuatu yang kosong.
Jika Anda harus memilih satu atau yang lain, saya akan mengatakan bahwa Anda harus cenderung ke koleksi kosong daripada nol. Tetapi ada kalanya koleksi kosong tidak sama dengan nilai nol.
Pikirkan selalu dalam mendukung klien Anda (yang menggunakan api Anda):
Mengembalikan 'null' sangat sering membuat masalah dengan klien yang tidak menangani pemeriksaan nol dengan benar, yang menyebabkan NullPointerException selama runtime. Saya telah melihat kasus-kasus dimana pemeriksaan nol yang hilang memaksa masalah produksi prioritas (klien menggunakan foreach (...) pada nilai nol). Selama pengujian masalah tidak terjadi, karena data yang dioperasikan sedikit berbeda.
Saya ingin memberi penjelasan di sini, dengan contoh yang sesuai.
Pertimbangkan sebuah kasus di sini ..
int totalValue = MySession.ListCustomerAccounts()
.FindAll(ac => ac.AccountHead.AccountHeadID
== accountHead.AccountHeadID)
.Sum(account => account.AccountValue);
Di sini Pertimbangkan fungsi yang saya gunakan ..
1. ListCustomerAccounts() // User Defined
2. FindAll() // Pre-defined Library Function
Saya dapat dengan mudah menggunakan ListCustomerAccount
dan FindAll
bukannya.,
int totalValue = 0;
List<CustomerAccounts> custAccounts = ListCustomerAccounts();
if(custAccounts !=null ){
List<CustomerAccounts> custAccountsFiltered =
custAccounts.FindAll(ac => ac.AccountHead.AccountHeadID
== accountHead.AccountHeadID );
if(custAccountsFiltered != null)
totalValue = custAccountsFiltered.Sum(account =>
account.AccountValue).ToString();
}
CATATAN: Karena AccountValue tidak null
, fungsi Sum () tidak akan kembali null
., Karena itu saya dapat menggunakannya secara langsung.
Mengembalikan koleksi kosong lebih baik dalam banyak kasus.
Alasannya adalah kemudahan implementasi penelepon, kontrak yang konsisten, dan implementasi yang lebih mudah.
Jika metode mengembalikan nol untuk menunjukkan hasil kosong, pemanggil harus menerapkan adaptor pemeriksaan nol selain enumerasi. Kode ini kemudian digandakan dalam berbagai penelepon, jadi mengapa tidak memasukkan adaptor ini ke dalam metode sehingga dapat digunakan kembali.
Penggunaan null yang valid untuk IEnumerable mungkin merupakan indikasi tidak adanya hasil, atau kegagalan operasi, tetapi dalam hal ini teknik lain harus dipertimbangkan, seperti melempar pengecualian.
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
namespace StackOverflow.EmptyCollectionUsageTests.Tests
{
/// <summary>
/// Demonstrates different approaches for empty collection results.
/// </summary>
class Container
{
/// <summary>
/// Elements list.
/// Not initialized to an empty collection here for the purpose of demonstration of usage along with <see cref="Populate"/> method.
/// </summary>
private List<Element> elements;
/// <summary>
/// Gets elements if any
/// </summary>
/// <returns>Returns elements or empty collection.</returns>
public IEnumerable<Element> GetElements()
{
return elements ?? Enumerable.Empty<Element>();
}
/// <summary>
/// Initializes the container with some results, if any.
/// </summary>
public void Populate()
{
elements = new List<Element>();
}
/// <summary>
/// Gets elements. Throws <see cref="InvalidOperationException"/> if not populated.
/// </summary>
/// <returns>Returns <see cref="IEnumerable{T}"/> of <see cref="Element"/>.</returns>
public IEnumerable<Element> GetElementsStrict()
{
if (elements == null)
{
throw new InvalidOperationException("You must call Populate before calling this method.");
}
return elements;
}
/// <summary>
/// Gets elements, empty collection or nothing.
/// </summary>
/// <returns>Returns <see cref="IEnumerable{T}"/> of <see cref="Element"/>, with zero or more elements, or null in some cases.</returns>
public IEnumerable<Element> GetElementsInconvenientCareless()
{
return elements;
}
/// <summary>
/// Gets elements or nothing.
/// </summary>
/// <returns>Returns <see cref="IEnumerable{T}"/> of <see cref="Element"/>, with elements, or null in case of empty collection.</returns>
/// <remarks>We are lucky that elements is a List, otherwise enumeration would be needed.</remarks>
public IEnumerable<Element> GetElementsInconvenientCarefull()
{
if (elements == null || elements.Count == 0)
{
return null;
}
return elements;
}
}
class Element
{
}
/// <summary>
/// http://stackoverflow.com/questions/1969993/is-it-better-to-return-null-or-empty-collection/
/// </summary>
class EmptyCollectionTests
{
private Container container;
[SetUp]
public void SetUp()
{
container = new Container();
}
/// <summary>
/// Forgiving contract - caller does not have to implement null check in addition to enumeration.
/// </summary>
[Test]
public void UseGetElements()
{
Assert.AreEqual(0, container.GetElements().Count());
}
/// <summary>
/// Forget to <see cref="Container.Populate"/> and use strict method.
/// </summary>
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void WrongUseOfStrictContract()
{
container.GetElementsStrict().Count();
}
/// <summary>
/// Call <see cref="Container.Populate"/> and use strict method.
/// </summary>
[Test]
public void CorrectUsaOfStrictContract()
{
container.Populate();
Assert.AreEqual(0, container.GetElementsStrict().Count());
}
/// <summary>
/// Inconvenient contract - needs a local variable.
/// </summary>
[Test]
public void CarefulUseOfCarelessMethod()
{
var elements = container.GetElementsInconvenientCareless();
Assert.AreEqual(0, elements == null ? 0 : elements.Count());
}
/// <summary>
/// Inconvenient contract - duplicate call in order to use in context of an single expression.
/// </summary>
[Test]
public void LameCarefulUseOfCarelessMethod()
{
Assert.AreEqual(0, container.GetElementsInconvenientCareless() == null ? 0 : container.GetElementsInconvenientCareless().Count());
}
[Test]
public void LuckyCarelessUseOfCarelessMethod()
{
// INIT
var praySomeoneCalledPopulateBefore = (Action)(()=>container.Populate());
praySomeoneCalledPopulateBefore();
// ACT //ASSERT
Assert.AreEqual(0, container.GetElementsInconvenientCareless().Count());
}
/// <summary>
/// Excercise <see cref="ArgumentNullException"/> because of null passed to <see cref="Enumerable.Count{TSource}(System.Collections.Generic.IEnumerable{TSource})"/>
/// </summary>
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void UnfortunateCarelessUseOfCarelessMethod()
{
Assert.AreEqual(0, container.GetElementsInconvenientCareless().Count());
}
/// <summary>
/// Demonstrates the client code flow relying on returning null for empty collection.
/// Exception is due to <see cref="Enumerable.First{TSource}(System.Collections.Generic.IEnumerable{TSource})"/> on an empty collection.
/// </summary>
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void UnfortunateEducatedUseOfCarelessMethod()
{
container.Populate();
var elements = container.GetElementsInconvenientCareless();
if (elements == null)
{
Assert.Inconclusive();
}
Assert.IsNotNull(elements.First());
}
/// <summary>
/// Demonstrates the client code is bloated a bit, to compensate for implementation 'cleverness'.
/// We can throw away the nullness result, because we don't know if the operation succeeded or not anyway.
/// We are unfortunate to create a new instance of an empty collection.
/// We might have already had one inside the implementation,
/// but it have been discarded then in an effort to return null for empty collection.
/// </summary>
[Test]
public void EducatedUseOfCarefullMethod()
{
Assert.AreEqual(0, (container.GetElementsInconvenientCarefull() ?? Enumerable.Empty<Element>()).Count());
}
}
}
Saya menyebutnya kesalahan miliaran dolar saya ... Pada waktu itu, saya sedang merancang sistem tipe komprehensif pertama untuk referensi dalam bahasa berorientasi objek. 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. - Tony Hoare, penemu ALGOL W.
Lihat di sini untuk badai kotoran rumit tentang null
secara umum. Saya tidak setuju dengan pernyataan yang undefined
lain null
, tetapi masih layak dibaca. Dan itu menjelaskan, mengapa Anda harus menghindari null
sama sekali dan tidak hanya dalam kasus yang Anda tanyakan. Intinya, null
dalam bahasa apa pun ada kasus khusus. Anda harus memikirkannya null
sebagai pengecualian. undefined
berbeda dalam hal itu, bahwa kode yang berurusan dengan perilaku tidak terdefinisi dalam kebanyakan kasus hanya bug. C dan sebagian besar bahasa lainnya juga memiliki perilaku yang tidak terdefinisi tetapi kebanyakan tidak memiliki pengidentifikasi untuk itu dalam bahasa tersebut.
Dari perspektif mengelola kompleksitas, tujuan rekayasa perangkat lunak utama, kami ingin menghindari penyebaran kompleksitas siklomatik yang tidak perlu ke klien API. Mengembalikan nol ke klien sama seperti mengembalikan mereka biaya kompleksitas siklomatik dari cabang kode lain.
(Ini sesuai dengan beban pengujian unit. Anda harus menulis tes untuk kasus pengembalian nol, selain kasus pengembalian koleksi kosong.)