Bir nesne bulunursa döndürülmesi gereken bir yöntem var.
Bulunmazsa, yapmalıyım:
- boş döndür
- istisna atmak
- diğer
Bir nesne bulunursa döndürülmesi gereken bir yöntem var.
Bulunmazsa, yapmalıyım:
Yanıtlar:
Her zaman bir değer bulmayı bekliyorsanız, eksikse istisnayı atın. İstisna, bir sorun olduğu anlamına gelir.
Değer eksik veya mevcut olabilir ve her ikisi de uygulama mantığı için geçerliyse, null değerini döndürün.
Daha önemli: Koddaki diğer yerleri ne yapıyorsunuz? Tutarlılık önemlidir.
GetPersonById(25)
o kişi silinirse atar, ancak GetPeopleByHairColor("red")
boş bir sonuç döndürür. Bence parametreler beklentiler hakkında bir şeyler söylüyor.
Sadece gerçekten bir hata ise bir istisna atın. Nesnenin bulunmaması beklenen bir davranışsa, null değerini döndürün.
Aksi takdirde bu bir tercih meselesidir.
Genel bir kural olarak, yöntemin her zaman bir nesneyi döndürmesi gerekiyorsa, istisna ile devam edin. Ara sıra null değerini tahmin ediyorsanız ve belirli bir şekilde ele almak istiyorsanız, null ile devam edin.
Ne yaparsanız yapın, üçüncü seçeneğe karşı şiddetle tavsiye ederim: "WTF" yazan bir dize döndürme.
Null hiçbir zaman hata belirtmezse, null değerini döndürün.
Null her zaman bir hataysa, bir istisna atayın.
Null bazen bir istisna ise, iki rutini kodlayın. Bir yordam bir istisna atar, diğeri ise bir çıktı parametresinde nesneyi döndüren ve nesne bulunmazsa rutin false değerini döndüren bir boolean sınama yordamıdır.
Bir Try rutinini kötüye kullanmak zor. Boş olup olmadığını kontrol etmeyi unutmak çok kolay.
Yani null bir hata olduğunda sadece
object o = FindObject();
Null bir hata olmadığında,
if (TryFindObject(out object o)
// Do something with o
else
// o was not found
find
ve findOrFail
laravel anlamlı gelen
TryFindObject
yöntemden döndürülecek çok özellikli bir nesne tanımlamak olmaz mıydı? Tuples, birden fazla değeri kapsayan bir nesneyi tanımlamak için zaman ayırmak istemeyen programcılar için daha tembel bir paradigma gibi görünüyor. Bu aslında tüm tuples özünde zaten.
Sadece daha önce belirtilen seçenekleri tekrarlamak istedim, yenilerini fırlatmak istedim:
Veya şu seçenekleri birleştirebilirsiniz:
Arayanızın aşırı yüklenmiş birkaç sürümünü sağlayın, böylece arayan hangi yöne gideceğine karar verebilir. Çoğu durumda, yalnızca ilkinin arama algoritmasının bir uygulaması vardır ve diğeri sadece ilkinin etrafını sarar:
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
Yalnızca bir uygulama sağlasanız bile, sözleşmenizi netleştirmek için böyle bir adlandırma kuralı kullanmak isteyebilirsiniz ve başka uygulamalar eklemeye karar vermenizde size yardımcı olur.
Aşırı kullanmamalısınız, ancak birçok farklı hata işleme kuralına sahip yüzlerce farklı uygulamada kullanacağınız bir yardımcı Sınıf yazarken özellikle yardımcı olabilir.
Expected<T> findObject(String)
nerede Expected<T>
işlevlere sahiptir orNull()
, orThrow()
, orSupplied(Supplier<T> supplier)
, orDefault(T default)
. Bu, hata işlemeden verilerin alınmasını
Boş nesne desenini kullanın veya bir istisna atın.
Person somePerson = personRepository.find("does-not-exist");
bu yöntemin kimlik için boş bir nesne döndürdüğünü varsayalım does-not-exist
. O zaman doğru davranış ne için olurdu somePerson.getAge()
? Şu anda, null nesne modelinin varlık aramaları için doğru çözüm olduğuna ikna olmadım.
İstisna atmanın avantajları:
Örneklerle daha fazla açıklama için bkz. Http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/
dilinizin ve kodunuzun tanıtımına göre değişir: LBYL (sıçramadan önce bak) veya EAFP (izin vermekten daha kolay affetme istemek)
LBYL, değerleri kontrol etmeniz gerektiğini söylüyor (bu yüzden boş bir değer
döndürün ) EAFP, işlemi denemek ve başarısız olup olmadığını görmek (bir istisna atmak ) diyor
yukarıdaki kabul ediyorum ama .. istisnalar istisnai / hata koşulları için kullanılmalıdır ve çekleri kullanırken bir boş döndürme en iyisidir.
EAFP ve Python'daki LBYL:
http://mail.python.org/pipermail/python-list/2003-May/205182.html
( Web Arşivi )
Sadece kendinize şunu sorun: "nesnenin bulunmaması istisnai bir durum mu?" Programınızın normal seyrinde olması bekleniyorsa, muhtemelen bir istisna oluşturmamalısınız (istisnai bir davranış olmadığı için).
Kısa sürüm: Programınızdaki normal kontrol akışını işlememek için değil, istisnai davranışları işlemek için istisnalar kullanın.
-AIan.
İstisnalar Sözleşme ile Tasarım ile ilgilidir.
Bir nesnenin arayüzü aslında iki nesne arasındaki bir sözleşmedir, arayan sözleşmeyi karşılamalıdır, aksi takdirde alıcı sadece bir istisna dışında başarısız olabilir. İki olası sözleşme vardır
1) tüm giriş yöntemi geçerlidir, bu durumda nesne bulunmadığında null değerini döndürmeniz gerekir.
2) yalnızca bir girdi geçerlidir, yani bulunan bir nesne ile sonuçlanır. Bu durumda, arayanın girişinin doğru olup olmadığını belirlemesini sağlayan ikinci bir yöntem SAĞLAMALIDIR. Örneğin
is_present(key)
find(key) throws Exception
EĞER VE SADECE 2. sözleşmenin her iki yöntemini de sağlarsanız, hiçbir şey bulunmadığı bir istisna atmanıza izin verilir!
Nesnenin bulunamamasının ne anlama geldiğine bağlıdır.
Normal bir durumsa, null değerini döndürün. Bu sadece arada bir olabilecek bir şeydir ve arayanlar bunu kontrol etmelidir.
Bu bir hataysa, bir istisna atarsa, arayanlar eksik nesnenin hata koşuluyla ne yapacağına karar vermelidir.
Nihayetinde de işe yarayacaktır, ancak çoğu insan genellikle İstisnaları sadece bir şey, istisnai olduğunda istisnalar kullanmanın iyi bir uygulama olarak görmesine rağmen.
İşte birkaç öneri daha.
Bir koleksiyon döndürüyorsanız, null döndürmekten kaçının, önce boş bir koleksiyon olmadan numaralandırmanın başlamasını kolaylaştıran boş bir koleksiyon döndürün.
Birkaç .NET API'sı, arayan kişiye nesne gerçekten istisnai bir durum mu yoksa nesne bulunmadığı mı seçenek olarak bir thrownOnError parametresi deseni kullanır. Type.GetType buna bir örnektir. BCL ile başka bir yaygın desen, bir boolean döndürüldüğü ve değerin bir çıkış parametresi yoluyla iletildiği TryGet desenidir.
Ayrıca, varsayılan veya davranış içermeyen bir sürüm olabilen bazı durumlarda Null Nesne desenini de düşünebilirsiniz. Anahtar, kod tabanı boyunca boş denetimlerden kaçınmaktır. Daha fazla bilgi için buraya bakın http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx
İstisna atmak yerine null döndürün ve API belgelerinde null dönüş değeri olasılığını açıkça belgeleyin. Çağıran kod API'yı onurlandırmazsa ve boş durumu kontrol ederse, büyük olasılıkla bir tür "boş işaretçi istisnası" ile sonuçlanır :)
C ++, bir nesne bulmak bir yöntem kurmak için 3 farklı tatlar düşünebilirsiniz.
Seçenek A
Object *findObject(Key &key);
Bir nesne bulunamadığında null değerini döndürün. Güzel ve basit. Ben bununla giderdim. Aşağıdaki alternatif yaklaşımlar parazitlerden nefret etmeyen insanlar içindir.
Seçenek B
void findObject(Key &key, Object &found);
Nesneyi alacak değişkene bir başvuru iletin. Bir nesne bulunamadığında yöntem bir istisna attı. Bu kural, bir nesnenin bulunamaması gerçekten beklenmiyorsa, muhtemelen daha uygundur - dolayısıyla beklenmedik bir durum olduğunu belirtmek için bir istisna atarsınız.
Seçenek C
bool findObject(Key &key, Object &found);
Bir nesne bulunamadığında yöntem false değerini döndürür. Bu A seçeneğine göre avantajı, hata durumunu tek bir adımda kontrol edebilmenizdir:
if (!findObject(myKey, myObj)) { ...
sadece null'un istisnai bir davranış olarak kabul edilmediği durumdan bahsederken, kesinlikle deneme yöntemi için kullanıyorum, burada söylendiği gibi "kitabı okumaya" veya "sıçramadan önce bak" a gerek yok
temelde:
bool TryFindObject(RequestParam request, out ResponseParam response)
ve bu, kullanıcının kodunun da net olacağı anlamına gelir
...
if(TryFindObject(request, out response)
{
handleSuccess(response)
}
else
{
handleFailure()
}
...
İstemci kodunun bulunan ve bulunmayan arasındaki farkı bilmesi önemliyse ve bunun rutin bir davranış olması gerekiyorsa, null değerini döndürmek en iyisidir. Böylece müşteri kodu ne yapacağınıza karar verebilir.
Genellikle null değerini döndürmelidir. Yöntemi çağıran kod, bir istisna atamaya mı yoksa başka bir şey yapmaya mı karar verecektir.
Veya bir Seçenek döndürün
Bir seçenek temel olarak istemciyi kabin kasalarını işlemeye zorlayan bir konteyner sınıfıdır. Scala'nın bu konsepti var, API'sına bakın.
Daha sonra bu nesne üzerinde bulunan nesneyi döndüren veya istemci belirtimlerini içeren bir alternatif olan T getOrElse (T valueIfNull) gibi yöntemleriniz vardır.
Ne yazık ki JDK tutarsız, eğer kaynak paketinde mevcut olmayan anahtara erişmeye çalışıyorsanız, istisna bulamazsınız ve haritadan değer talep ettiğinizde mevcut değilse null alırsınız. Bu yüzden kazanan cevabı değiştirebilirim, eğer bulunan değer null olabilirse, bulunmadığında istisnayı yükseltir, aksi takdirde null döndürür. Bu nedenle, kuralın bir istisnasını uygulayın, değerin neden bulunmadığını bilmeniz gerekiyorsa, her zaman istisnayı yükseltin veya ..
Nesneye bir başvuru döndürmesi gerektiği sürece, bir NULL döndürmek iyi olmalıdır.
Ancak, tüm kanlı şeyi döndürüyorsa (eğer yaparsanız C ++ gibi: 'return & blah;' yerine 'return blah;' (veya 'blah' bir işaretçi), o zaman bir NULL döndüremezsiniz, çünkü Bu durumda, bir istisna atmak veya bir başarı bayrağı ayarlanmamış boş bir nesne döndürmek, soruna nasıl yaklaşacağımdır.
İstisna taşıma yükü bahsetti kimse sanmıyorum - bu kadar gerçek bir uygulama öldürme veya işlem durdurma olayı (ileri gitmek iyi daha fazla zarar neden olur) sürece yüklemek ve istisna işlemek için ek kaynaklar alır bir geri geçmek için tercih ediyorum çağıran ortamın uygun gördüğü şekilde yorumlayabileceği değer.
Burada fikir birliği gibi görünen şeylere katılıyorum ("bulunamadı" ise normal bir olası sonuçsa null değerini döndürün veya durumun anlambilimi nesnenin her zaman bulunmasını gerektiriyorsa bir istisna atın).
Bununla birlikte, özel durumunuza bağlı olarak anlamlı olabilecek üçüncü bir olasılık vardır. Yönteminiz, "bulunamadı" koşulunda bir tür varsayılan nesne döndürebilir ve arama kodunun, boş denetime veya özel durum yakalamaya gerek kalmadan her zaman geçerli bir nesne alacağından emin olmasını sağlar.
İstisnalar olmalıdır olağanüstü . Boş döndürmek için geçerliyse null döndür .
Yöntem bir koleksiyon döndürürse, boş bir koleksiyon döndürün (yukarıda belirtildiği gibi). Ama lütfen Collections.EMPTY_LIST veya benzeri değil! (Java durumunda)
Yöntem tek bir nesne alırsa, bazı seçenekleriniz vardır.
Boş bir değer döndürmeye karar verirseniz dikkatli olun. Projede tek programcı değilseniz, çalışma zamanında NullPointerExceptions (Java'da veya diğer dillerde ne olursa olsun) alacaksınız! Bu nedenle derleme zamanında denetlenmeyen boş değer döndürmeyin.
null
. Daha fazla bilgi için en çok oy alan cevaba bakın.
Bir kitaplık veya istisna oluşturan başka bir sınıf kullanıyorsanız, kitabı yeniden denemeniz gerekir. İşte bir örnek. Örnek2.java kütüphane gibidir ve Örnek.java nesnesini kullanır. Main.java bu İstisnayı ele almak için bir örnektir. Arayan tarafta kullanıcıya anlamlı bir mesaj göstermeli ve (gerekirse) izlemeyi yığınlamalısınız.
Main.java
public class Main {
public static void main(String[] args) {
Example example = new Example();
try {
Example2 obj = example.doExample();
if(obj == null){
System.out.println("Hey object is null!");
}
} catch (Exception e) {
System.out.println("Congratulations, you caught the exception!");
System.out.println("Here is stack trace:");
e.printStackTrace();
}
}
}
Example.java
/**
* Example.java
* @author Seval
* @date 10/22/2014
*/
public class Example {
/**
* Returns Example2 object
* If there is no Example2 object, throws exception
*
* @return obj Example2
* @throws Exception
*/
public Example2 doExample() throws Exception {
try {
// Get the object
Example2 obj = new Example2();
return obj;
} catch (Exception e) {
// Log the exception and rethrow
// Log.logException(e);
throw e;
}
}
}
Example2.java
/**
* Example2.java
* @author Seval
*
*/
public class Example2 {
/**
* Constructor of Example2
* @throws Exception
*/
public Example2() throws Exception{
throw new Exception("Please set the \"obj\"");
}
}
Bu gerçekten nesneyi bulup bulmayacağınıza bağlıdır. Bir şeyi belirtmek için istisnaların kullanılması gerektiği düşüncesini takip ederseniz, o zaman, hata, istisnai bir durum ortaya çıktı:
Aksi takdirde null değerini döndürün.