Dönüş değerinin bulunmadığı fonksiyon / yöntemlerden NULL değeri veya boş değerler döndürmek daha mı iyidir?


135

Burada bir öneri arıyorum. Dönüş değeri olmadığında veya belirlenemediğinde, bir yöntemden NULL veya boş bir değer döndürmenin daha iyi olup olmadığıyla mücadele ediyorum.

Aşağıdaki iki yöntemi örnek olarak alın:

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

İçinde ReverseString()boş bir dize döndürür derdim çünkü dönüş türü dizedir, bu yüzden arayan kişi bunu bekler. Ayrıca, bu şekilde, arayan bir NULL döndürülmüş olup olmadığını kontrol etmek zorunda kalmayacaktı.

İçinde FindPerson()NULL döndürmek daha uygun görünüyor. NULL veya boş bir Person Object ( new Person()) döndürülüp döndürülmediğine bakılmaksızın , arayan kişi bir şey yapmadan önce (Görüşme gibi UpdateName()) Person Object'in NULL veya boş olup olmadığını kontrol etmek zorunda kalacaktır . Öyleyse neden NULL'u buraya geri döndürmüyorsun ve arayan sadece NULL'u kontrol etmek zorunda.

Bununla mücadele eden başka biri var mı? Herhangi bir yardım veya içgörü takdir edilmektedir.


2
Değişecektir. Ayrıca, yöntemin ön kısımda yanlış olan değerleri durdurması gerektiğini, örneğin stringToReverse parametrenizin boş veya null olarak iletilmesi gerektiğini savunabilirsiniz. Bu kontrolü yaptıysanız (bir istisna geri döndü), her zaman boş değerden başka bir şey döndürür.
Aaron McIver

Fowler POEAA - s. 496 Baz Desenler - Özel Durum (boş nesne) Bloch Etkili Java 2nd Edition Ürün 43: Boş diziler veya koleksiyonları değil, boş değerlere İade
Boris Treukhov

1
@Boris Yorumunuzu görmedim. Aslında Özel Dava'yı cevap olarak gönderdim.
Thomas Owens

@Tomas İçinde herhangi bir sorun görmüyorum :). Soruya gelince, zaten sağduyulu bir mesele.
Boris Treukhov

İlginç bir yorum Oracle veritabanlarında NULL ve boş dize aynıdır
WuHoUnited

Yanıtlar:


77

StackOverflow'un bu soru ve cevapta bu konu hakkında iyi bir tartışması var . En çok oylanan soruda, kronoz şöyle not eder:

Kullanılabilir bir veri olmadığını belirtmek isterseniz, null değeri genellikle en iyi fikirdir.

Boş bir nesne verinin döndürüldüğünü, oysa null değerinin açıkça döndürüldüğünü gösterir.

Ek olarak, null değerinin döndürülmesi, nesnedeki üyelere erişmeye çalışırsanız, buggy kodunu vurgulamak için yararlı olabilecek bir boş istisna ile sonuçlanır - hiçbir şey olmayan bir üyeye erişmeye çalışmak hiç mantıklı gelmez. Boş bir nesnenin üyelerine erişmek başarısız olmaz; böceklerin keşfedilmemesi anlamına gelir.

Şahsen, yerine konması gereken hata işleme miktarını en aza indirmek için dizeleri döndüren işlevler için boş dizeler döndürmeyi seviyorum. Ancak, birlikte çalıştığınız grubun aynı kuralı takip edeceğinden emin olmanız gerekir - aksi takdirde bu kararın yararları elde edilemez.

Bununla birlikte, SO cevabındaki posterin işaret ettiği gibi, bir nesnenin beklenen olması durumunda, verilerin döndürülüp döndürülmediğine dair hiçbir şüphe bulunmaması için boş gösterilmesi gerekir.

Sonunda, işleri yapmanın en iyi tek yolu yoktur. Takım fikir birliği oluşturmak, takımınızın en iyi uygulamalarını sonuçlandıracaktır.


8
Şahsen, yerine konması gereken hata işleme miktarını en aza indirmek için dizeleri döndüren işlevler için boş dizeler döndürmeyi seviyorum. Bu argümanı asla anlamadım. Boş kontrol, en fazla <10 karakter mi? Neden böyle geri emek bükme gibi davranıyoruz?
Aaron McIver

19
Kimse geri emeği geri çevirdiğini söylemedi. Ama bir emek. Bu, koda özel bir durum ekliyor, bu da test edilecek bir dal daha anlamına geliyor. Ayrıca, kodun akışını bozar. for x in list_of_things() {...}tartışmalı grok sonra hızlıdırl = list_of_things(); if l != null {...}
Bryan Oakley

5
@Bryan: boş bir değer listesi ile boş bir dize arasında büyük bir fark vardır. Dize nadiren bir karakter listesini temsil eder.
kevin cline

3
kevin cline: elbette. Ancak, bir dizgede, bu dizginin null olsun olmasın, bir günlükte görünmesini isteyebilirsiniz. Boş olup olmadığını kontrol etmek zorunda kalmak, böylece boş bir dize yazdırabilir ve gerçek amacı gizler. Veya belki de bir web sayfasına eklemek istediğiniz, kullanıcı tarafından eklenen içeriği içeren veritabanı alanı gibi bir şey. Bunu yapmak için daha kolay emit(user.hometown)dahaif user.hometown == null { emit("") else {emit(user.hometown)}
Bryan Oakley

1
Sadece fazladan yazma yapmak değil (büyük bir şey değil), aynı zamanda okunabilirliği de etkiler. Şahsen ben bir sürü boş çek ile rahatsız edici bir kod buluyorum.
ToddR

82

Yazdığım tüm kodlarda null, bir işlevden geri dönmekten kaçınırım . Bunu Temiz Kod'da okudum .

Kullanmanın sorunu null, arayüzü kullanan kişinin nullolası bir sonuç olup olmadığını ve kontrol etmesi gerekip gerekmediğini bilmemesidir , çünkü not nullreferans türü yoktur .

F # ' da , ya optionda olabilen bir tür geri dönebilirsiniz , bu yüzden arayan kişiye kontrol etmesi gerektiği açıktır.some(Person)none

Analog C # (anti-) modeli Try...yöntemdir:

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

Şimdi insanlar dediler biliyorum nefretTry... bir çıkış parametresi olan bir saf fonksiyonun fikirleri kırar çünkü deseni, ancak daha çok farklı değil:

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);

... ve dürüst olmak gerekirse, her .NET programlayıcısının Try...modeli bildiğini varsayabilirsin çünkü dahili olarak .NET çerçevesi tarafından kullanılır. Bu, ne yaptığını anlamak için belgeleri okumamaları gerekmediği anlamına gelir ; bu benim için bazı puristlerin işlevler görünümüne bağlı kalmaktan daha önemlidir (bunun resultbir outparametre değil , bir parametre olduğunu anlamak ref).

Ben de giderdim TryFindPersonçünkü onu bulamamanın tamamen normal olduğunu gösteriyor gibi görünüyorsun.

Öte yandan, arayan kişinin personIdvarolmayan bir şeyi sağlayabilmesi için mantıklı bir sebep yoksa, muhtemelen şunu yapardım:

public Person GetPerson(int personId);

... ve sonra geçersiz olsaydı bir istisna atardım. Get...Önek arayan başarıyla sonuçlanması gerektiğini bilir anlamına gelmektedir.


28
+1, daha önce yapmamış olsaydınız, bu kodu Temiz Kod referansı ile cevaplardım. Ben mantrayı severim: "FONKSİYONUNUZ, BİR İSTEYNİYETE ÇIKTIĞINDAN ADI NEDİRSİNİZ YAPABİLİRSEM". Her düzine ya da öylesine boşuna kontrol etmekten daha iyi ....
Graham

13
İnsanların bilgisi hakkında bir şeyler varsaymaktan vazgeçtim.
CaffGeek

5
"Null kullanmanın sorunu, arayüzü kullanan kişinin null'ın olası bir sonuç olup olmadığını ve neyin kontrol edilip edilmeyeceğini bilmemesidir, çünkü boş referans türü yoktur." Referans türleri boş olabileceğinden, her zaman null'un olası bir sonuç olduğunu varsayamazsınız?
Tommy Carlier

4
Bir işlev bir işaretçi (C / C ++) veya bir nesneye (Java) başvuru döndürürse, her zaman boş dönebileceğini varsayarım.
Giorgio

7
"Null kullanmanın sorunu, arayüzü kullanan kişinin null'un olası bir sonuç olup olmadığını ve bunu kontrol etmesinin gerekip gerekmediğini bilmemesidir, [...]" Bir yöntem null döndürürse, açıkça belirtilmelidir. API sözleşmesinin bir parçası olarak belirtilmiştir.
Zsolt Török

28

Martin Fowler'ın Özel Durum desenini , Paterns of Enterprise Application Architecture'dan deneyebilirsiniz :

Boşluklar nesne yönelimli programlarda garip şeylerdir çünkü çok biçimliliği yenerler. Genellikle, öğenin tam tür mü yoksa alt sınıf mı olduğu konusunda endişelenmeden, foo'yu belirli bir türdeki değişken referansta serbestçe çalıştırabilirsiniz. Çok iyi yazılmış bir dilde, derleyicinin aramanın doğru olduğunu kontrol etmesini bile sağlayabilirsiniz. Bununla birlikte, bir değişken null içerebildiğinden, null'daki bir mesajı çağırarak çalışma zamanı hatasıyla karşılaşabilirsiniz; bu da size güzel ve arkadaşça bir yığın izlemesi sağlayacaktır.

Bir değişkenin null olması mümkünse, onu boş sınama koduyla çevrelemeyi hatırlamanız gerekir, böylece null varsa doğru olanı yaparsınız. Çoğu zaman doğru şey birçok bağlamda aynıdır, bu nedenle birçok yerde benzer kodlar yazıyorsunuz - kod çoğaltmanın günahını işliyorsunuz.

Boş değerler, bu sorunların ortak bir örneğidir ve diğerleri düzenli olarak çoğalır. Sayı sistemlerinde, gerçek sayıların olağan değişmezlerini kıran ek gibi şeyler için özel kurallara sahip olan sonsuzlukla baş etmek zorundasınız. İş yazılımlarındaki en eski deneyimlerimden biri, “yolcu” olarak adlandırılan, tam olarak bilinmeyen bir müşteriyle oldu. Bunların hepsi, türün normal davranışını değiştirmek anlamına gelir.

Null veya bir tuhaf değer döndürmek yerine, arayanın beklediği ile aynı arayüze sahip bir Özel Durum döndürün.


Bu senaryoya girdim, ancak yalnızca yazılım piyasaya sürüldükten sonra. Test verilerim onu ​​asla tetiklemedi, bu yüzden biraz maviden ve hata ayıklamak için bir acı oldu. Özel Durum modeli ile çözemediğim halde, farkında olmak güzel.
samis

14

Ben düşünürdüm ReverseString()ters dize döneceğini ve atmak bir olurdu IllegalArgumentExceptionbir geçirilen eğer Null.

Bence her zaman bir şeyler bulabilirseniz FindPerson(), NullObject Paternini izlemeli veya bir şey bulamama konusunda denetlenmeyen bir istisna oluşturmalıyım.

Başa çıkmak zorunda Nullolmak, kaçınılması gereken bir şeydir. Dillere sahip olmak Null, mucidi tarafından Milyar Dolarlık Hata olarak adlandırıldı !

Milyar dolarlık hatam diyorum. 1965'teki boş referansın icadıydı. O zamanlar, nesne yönelimli bir dilde (ALGOL W) referanslar için ilk kapsamlı tip sistemi tasarlıyordum.

Amacım, derleyici tarafından otomatik olarak yapılan kontrollerle referansların tüm kullanımının kesinlikle güvenli olmasını sağlamaktı. Ancak boş bir referans verme eğilimine karşı koyamadım, çünkü uygulanması çok kolaydı.

Bu, son kırk yılda muhtemelen bir milyar dolarlık acı ve hasara neden olan sayısız hata, güvenlik açığı ve sistem çökmesine neden oldu.

Son yıllarda, referansları kontrol etmek ve boş olma riskleri varsa uyarılar vermek için Microsoft'ta PREfix ve PREfast gibi bir dizi program analizcisi kullanılmıştır. Spec # gibi daha yeni programlama dilleri boş olmayan referanslar için beyanlar getirmiştir. 1965'te reddettiğim çözüm bu.

Tony Hoare


11

Bir Seçenek İade Et . NullPointerException riski olmadan farklı bir geçersiz değer döndürmenin tüm faydaları (koleksiyonlarınızda boş değerlere sahip olmak gibi).


1
İlginç. Java'da bir seçenek nasıl uygulanır? Ve C ++ 'da?
Giorgio

1
@Giorgio, Java için, Google'dan Guava kütüphaneleri, İsteğe Bağlı olarak adlandırılan bir sınıfa sahiptir .
Otavio Macedo

1
C ++ için varboost::optional<T>
MS

8

Bu argümanın her iki tarafını görüyorum ve kodun temiz tutulması, fazladan hata yapma bloklarından kaçınmak, vb.

Bununla birlikte, boşa dönen taraftarlarla yan yana olma eğilimindeyim. Bir yöntemin çağrılmasında önemli bir ayrım olduğunu görüyorum ve bununla ilgili herhangi bir veriye sahip değilim ve bu boş Dize'ye sahip olduğumla yanıtlıyor .

Bir Person sınıfına atıfta bulunulan tartışmaların bazılarını gördüğümden, sınıfın bir örneğini aramaya çalıştığınız senaryoyu inceleyin. Bazı bulucu özniteliklerini (örn., Bir kimlik) iletirseniz, bir müşteri, hiçbir değer bulunup bulunmadığını görmek için hemen null kontrolü yapabilir. Bu mutlaka istisnai bir durum değildir (bu nedenle istisnalar gerektirmez), fakat ayrıca açıkça belgelenmelidir. Evet, bu müşterinin adına biraz titizlik gerektirir ve hayır, bunun kötü bir şey olduğunu sanmıyorum.

Şimdi, içinde hiçbir şey olmayan ... geçerli bir Person nesnesi döndürdüğünüz alternatifi düşünün. Tüm değerlerine (isim, adres, favoriteDrink) boş değerler mi koyuyorsunuz ya da şimdi geçerli ama boş nesnelerle dolduruyor musunuz? Müşteriniz şimdi gerçek Kişi bulunamadığını nasıl belirleyecek? Adın null yerine boş bir String olup olmadığını kontrol etmeleri gerekir mi? Bu tür bir şey gerçekte null olup olmadığına göre daha fazla veya daha fazla kod karmaşasına ve koşullu ifadeye yol açmayacak mı?

Yine, bu tartışmanın iki tarafında da hemfikir olduğum noktalar var, ama bunun çoğu insan için en mantıklı olduğunu düşünüyorum (kodu daha sürdürülebilir hale getirmek).


Aradaki fark, " anahtar yoksa, boş değer döndürür mü FindPersonyoksa GetPersonbir istisna atar mı?" API'nin bir kullanıcısı olarak bilmiyorum ve dokümantasyonu kontrol etmem gerekiyor. Öte yandan, bool TryGetPerson(Guid key, out Person person)belgeleri kontrol etmemi gerektirmiyor ve istisnai olmayan bir durum için ne gibi bir istisna atılmadığını biliyorum . Cevabımı vermeye çalıştığım nokta bu.
Scott Whitlock

4
Bence insanlar istisnalara fazla bağlandılar. İstisnalar kötü ve kaynak tüketiyor. İnsanların hiçbir şeyi çözmeden ifadelerini almaya çalıştıklarından bahsetmiyorum bile. İstisnalar, bir şeyin temelde yanlış gittiğinin işaretidir. Örneğin, boş referanslar bir istisna atar, çünkü boş nesnelere başvurmak açıkça yanlıştır. Kişinin bulunup bulunmadığını kontrol etmek için kullanmak yanlıştır.
Vladimir Kocjancic

1
@VladimirKocjancic: Kesinlikle katılıyorum: İstisnai durumlar, yazılım hataları, donanım arızaları, sistemin yanlış yapılandırılması gibi istisnai durumlar için kullanılmalıdır. Kısmi bir işlevi (gibi findPerson) hesaplıyorsanız , sonuç alamaması kesinlikle normaldir. Bu bir istisnaya yol açmamalıdır.
Giorgio,

6

Maddenin var olup olmadığını bilmeniz gerekiyorsa null değerini döndürün. Aksi takdirde, beklenen veri türünü döndürün. Bu, özellikle bir öğe listesi döndürüyorsanız geçerlidir. Arayan kişinin bir liste isteyip istemediğini varsaymak genellikle güvenlidir, listeyi tekrarlamak isteyeceklerdir. Birçok (çoğu? Tümü?) Dil, null üzerinden yineleme yapmaya çalışırsanız, ancak boş bir listeyi yinelediğinizde başarısız olur.

Böyle bir kodu denemeyi ve kullanmayı, sadece başarısız olması için sinir bozucu buluyorum:

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

Hiçbir şey olmadığında dava için özel bir dava eklemek zorunda kalmamalıyım .


7
Bir listenin veya başka bir değer grubunun beklendiği durumlarda, tam olarak bu sebepten dolayı her zaman boş bir listeye dönmeyi seçerim. Varsayılan eylem (boş bir listeyi yineleyen) hemen hemen her zaman doğrudur ve eğer değilse, arayan kişi listenin boş olup olmadığını açıkça kontrol edebilir.
TMN

5

Bu, yöntemin anlamına bağlıdır. Muhtemelen belirtebilirsiniz, yönteminiz sadece "Boş değil" i kabul eder. Java’da bazı meta veri ek açıklamaları kullanarak şunları beyan edebilirsiniz:

string ReverseString(@NotNull String stringToReverse)

Bir şekilde dönüş değerini belirtmelisin. Bildirirseniz, yalnızca NotNull değerlerini kabul edersiniz, boş dize döndürmek zorunludur (giriş de boş dize ise).

İkinci durum anlambiliminde biraz karışık. Bu yöntem bir kimseyi birincil anahtarıyla (ve o kişinin olması bekleniyor) döndürmekse, daha iyi bir yol istisna atmaktır.

Person FindPerson(int personID)

Kişiyi tahmin edilen bir kimliğe göre ararsanız (ki bu garip görünüyor), bu yöntemi @Nullable olarak bildirmeniz iyi olur.


3

Mümkün olduğunda Null Object desenini kullanmanızı öneririm. Yöntemlerinizi çağırırken kodu basitleştirir ve çirkin kodları okumazsınız.

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

Örneğin, bir yöntem bazı desene uyan nesneler koleksiyonunu döndürürse, boş bir koleksiyonun döndürülmesi geri dönmekten daha anlamlı olur nullve bu boş koleksiyonun yinelenmesi neredeyse hiçbir performans cezasına sahip olmaz. Başka bir durum, verileri günlüğe kaydetmek için kullanılan sınıf örneğini döndüren, nullkullanıcıların geri gönderilen başvurunun her zaman kontrol edilmesini zorlamadığı için bence tercih edilmek yerine Null nesnesini döndüren bir yöntem olabilir null.

nullDöndürmenin anlamlı olduğu durumlarda ( findPerson ()örneğin yöntemi çağırıyorsanız ), en azından nesne varsa ( personExists (int personId)örneğin) varsa döndüren bir yöntem sağlamaya çalışırdım , başka bir örnek de containsKey ()bir MapJava'daki yöntem olurdu . Arayan kişinin kodunu daha temiz bir hale getirir, çünkü istediğiniz nesnenin bulunmaması olasılığını kolayca görebilirsiniz (kişi yoktur, anahtar haritada yoktur). Bir referansın nullbence kandırıp karıştırmadığını sürekli kontrol etmek bence.


3

null, aşağıdaki koşulların geçerli olması durumunda ve yalnızca döndürülmesi en iyi şeydir:

  • Normal işlemde boş sonuç bekleniyor . Bazı makul koşullar altında bir kişiyi bulamayacağınız beklenebilir, bu nedenle null döndüren findPerson () durumu iyidir. Ancak, gerçekten beklenmeyen bir hata ise (örneğin, saveMyImportantData () adlı bir işlevdeyse), bir İstisna atmanız gerekir. Adında bir ipucu var - İstisnalar istisnai durumlar içindir!
  • null, "bulunamadı / değer yok" anlamına gelir . Başka bir şey demek istiyorsan, başka bir şey iade et! İyi örnekler, Infinity veya NaN döndüren kayan nokta işlemleri olabilir - bunlar özel anlamları olan değerlerdir, bu nedenle burada boş dönerseniz çok kafa karıştırıcı olur.
  • İşlev, findPerson () gibi tek bir değer döndürmek içindir . Bir koleksiyon döndürmek için tasarlandıysa, örneğin findAllOldPeople (), boş bir koleksiyon en iyisidir. Bunun bir sonucu olarak, koleksiyonu döndüren bir işlevin hiçbir zaman boş döndürmemesi gerektiğidir .

Ayrıca , işlevin boş döndüğü gerçeğini belgelendiğinizden emin olun .

Bu kuralları izlerseniz, boş değerler çoğunlukla zararsızdır. Null değerini kontrol etmeyi unutursanız, normal olarak hemen sonra bir NullPointerException elde edersiniz, bu genellikle düzeltilmesi oldukça kolay bir hatadır. Bu hızlı başarısız yaklaşım, sisteminizde etrafa sessizce yayılan, muhtemelen bir istisna oluşturmadan, verileri bozan sahte bir dönüş değerine (örneğin boş bir dize) sahip olmaktan çok daha iyidir.

Son olarak, bu kuralları soruda listelenen iki fonksiyona uygularsanız:

  • FindPerson - kişi bulunmazsa bu işlevin boşa dönmesi uygun olur
  • ReverseString - bir dizgiyi geçerse sonuç asla başarısız olmaz gibi görünür (boş dizgiler de dahil olmak üzere tüm dizeler tersine çevrilebilir). Bu yüzden asla boşa dönmemelidir. Bir şey yanlış giderse (bellek yetersiz mi?) O zaman bir istisna atması gerekir.

1

Bence NULL döndürmek, bir miktar boş sonuç döndürmek (örneğin boş dize veya boş bir liste) ve bir istisna atmak arasında bir fark var.

Normalde aşağıdaki yaklaşımı alıyorum. Bir işlevi veya yöntemi f (v1, ..., vn) çağrısı bir işlevin uygulaması olarak kabul ediyorum

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

burada S, "dünyanın durumu" T1, ..., Tn, giriş parametresi tipleridir ve T, geri dönüş tipidir.

Önce bu işlevi tanımlamaya çalışıyorum. İşlev kısmi ise (yani bunun tanımlanmadığı bazı giriş değerleri var) bunu bildirmek için NULL döndürürüm. Bunun nedeni, hesaplamanın normal şekilde sonlandırılmasını ve istediğim fonksiyonun verilen girişlerde tanımlanmadığını söylemesini istemem. Örneğin, return değeri olarak boş bir dize kullanılması, işlev girişlerde tanımlandığı ve boş dize doğru sonuç olabileceği için belirsizdir.

Kısmi bir işlev uyguladığınız için çağrı kodundaki NULL bir işaretçi için fazladan kontrol yapılması gerekli olduğunu düşünüyorum ve işlev verilen girdi için tanımlanmamışsa, size söylenen yöntemin görevidir.

Hesaplamayı yapmasına izin vermeyen hatalar için istisnalar kullanmayı tercih ederim (yani herhangi bir cevap bulmak mümkün değildi).

Örneğin, bir sınıf Müşterim olduğunu varsayalım ve bir yöntem uygulamak istediğimi varsayalım.

Customer findCustomer(String customerCode)

Uygulama veritabanında bir müşteriyi koduyla aramak için. Bu yöntemde olurdum

  • Sorgu başarılı olursa, Müşteri sınıfı bir nesne döndürün,
  • Sorgu herhangi bir müşteri bulamazsa null değerini döndür.
  • Veritabanına bağlanmak mümkün değilse bir istisna atın.

Null için ekstra çek, örneğin

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

Yaptıklarımın anlambiliminin bir parçası ve kodun daha iyi okunması için sadece "atladım". Eldeki problemin anlamını basitleştirmenin sadece kodu basitleştirmenin iyi bir uygulama olduğunu düşünmüyorum.

Elbette, null kontrolü çok sık gerçekleştiğinden, dilin bunun için bazı özel sözdizimini desteklemesi iyi olur.

Ayrıca, bir sınıfın boş nesnesini diğer tüm nesnelerden ayırt edebildiğim sürece Null Object pattern'ini (Laf tarafından önerildiği şekilde) kullanmayı düşünürdüm.


0

Koleksiyon geri döndürme yöntemleri boş dönmelidir, ancak diğerleri null değerine geri dönebilir, çünkü koleksiyonlar için nesne olabilir, ancak içinde hiçbir öğe yoktur, bu nedenle arayan kişi her ikisi için de sadece boyutlarını doğrular.


0

Bana göre burada iki dava var. Eğer bir çeşit listeye dönüyorsanız, ne olursa olsun, her zaman listeyi iade etmelisiniz, eğer içine koymak için hiçbir şeyiniz yoksa, boş.

Herhangi bir tartışmayı gördüğüm tek vaka, tek bir ürün iade ettiğiniz zamanlar. Böyle bir durumda başarısızlık durumunda işleri hızlı bir şekilde başarısız kılma temelinde boş vermeyi tercih ediyorum.

Bir boş nesne döndürürseniz ve arayan gerçek bir nesneye ihtiyaç duyduğunda, devam edebilir ve beklenmedik davranışlar üreten boş nesneyi kullanmaya çalışabilirler. Bence durumla başa çıkmayı unuturlarsa rutinin patlaması daha iyi olur. Bir şey yanlışsa en kısa sürede bir istisna istiyorum. Böcekleri bu şekilde gönderme ihtimaliniz daha düşük.


0

İnsanların Maybetype yapıcı hakkında söylediklerini ekleyerek :

NPE'leri riske atmamaktan başka bir büyük kazanç semantiktir. Saf fonksiyonlarla uğraştığımız fonksiyonel dünyada, uygulandıklarında dönüş değerlerine tam olarak eşit olan fonksiyonları yapmaya çalışmayı seviyoruz . Şunu düşünün String.reverse(): Bu, belirli bir dize verilen dizenin ters çevrilmiş sürümünü temsil eden bir işlevdir. Bu dizgenin var olduğunu biliyoruz, çünkü her dize tersine çevrilebilir (dizeler temelde sıralı karakter kümeleridir).

Şimdi, peki ya findCustomer(int id)? Bu işlev, verilen kimliği olan müşteriyi temsil eder. Bu var olan veya olmayan bir şey. Ancak unutmayın, işlevlerin tek bir geri dönüş değeri vardır, bu yüzden gerçekten söyleyemezsiniz "bu işlev bir kimliği verilen bir kimlikle VEYA geri döndürür null.

Bu benim nullboş meselemde hem iade hem de geri dönen asıl meselem . Yanıltıcılar. nullmüşteri değil ve gerçekten de "müşterinin yokluğu" değil. Bir şey yokluğu. HİÇBİR ŞEYE işaretli sadece işaretsiz bir gösterge. Çok düşük seviye ve çok çirkin ve çok hata eğilimli. Boş bir nesne de bence oldukça yanıltıcıdır. Boş müşteri, müşteridir. Birinin yokluğu değil, istenen kimliği olan müşteri değil, bu yüzden geri dönmek sadece YANLIŞ. Bu istediğim müşteri DEĞİL, ama yine de bir müşteri iade ettiğini iddia ediyorsun. Yanlış kimliği var, açıkça bu bir hatadır. Yöntemin adı ve imzası tarafından önerilen sözleşmeyi ihlal eder. Müşteri kodunun tasarımınızla ilgili bir şeyler üstlenmesini veya belgeleri okumasını gerektirir.

Bu sorunların her ikisi de a Maybe Customer. Birdenbire, "bu işlev verilen kimliği olan müşteriyi temsil ediyor" demiyoruz. Diyoruz ki "bu işlev, müşteriyi verilen kimlikle temsil ediyorsa gösterir . Şimdi ne olduğu hakkında çok net ve açık. Var olmayan bir kimliğe sahip müşteri için sorarsanız, alacaksınız Nothing. Bu nasıl daha iyi? daha null? NPE risk için. Ama aynı zamanda tipi nedeniyle değil sadece Nothingadil değil Maybe. o var Maybe Customer. Bu semantik bir anlamı vardır. özel olarak bu tür bir müşterinin mevcut olmadığını belirten "bir müşteri yokluğunu" anlamına gelir.

Boş olan bir başka sorun ise elbette belirsiz olmasıdır. Müşteriyi bulamadınız mı, yoksa db bağlantı hatası mı vardı, yoksa bu müşteriyi görmeme izin yok mu?

Bunun gibi birkaç hata durumunuz varsa, bu sürümler için istisnalar atabilir ya da (ya da ben bunu tercih ederim) Either CustomerLoadError Customeryanlış giden bir şeyi ya da iade edilen müşteriyi temsil eden bir geri döndürebilirsiniz . Maybe CustomerNeyin yanlış gidebileceğini belirlemenize izin verirken tüm avantajlara sahiptir .

Peşinde olduğum en önemli şey, imzasındaki işlev sözleşmesini yakalamak. Bazı şeyleri varsaymayın, geçici sözleşmelere güvenmeyin, açık olun.


0

1) Eğer fonksiyonun semantiği hiçbir şeyi geri getiremezse, arayan kişi bunun için test etmelidir, aksi halde örneğin. Paranı al ve kimseye ver.

2) Anlamsal olarak her zaman bir şey döndüren (veya fırlatan) işlevler yapmak iyidir.

Bir kayıt cihazı ile , herhangi bir kayıt cihazı tanımlanmadıysa kayıt tutmayan kayıt cihazına geri dönmek mantıklı olur. Koleksiyona geri döndüğünde, hiçbir zaman döndürmemek hiçbir zaman anlamsız ("yeterince düşük seviye" dışında, koleksiyonun kendisinin veri olduğu, hiçbir şey içermemesidir), çünkü boş bir küme hiçbir şey değildir.

Bir kişi örneğiyle, "kış uykusuna yatar" yoluna giderim (vs vs load, IIRC, ancak orada tembel yükleme için proxy nesneler tarafından karmaşıklaşır), iki işlevi vardır, biri null, diğeri ise fırlatır.


-1
  • Uygulama kullanılabilir bir veri bekliyorsa ancak veriler mevcut değilse NULL döndürülmelidir. Örneğin, şehir bulunmazsa, CITY’i posta koduna göre döndüren bir hizmet null değerinde dönmelidir. Arayan kişi daha sonra boş olanı kullanmaya veya havaya uçurmaya karar verebilir.

  • İki olasılık varsa boş liste döndürülmelidir. Veri mevcut veya veri mevcut değil. Örneğin, nüfus belirli bir sayıdan büyükse, ŞEH (ler) i veren bir hizmet. Verilen kriterleri karşılayan hiçbir veri yoksa boş bir liste döndürebilir.


-2

NULL döndürmek , nesne yönelimli dünyada korkunç bir tasarım . Özet olarak, NULL kullanımı şunlara yol açar:

  • geçici hata işleme (istisnalar yerine)
  • belirsiz anlamsal
  • hızlı başarısızlık yerine yavaş
  • bilgisayarla düşünme vs nesne düşünme
  • değiştirilebilir ve eksik nesneler

Ayrıntılı bir açıklama için bu blog gönderisine bakın: http://www.yegor256.com/2014/05/13/why-null-is-bad.html

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.