İddiaların kilit rolünü anlamak için bazı gerçek hayat örnekleri nelerdir?
İddiaların kilit rolünü anlamak için bazı gerçek hayat örnekleri nelerdir?
Yanıtlar:
Java 1.4'e iddialar ( assert anahtar sözcüğü aracılığıyla) eklendi. Koddaki bir değişmezin doğruluğunu doğrulamak için kullanılırlar. Hiçbir zaman üretim kodunda tetiklenmemelidirler ve bir kod yolunda bir hata veya yanlış kullanım olduğunu gösterirler. Komuttaki -ea
seçenek aracılığıyla çalışma zamanında etkinleştirilebilirler java
, ancak varsayılan olarak açılmazlar.
Bir örnek:
public Foo acquireFoo(int id) {
Foo result = null;
if (id > 50) {
result = fooService.read(id);
} else {
result = new Foo(id);
}
assert result != null;
return result;
}
assert
herkese açık yöntem parametrelerini ( docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html ) kontrol etmek için kullanmamayı söyler . Bu bir Exception
programı öldürmek yerine atmalıdır.
This convention is unaffected by the addition of the assert construct. Do not use assertions to check the parameters of a public method. An assert is inappropriate because the method guarantees that it will always enforce the argument checks. It must check its arguments whether or not assertions are enabled. Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError.
docs.oracle.com/javase/8/docs/technotes/guides/language/…
Bir nükleer enerji santralini kontrol etmek için bir program yazmanız gerektiğini varsayalım. En küçük hatanın bile yıkıcı sonuçlara sahip olabileceği oldukça açıktır, bu nedenle kodunuzun hatasız olması gerekir (JVM'nin argüman uğruna hatasız olduğu varsayılarak).
Java, doğrulanabilir bir dil değildir, yani: işleminizin sonucunun mükemmel olacağını hesaplayamazsınız. Bunun ana nedeni işaretçilerdir: herhangi bir yere veya hiçbir yere işaret edemezler, bu nedenle en azından makul bir kod aralığı dahilinde değil, bu tam değere sahip oldukları hesaplanamazlar. Bu sorun göz önüne alındığında, kodunuzun bir bütün olarak doğru olduğunu kanıtlamanın bir yolu yoktur. Ancak yapabileceğiniz şey, en azından her hatayı oluştuğunda bulduğunuzu kanıtlamaktır.
Bu fikir, Sözleşmeye Göre Tasarım (DbC) paradigmasına dayanır: önce yönteminizin ne yapması gerektiğini (matematiksel hassasiyetle) tanımlarsınız ve daha sonra bunu gerçek yürütme sırasında test ederek doğrularsınız. Misal:
// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
return a + b;
}
Bu iyi çalışmak oldukça açık olsa da, çoğu programcı bunun içindeki gizli hatayı görmeyecektir (ipucu: Ariane V benzer bir hata nedeniyle çöktü). Şimdi DbC, düzgün çalıştığını doğrulamak için her zaman bir işlevin giriş ve çıkışını kontrol etmeniz gerektiğini tanımlar . Java bunu iddialarla yapabilir:
// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
assert (Integer.MAX_VALUE - a >= b) : "Value of " + a + " + " + b + " is too large to add.";
final int result = a + b;
assert (result - a == b) : "Sum of " + a + " + " + b + " returned wrong sum " + result;
return result;
}
Bu işlev şimdi başarısız olursa, fark edeceksiniz. Kodunuzda bir sorun olduğunu bilirsiniz, nerede olduğunu bilirsiniz ve neye neden olduğunu bilirsiniz (İstisnalara benzer). Ve daha da önemlisi: başka bir kodun yanlış değerlerle çalışmasını önlemek ve kontrol ettiği her şeye zarar vermesini önlemek için doğru yürütmeyi durdurursunuz.
Java İstisnaları benzer bir kavramdır, ancak her şeyi doğrulayamazlar. Daha fazla kontrol istiyorsanız (yürütme hızı pahasına) iddiaları kullanmanız gerekir. Bunu yapmak kodunuzu şişirir, ancak sonunda bir ürünü şaşırtıcı derecede kısa bir geliştirme zamanında teslim edebilirsiniz (ne kadar erken bir hatayı düzeltirseniz, maliyet o kadar düşük olur). Ayrıca: kodunuzun içinde herhangi bir hata varsa, onu tespit edersiniz. Bir hatanın kayması ve daha sonra sorunlara neden olmasının bir yolu yoktur.
Bu hala hatasız kod için bir garanti değildir, ancak normal programlardan çok daha yakındır.
new IllegalArgumentException
ile mesaj atmak yerine ne arasındaki fark nedir ? Yani, o throws
yöntem bildirimi ve bu istisnayı başka bir yerde yönetmek için kod eklemek o bir yana . Neden assert
yeni bir İstisna atmak istiyorsun? Ya da if
bunun yerine neden olmasın assert
? Gerçekten
a
negatif olabilirse yanlıştır . İkinci iddia işe yaramaz; int değerleri için her zaman a + b - b == a söz konusudur. Bu sınama yalnızca bilgisayar temelden kırıksa başarısız olabilir. Bu olasılığa karşı savunmak için, birden fazla CPU arasında tutarlılığı kontrol etmeniz gerekir.
İddialar, kodunuzdaki hataları yakalamak için bir geliştirme aşaması aracıdır. Kolayca çıkarılacak şekilde tasarlanmıştır, bu nedenle üretim kodunda mevcut olmazlar. Dolayısıyla, iddialar müşteriye sunduğunuz "çözüm" ün bir parçası değildir. Yaptığınız varsayımların doğru olduğundan emin olmak için dahili kontrollerdir. En yaygın örnek null değerini sınamaktır. Birçok yöntem şöyle yazılır:
void doSomething(Widget widget) {
if (widget != null) {
widget.someMethod(); // ...
... // do more stuff with this widget
}
}
Çoğu zaman böyle bir yöntemde, widget hiçbir zaman boş olmamalıdır. Bu nedenle, boşsa, kodunuzda izlemeniz gereken bir hata vardır. Ancak yukarıdaki kod size bunu asla söylemeyecektir. Yani "güvenli" kod yazmak için iyi niyetli bir çabayla, bir hatayı da saklıyorsunuz. Bunun gibi bir kod yazmak çok daha iyidir:
/**
* @param Widget widget Should never be null
*/
void doSomething(Widget widget) {
assert widget != null;
widget.someMethod(); // ...
... // do more stuff with this widget
}
Bu şekilde, bu hatayı erken yakalayacağınızdan emin olacaksınız. (Sözleşmede bu parametrenin hiçbir zaman boş olmaması gerektiğini belirtmek de yararlıdır.) Geliştirme sırasında kodunuzu test ederken iddiaları açtığınızdan emin olun. (Ve meslektaşlarınızı da bunu yapmaya ikna etmek genellikle zordur, ki bu çok can sıkıcı buluyorum.)
Şimdi, bazı meslektaşlarınız, üretimde bir istisnayı önlemek için yine de boş kontrol yapmanız gerektiğini savunarak bu koda itiraz edecekler. Bu durumda, iddia hala yararlıdır. Bunu şöyle yazabilirsiniz:
void doSomething(Widget widget) {
assert widget != null;
if (widget != null) {
widget.someMethod(); // ...
... // do more stuff with this widget
}
}
Bu şekilde, iş arkadaşlarınız null kontrolünün üretim kodu için orada olduğu için mutlu olacaklar, ancak geliştirme sırasında artık widget null olduğunda hatayı gizlemiyorsunuz.
İşte gerçek dünya örneği: Bir keresinde eşitlik için iki keyfi değeri karşılaştıran bir yöntem yazdım, burada her iki değer de boş olabilir:
/**
* Compare two values using equals(), after checking for null.
* @param thisValue (may be null)
* @param otherValue (may be null)
* @return True if they are both null or if equals() returns true
*/
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
} else {
result = thisValue.equals(otherValue);
}
return result;
}
Bu kod, equals()
thisValue değerinin boş olmaması durumunda yöntemin çalışmasını devreder. Ancak, null parametresini uygun equals()
şekilde işleyerek yöntemin sözleşmeyi doğru şekilde yerine getirdiğini varsayar equals()
.
Bir meslektaşım, kodumuza itiraz etti ve sınıflarımızın çoğunun equals()
null için test edilmeyen buggy yöntemleri olduğunu söyledi, bu yüzden bu kontrolü bu yönteme koymalıyım. Bu akıllıca ise tartışmalı veya hatayı zorlamalıyız, bu yüzden onu tespit edip düzeltebiliriz, ancak meslektaşım için ertelendi ve bir yorum ile işaretlediğim boş bir kontrol yaptım:
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
} else {
result = otherValue != null && thisValue.equals(otherValue); // questionable null check
}
return result;
}
Buradaki ek kontrol other != null
, ancak equals()
yöntem, sözleşmesinin gerektirdiği şekilde null olup olmadığını kontrol edemezse gereklidir.
İş arkadaşımla, buggy kodunun kod tabanımızda kalmasına izin vermenin bilgeliği hakkında meyvesiz bir tartışmaya girmek yerine, sadece kodda iki iddiada bulundum. Bu iddialar, geliştirme aşamalarında, sınıflarımızdan biri equals()
düzgün bir şekilde uygulanamazsa, bunu bana bildirir , böylece düzeltebilirim:
public static boolean compare(final Object thisValue, final Object otherValue) {
boolean result;
if (thisValue == null) {
result = otherValue == null;
assert otherValue == null || otherValue.equals(null) == false;
} else {
result = otherValue != null && thisValue.equals(otherValue);
assert thisValue.equals(null) == false;
}
return result;
}
Akılda tutulması gereken önemli noktalar şunlardır:
İddialar sadece geliştirme aşaması araçlarıdır.
Bir iddianın amacı, sadece kodunuzda değil, kod tabanınızda bir hata olup olmadığını bildirmektir . (Buradaki iddialar aslında diğer sınıflardaki hataları işaretleyecektir.)
Meslektaşım sınıflarımızın düzgün bir şekilde yazıldığından emin olsa bile, buradaki iddialar hala yararlı olacaktır. Null değerini sınamayabilecek yeni sınıflar eklenir ve bu yöntem bu hataları bizim için işaretleyebilir.
Geliştirmede, yazdığınız kod iddia kullanmasa bile her zaman iddiaları açmalısınız. IDE'm bunu yeni yürütülebilir dosyalar için her zaman varsayılan olarak yapacak şekilde ayarlanmıştır.
İddialar, üretimdeki kodun davranışını değiştirmez, bu nedenle meslektaşım, null kontrolün orada olduğundan ve equals()
yöntem buggy olsa bile bu yöntemin düzgün bir şekilde yürütülmesinden memnun olur . Mutluyum çünkü equals()
kalkınmada herhangi bir buggy yöntemi yakalayacağım .
Ayrıca, başarısız olacak geçici bir iddiayı koyarak onaylama politikanızı test etmelisiniz, böylece günlük dosyası veya çıktı akışındaki bir yığın izlemesi yoluyla bilgilendirileceğinizden emin olabilirsiniz.
assert
Anahtar kelimenin ne yaptığını açıklayan çok sayıda iyi yanıt , ancak asıl soruyu yanıtlayan çok az cevap var, "assert
anahtar kelime gerçek hayatta kullanılmalıdır?"
Cevap: neredeyse asla .
Kavram olarak iddialar harikadır. İyi kod çok sayıda if (...) throw ...
ifadeye sahiptir (ve akrabaları Objects.requireNonNull
ve gibi Math.addExact
). Bununla birlikte, belirli tasarım kararları, assert
anahtar kelimenin kendisinin kullanımını büyük ölçüde sınırlandırmıştır .
assert
Anahtar kelimenin arkasındaki itici fikir erken optimizasyon ve ana özellik tüm kontrolleri kolayca kapatabiliyor. Aslında, assert
kontroller varsayılan olarak kapalıdır.
Ancak üretimde değişmez kontrollerin yapılmaya devam edilmesi kritik önem taşımaktadır. Bunun nedeni, mükemmel test kapsamının imkansız olması ve tüm üretim kodlarının, teşhislerin teşhis edilmesine ve hafifletilmesine yardımcı olması gereken hatalara sahip olmasıdır.
Bu nedenle, if (...) throw ...
genel yöntemlerin parametre değerlerini kontrol etmek ve atmak için gerekli olduğu gibi , kullanımı tercih edilmelidir IllegalArgumentException
.
Bazen, işlenmesi istenmeyen uzun bir zaman alan (ve önemli olması için yeterince sık çağrılan) değişmez bir kontrol yazmak cazip gelebilir. Bununla birlikte, bu tür kontroller istenmeyen bir testtir. Bu tür zaman alıcı kontroller genellikle birim testler olarak yazılır. Bununla birlikte, bazen assert
bu nedenle kullanmak mantıklı olabilir .
Kullanmayın assert
o daha temiz ve daha güzel olduğu için basitçe if (...) throw ...
(ve çünkü ben temiz ve hoş gibi büyük bir acıyla söylemek). Kendinize yardım edemiyorsanız ve uygulamanızın nasıl başlatıldığını kontrol edebiliyorsanız, kullanmaktan çekinmeyin, assert
ancak üretimde her zaman iddiaları etkinleştirin. Kuşkusuz, bunu yapmaya eğilimliyim. Daha çok assert
hareket etmesine neden olacak bir lombok ek açıklaması için bastırıyorum if (...) throw ...
. Burada oy verin.
(Rant: JVM geliştiricileri, bir sürü korkunç, erken optimizasyon kodlayıcıydı. Bu yüzden Java eklentisinde ve JVM'de çok fazla güvenlik sorunu duydunuz. Üretim koduna temel kontrolleri ve iddiaları eklemeyi reddettik ve fiyatı ödeyin.)
catch (Throwable t)
. OutOfMemoryError, AssertionError, vs.'den tuzak kurmaya, günlüğe kaydetmeye veya yeniden denemeye / kurtarmaya çalışmamak için hiçbir neden yoktur
assert
Anahtar kelimenin uygulanması kötüdür. Cevaba değil, anahtar kelimeye atıfta bulunduğumu daha açık hale getirmek için cevabımı düzenleyeceğim.
İşte en yaygın kullanım örneği. Bir numaralandırma değerini açtığınızı varsayalım:
switch (fruit) {
case apple:
// do something
break;
case pear:
// do something
break;
case banana:
// do something
break;
}
Her davayı ele aldığınız sürece, iyisiniz. Ama bir gün, biri enumunuza incir ekleyecek ve bunu anahtar ifadenize eklemeyi unutacak. Bu, yakalanması zor olabilecek bir hata üretir, çünkü efektler, switch deyimini terk edene kadar hissedilmez. Ancak anahtarınızı böyle yazarsanız, hemen yakalayabilirsiniz:
switch (fruit) {
case apple:
// do something
break;
case pear:
// do something
break;
case banana:
// do something
break;
default:
assert false : "Missing enum value: " + fruit;
}
AssertionError
if ifadeleri etkinleştirilmişse ( -ea
) atar . Üretimde istenen davranış nedir? Daha sonra infaz sessiz sessiz bir op ve potansiyel felaket? Muhtemelen değil. Ben açık bir öneriyorum throw new AssertionError("Missing enum value: " + fruit);
.
default
ki derleyici kayıp durumlarda sizi uyarabilir. Bunun return
yerine break
(yöntemin çıkarılması gerekebilir) ve daha sonra anahtardan sonra eksik durumu işleyebilirsiniz. Bu şekilde hem uyarı hem de bir fırsat elde edersiniz assert
.
Son koşullar ve "asla başarısız olmamalıdır" ön koşullarını kontrol etmek için iddialar kullanılır. Doğru kod asla bir iddiada başarısız olmamalıdır; tetiklediklerinde bir hata belirtmelidirler (umarım sorunun gerçek lokusunun bulunduğu yere yakın bir yerde).
Bir iddiaya örnek olarak, belirli bir yöntem grubunun doğru sırada çağrıldığını kontrol etmek (ör. hasNext()
önce çağrılır next()
bir in Iterator
).
Java'daki assert anahtar kelimesi ne işe yarar?
Derlenmiş bayt koduna bakalım.
Sonuç olarak:
public class Assert {
public static void main(String[] args) {
assert System.currentTimeMillis() == 0L;
}
}
neredeyse aynı bayt kodunu oluşturur:
public class Assert {
static final boolean $assertionsDisabled =
!Assert.class.desiredAssertionStatus();
public static void main(String[] args) {
if (!$assertionsDisabled) {
if (System.currentTimeMillis() != 0L) {
throw new AssertionError();
}
}
}
}
nerede Assert.class.desiredAssertionStatus()
olduğu true
zaman-ea
aksi Komut satırına geçirilen ve yanlış olduğunu.
System.currentTimeMillis()
Optimize edilmemesini sağlamak için kullanıyoruz ( assert true;
yaptı).
Sentetik alan, Java'nın Assert.class.desiredAssertionStatus()
yükleme sırasında yalnızca bir kez çağrı yapması için oluşturulur ve ardından sonucu burada önbelleğe alır. Ayrıca bakınız: "Statik sentetik" in anlamı nedir?
Bunu aşağıdakilerle doğrulayabiliriz:
javac Assert.java
javap -c -constants -private -verbose Assert.class
Oracle JDK 1.8.0_45 ile sentetik bir statik alan üretildi (ayrıca bkz: "statik sentetik" in anlamı nedir? ):
static final boolean $assertionsDisabled;
descriptor: Z
flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
statik bir başlatıcı ile birlikte:
0: ldc #6 // class Assert
2: invokevirtual #7 // Method java/lang Class.desiredAssertionStatus:()Z
5: ifne 12
8: iconst_1
9: goto 13
12: iconst_0
13: putstatic #2 // Field $assertionsDisabled:Z
16: return
ve ana yöntem:
0: getstatic #2 // Field $assertionsDisabled:Z
3: ifne 22
6: invokestatic #3 // Method java/lang/System.currentTimeMillis:()J
9: lconst_0
10: lcmp
11: ifeq 22
14: new #4 // class java/lang/AssertionError
17: dup
18: invokespecial #5 // Method java/lang/AssertionError."<init>":()V
21: athrow
22: return
Şu sonuca varıyoruz ki:
assert
: bir Java dili konseptidirassert
komut satırında -Pcom.me.assert=true
değiştirilecek sistem özellikleri ile oldukça iyi bir şekilde taklit edilebilir -ea
ve a throw new AssertionError()
.catch (Throwable t)
madde de iddia ihlallerini yakalayabiliyor mu? Benim için faydalarını sadece iddianın gövdesinin zaman alıcı olduğu durumla sınırlandırır, bu nadirdir.
AssertionError
ilkini yakalayıp yeniden yapabilirsiniz .
Stack sınıfından gerçek bir dünya örneği ( Java Makalelerindeki Onaylama'dan )
public int pop() {
// precondition
assert !isEmpty() : "Stack is empty";
return stack[--num];
}
Bir iddia, koddaki hataları tespit etmeyi sağlar. Test ve hata ayıklama için, programınız hazırlanırken bunları kapalı bırakarak iddiaları açabilirsiniz.
Bunun doğru olduğunu bildiğinizde neden bir şey iddia ediyorsunuz? Bu sadece her şey düzgün çalışıyorsa geçerlidir. Programda bir kusur varsa, aslında doğru olmayabilir. Bunu işlemin başlarında tespit etmek, bir şeyin yanlış olduğunu bilmenizi sağlar.
Bir assert
ifade, isteğe bağlı bir String
mesajla birlikte bu ifadeyi içerir .
Bir assert ifadesinin sözdiziminin iki formu vardır:
assert boolean_expression;
assert boolean_expression: error_message;
Aşağıda, iddiaların nerede ve nerede kullanılmaması gerektiğini belirleyen bazı temel kurallar verilmiştir. İddialar gerektiğini kullanılacak:
Özel bir yöntemin giriş parametrelerini doğrulama. Herkese açık yöntemler için DEĞİLDİR . public
yöntemler kötü parametreler iletildiğinde düzenli istisnalar atmalıdır.
Programın herhangi bir yerinde, neredeyse kesinlikle doğru olan bir gerçeğin geçerliliğini sağlamak.
Örneğin, yalnızca 1 veya 2 olacağından eminseniz, aşağıdaki gibi bir iddia kullanabilirsiniz:
...
if (i == 1) {
...
}
else if (i == 2) {
...
} else {
assert false : "cannot happen. i is " + i;
}
...
İddialar olmamalıdır için kullanılabilir:
Genel bir yöntemin giriş parametrelerini doğrulama. İddialar her zaman uygulanamayabileceğinden, düzenli istisna mekanizması kullanılmalıdır.
Kullanıcı tarafından girilen bir şey üzerindeki kısıtlamaları doğrulama. Yukarıdaki ile aynı.
Yan etkiler için kullanılmamalıdır.
Örneğin, bu uygun bir kullanım değildir, çünkü burada iddia, doSomething()
yöntemin çağrılmasının yan etkisi için kullanılır.
public boolean doSomething() {
...
}
public void someMethod() {
assert doSomething();
}
Bunun gerekçelendirilebileceği tek durum, kodunuzda iddiaların etkinleştirilip etkinleştirilmediğini bulmaya çalıştığınız durumdur:
boolean enabled = false;
assert enabled = true;
if (enabled) {
System.out.println("Assertions are enabled");
} else {
System.out.println("Assertions are disabled");
}
Burada verilen tüm harika cevaplara ek olarak, resmi Java SE 7 programlama kılavuzunun kullanımı hakkında oldukça özlü bir el kitabı vardır assert
; iddiaları kullanmanın iyi (ve önemli olarak kötü) bir fikir olduğu ve istisnalar atmanın ne kadar farklı olduğuna dair birkaç örnek.
Assert gelişirken çok faydalıdır. Bir şey yapamadığında kullanırsın kodunuzu doğru çalışıp çalışmadığını olur. Kullanımı kolaydır ve kodda sonsuza kadar kalabilir, çünkü gerçek hayatta kapatılacaktır.
Durumun gerçek hayatta ortaya çıkma şansı varsa, o zaman ele almalısınız.
Bayıldım ama Eclipse / Android / ADT'de nasıl açılacağını bilmiyorum. Hata ayıklama sırasında bile kapalı görünüyor. (Bu konuda bir iş parçacığı vardır, ancak ADT Çalışma Yapılandırmasında görünmeyen 'Java vm' anlamına gelir).
İşte bir Hibernate / SQL projesi için bir sunucuda yazdığım bir iddia. Bir varlık fasulyesinin isActive ve isDefault adı verilen iki etkin-boolean özelliği vardı. Her birinin değeri "Y" veya "N" veya null olabilir, bu değer "N" olarak kabul edilir. Tarayıcı istemcisinin bu üç değerle sınırlı olduğundan emin olmak istiyoruz. Yani, bu iki özellik için seterlerimde, bu iddiayı ekledim:
assert new HashSet<String>(Arrays.asList("Y", "N", null)).contains(value) : value;
Aşağıdakilere dikkat edin.
Bu iddia sadece geliştirme aşaması içindir. Müşteri kötü bir değer gönderirse, üretime ulaşmadan çok önce bunu yakalayıp düzeltiriz. İddialar erken yakalayabileceğiniz kusurlar içindir.
Bu iddia yavaş ve verimsizdir. Sorun yok. İddialar yavaş olmakta serbesttir. Umurumuzda değil çünkü sadece geliştirme araçları. Bu, üretim kodunu yavaşlatmayacaktır çünkü iddialar devre dışı bırakılacaktır. (Bu konuda daha sonra alacağım bazı anlaşmazlıklar var.) Bu benim bir sonraki noktama götürüyor.
Bu iddianın yan etkisi yoktur. Değişimimi değiştirilemez bir statik final Setine karşı test edebilirdim, ancak bu set hiç kullanılmayacağı üretimde kaldı.
Bu iddia, istemcinin düzgün çalıştığını doğrulamak için mevcuttur. Üretime ulaştığımızda, müşterinin düzgün çalıştığından emin olacağız, böylece iddiayı güvenli bir şekilde kapatabiliriz.
Bazı insanlar bunu soruyor: Üretimde iddiaya ihtiyaç duyulmuyorsa, neden sadece işiniz bittiğinde bunları çıkarmıyorsunuz? Çünkü bir sonraki versiyonda çalışmaya başladığınızda hala onlara ihtiyacınız olacak.
Bazı insanlar asla iddiaları kullanmamanız gerektiğini savundu, çünkü tüm hataların gittiğinden asla emin olamazsınız, bu yüzden onları üretimde bile tutmanız gerekir. Ve böylece assert ifadesini kullanmanın bir anlamı yok, çünkü iddia etmenin tek avantajı onları kapatabiliyor olmanız. Bu nedenle, bu düşünceye göre, (neredeyse) asla takıntı kullanmamalısınız. Katılmıyorum. Bir test üretime aitse, bir iddia kullanmamanız kesinlikle doğrudur. Ama bu test yapar değil üretime ait . Bu, üretime hiç ulaşması muhtemel olmayan bir hatayı yakalamak içindir, bu nedenle işiniz bittiğinde güvenle kapatılabilir.
BTW, şöyle yazmış olabilirdim:
assert value == null || value.equals("Y") || value.equals("N") : value;
Bu sadece üç değer için iyidir, ancak olası değerlerin sayısı artarsa HashSet sürümü daha uygun hale gelir. Verimlilik konusunu vurgulamak için HashSet sürümünü seçtim.
HashSet
, herhangi bir hız avantajı sağladığından şüpheliyim ArrayList
. Dahası, set ve liste kreasyonları arama süresine hakimdir. Sabit kullanırken iyi olurlar. Hepsi dedi +1.
İddia temelde uygulamada hata ayıklamak için kullanılır veya bir uygulamanın geçerliliğini kontrol etmek için bazı uygulamalar için kural dışı durum işleme yerine kullanılır.
İddia çalışma zamanında çalışır. Tüm kavramı çok basit bir şekilde açıklayabilen basit bir örnek, buradadır - assert anahtar kelimesi Java'da ne yapar? (WikiAnswers).
İddialar varsayılan olarak devre dışıdır. Bunları etkinleştirmek için programı -ea
seçeneklerle çalıştırmalıyız (ayrıntı düzeyi değişebilir). Örneğin java -ea AssertionsDemo
,.
İddiaları kullanmak için iki format vardır:
assert 1==2; // This will raise an AssertionError
.assert 1==2: "no way.. 1 is not equal to 2";
Bu, verilen mesajın da görüntülenmesiyle bir AssertionError hatası oluşturur ve bu nedenle daha iyidir. Gerçek sözdizimi assert expr1:expr2
expr2'nin bir değer döndüren herhangi bir ifade olabilmesine rağmen, bunu yalnızca bir ileti yazdırmak için daha sık kullandım.Özetlemek gerekirse (ve bu sadece Java için değil, birçok dil için de geçerlidir):
"assert", hata ayıklama işlemi sırasında öncelikle yazılım geliştiricileri tarafından bir hata ayıklama yardımcısı olarak kullanılır. Onay mesajları asla görünmemelidir. Birçok dil, "üretim" kodunun üretilmesinde kullanılmak üzere tüm "varsayımların" yok sayılmasına neden olacak bir derleme zamanı seçeneği sunar.
"istisnalar", mantık hatalarını temsil etseler de etmeseler de her türlü hata koşulunu ele almanın kullanışlı bir yoludur, çünkü devam edemeyeceğiniz bir hata koşuluyla karşılaşırsanız, bunları "havaya fırlatabilir, "Nerede olursanız olun, başka birisinin onları" yakalamaya "hazır olmasını bekliyorsunuz. Kontrol, istisnayı atan koddan doğrudan yakalayıcının eldivenine tek adımda aktarılır. (Ve alıcı gerçekleşen çağrıların tam geri izini görebilir.)
Dahası, bu altyordamın arayanları, altyordamın başarılı olup olmadığını kontrol etmek zorunda değildir: "şimdi buradaysak, başarılı olmalıydı, çünkü aksi halde bir istisna atardı ve şimdi burada olmazdık!" Bu basit strateji kod tasarımını ve hata ayıklamayı çok daha kolay hale getirir.
İstisnalar, ölümcül hata koşullarının oldukları gibi olmasını sağlar: "kuralın istisnaları". Ve onlar için de "kuralın bir istisnası ... " sinek topu!
İddialar kapatılabilecek kontrollerdir. Nadiren kullanılırlar. Neden?
result != null
tür kontroller çok hızlı olduğu ve kaydedilecek pek bir şey olmadığı gibi basit kontroller için kullanılmamalıdır .Peki geriye ne kaldı? Gerçekten doğru olması beklenen koşullar için pahalı kontroller . Buna iyi bir örnek, RB ağacı gibi bir veri yapısının değişmezleri olacaktır. Aslında, ConcurrentHashMap
JDK8'de, bu tür birkaç anlamlı iddia vardır TreeNodes
.
Bazen, çek gerçekten pahalı değil, ama aynı zamanda oldukça eminsin, geçecek. Kodumda, örneğin,
assert Sets.newHashSet(userIds).size() == userIds.size();
Yeni oluşturduğum listenin benzersiz öğeleri olduğundan eminim, ancak bunu belgelemek ve tekrar kontrol etmek istedim.
Temel olarak, "assert true" geçer ve "assert false" başarısız olur. Bunun nasıl çalışacağına bakalım:
public static void main(String[] args)
{
String s1 = "Hello";
assert checkInteger(s1);
}
private static boolean checkInteger(String s)
{
try {
Integer.parseInt(s);
return true;
}
catch(Exception e)
{
return false;
}
}
assert
bir anahtar kelimedir. JDK 1.4'te tanıtıldı. İki tür assert
s
assert
ifadelerassert
ifadeler.Varsayılan olarak tüm assert
ifadeler yürütülmez. Bir assert
ifade yanlış alırsa, otomatik olarak bir onaylama hatası oluşturur.