Boolean mantığının sürdürülebilirliği - İfadelere ihtiyaç duyulursa iç içe yerleştirme var mı?


11

Bunlardan hangisi sürdürülebilirlik için daha iyidir?

if (byteArrayVariable != null)
    if (byteArrayVariable .Length != 0)
         //Do something with byteArrayVariable 

VEYA

if ((byteArrayVariable != null) && (byteArrayVariable.Length != 0))
  //Do something with byteArrayVariable 

Ben ikinci okuma ve yazma tercih, ama kod böyle bir şey yapmanın sürdürülebilirlik için kötü olduğunu tam okuma hatırlıyorum.

Bunun nedeni if, ilk bölüm yanlışsa ve tüm diller bunu yapmıyorsa , ikinci bölümünü değerlendirmemek için dile güveniyor olmanızdır . (Boş olarak değerlendirilirse ikinci bölüm bir istisna atar byteArrayVariable.)

Bunun gerçekten endişelenecek bir şey olup olmadığını bilmiyorum ve soru hakkında genel geri bildirim almak istiyorum.

Teşekkürler.


1
İlk formun başkalarının
sarkma

sadece merak ediyorum, hangi dilde çalışıyorsun?
STW

@STW - C # kullanıyoruz ve Delphi'de bazı eski kodlarımız var.
Vaccano

2
bunu bildiğim iyi oldu. Ben Delphi aşina değilim ama C # &&ve ||kısa devre değerlendirme gerçekleştirme operatörleri emin olabilirsiniz . Bir dilden diğerine geçmek genellikle bazı gotcha'lara sahiptir ve bu küçük sorunları yakalamaya yardımcı olmak için kod incelemeleri yapmak konusunda sağlam olmak iyidir.
STW

Burada birçok cevapla birlikte ikinciyi daha okunabilir buluyorum, birincisi hata ayıklamak için çok daha kolay. Bu durumda, ikincisini kullanmaya devam ediyorum çünkü hata ayıklamak için kolay kontrol ediyorsunuz. Ama genel olarak dikkatli olun.
Magus

Yanıtlar:


30

İkinci formun iyi olduğunu ve ayrıca ne yapmaya çalıştığınızı daha açık bir şekilde temsil ettiğini düşünüyorum. Bunu sen söyledin...

Ben kod tamamıyla okuma hatırlıyorum böyle şeyler yapmanın sürdürülebilirlik için kötü olduğunu. Bunun nedeni, eğer birinci bölüm yanlışsa ve tüm diller bunu yapmıyorsa, if'nin ikinci bölümünü değerlendirmemek için dile güveniyor olmanızdır.

Tüm dillerin bunu yapması önemli değil . Var mısın yazı bir eğer belirli bir dil, bu nedenle sadece önemli olan o dili bunu yapmaz. Aksi takdirde, aslında belirli bir dilin özelliklerini kullanmamanız gerektiğini söylüyorsunuz çünkü diğer diller bu özellikleri desteklemeyebilir ve bu sadece aptalca.


12
Kabul. Neden başka bir dile kopyalandığında kodumun aynı şekilde çalışıp çalışmayacağını umuyorum?
Tim Goodman

16

Kimsenin bahsetmediğine şaşırdım (umarım soruyu yanlış okumam) - ama her ikisi de emmek!

Daha iyi bir alternatif, erken çıkışları kullanmak olacaktır (başka bir kod yürütülmemesi gerekiyorsa, kodun başına bir return ifadesi yerleştirmek). Bu, kodunuzun nispeten iyi bir şekilde yeniden düzenlendiğini ve her yöntemin özlü bir amacı olduğunu varsayar.

Bu noktada şöyle bir şey yaparsınız:

if ((byteArrayVariable == null) || (byteArrayVariable.Length != 0)) {
  return; // nothing to be done, leaving
}

// Conditions met, do something

Doğrulama gibi görünebilir - ve tam da budur. Yöntemin bir şey yapması için koşulların yerine getirildiğini doğrular - sunduğunuz her iki seçenek de ön mantık denetimleri içindeki gerçek mantığı gizledi.

Kodunuz çok fazla spagetti ise (loooong yöntemleri, aralarına dağılmış mantık ile iç içe ifs vb.), Daha küçük stilistik sorunlardan önce kodunuzu şekillendirmek için daha büyük probleme odaklanmalısınız. Ortamınıza ve karışıklığın ciddiyetine bağlı olarak, yardımcı olacak bazı harika araçlar vardır (örneğin, Visual Studio'nun bir "Extract Method" refactoring işlevi vardır).


Jim'in bahsettiği gibi, erken çıkışın nasıl yapılandırılacağı konusunda hala tartışmalar için yer var . Yukarıdakilere alternatif:

if (byteArrayVariable == null) 
  return; // nothing to be done, leaving

if (byteArrayVariable.Length != 0)
  return;

// Conditions met, do something

1
İyi mantığın sarılması yerine geri dönüşe katılıyorum, ama aynı insanlar || && için olduğu gibi.
MIA

14

Her için tuzak çalışırken zaman kaybetmeyin olmayan bu durum. Verileri veya durumu diskalifiye edebiliyorsanız, bunu mümkün olan en kısa sürede yapın.

if (byteArrayVariable == null) Exit;
if (byteArrayVariable.Length == 0) Exit;
// do something

Bu, kodunuzu yeni koşullar için çok daha kolay uyarlamanızı sağlar

if (byteArrayVariable == null) Exit;
if (byteArrayVariable.Length == 0) Exit;
if (NewCondition == false) Exit;
if (NewerCondition == true) Exit;
// do something

2
+1 Evet, evet, evet. Bu kadar basit bir mantık zor kodlarla sonuçlanmamalıdır. (Askerin) bağırsağın sana bunu söylüyor olmalı.
İş

11

Örneğiniz, iç içe geçmiş ifsBoole karşılaştırmasını düzgün bir şekilde destekleyen çoğu dil için neden kötü bir yaklaşım olduğuna mükemmel bir örnektir . Yuvalamak, ifsniyetinizin net olmadığı bir durum yaratır. İkincisinin ifhemen ilkini takip etmesi gerekli mi? Yoksa sadece oraya henüz başka bir işlem yapmadığınız için mi?

if ((byteArrayVariable != null) && (byteArrayVariable.Length != 0))
  //Do something with byteArrayVariable 

Bu durumda, bunlar hemen hemen birlikte olmalıdır . İstisnaya neden olacak bir işlem yapmamanızı sağlamak için bir koruyucu görevi görürler. İç içe kullanarak ifs, onu izleyen kişinin, iki parçalı bir bekçi mi yoksa başka bir dallanma mantığını mı temsil ettiği konusunda yorumlamaya bırakın. Onları tek bir araya getirerek ifbunu belirtiyorum. İçinde olmaması gereken bir operasyonu gizlemek çok daha zor.

Birisinin aptalca iddiası konusundaki niyetimin her zaman "tüm dillerde çalışmadığı" konusunda açık bir şekilde iletişim kurmayı tercih edeceğim. Bil bakalım ne ... throwtüm dillerde de çalışmıyor, bu C # veya Java kodlama yaparken kullanmamalıyım ve bunun yerine bir sorun olduğunda sinyal vermek için dönüş değerlerine güvenmesi gerektiği anlamına mı geliyor?

Bu çok daha okunabilir onu çevirin ve ya eğer sadece yöntemin dışına dönmek olduğunu söyledi Bütün değil STW Yanıtlarında söylediği gibi memnun.


İkiden fazla koşul, kendi işlevlerini geçersiz kılabilir.
İş

3

Bu durumda iki cümleniz doğrudan ilişkilidir, bu nedenle 2. form tercih edilir.

İlişkilendirilmediylerse (örneğin, farklı koşullarda bir dizi koruma maddesi) o zaman 1. formu tercih ederim (veya bileşik koşulun gerçekte neyi temsil ettiğini gösteren bir isim içeren bir yöntemi yeniden düzenlerdim).


1

Delphi'de çalışıyorsanız, ilk yol genel olarak daha güvenlidir. (Belirtilen örnek için, iç içe ifs kullanmanın getireceği çok şey yoktur.)

Delphi, derleyici anahtarları aracılığıyla boole ifadelerinin değerlendirilip değerlendirilmeyeceğini veya "kısa devre" olup olmadığını belirlemenizi sağlar. # 1 yolunun (iç içe ifs) yapılması, ikinci cümlenin yalnızca ilk cümle doğru olarak değerlendirilirse (ve kesinlikle sonra ) yürütüldüğünden emin olmanızı sağlar .


1
Delphi gelişiminin 23 yılında hiçbir zaman "Complete boolean eval" seçeneğini değiştirmedim. Başka bir yere kod göndersem, birime {$ BOOLEVAL OFF} veya {$ B-} koyardım.
Gerry

Ben de değil. Ben de her zaman menzil kontrolü kullanıyorum ... ama diğer insanlar kullanmıyor Ve bu olmamalı sen çünkü belki performans açısından haricinde bir fark yaratmak olmamalı boolean ifadeleri kullanılan fonksiyonlarda yan etkileri kullanıyor. Eminim oradaki biri yapar!
Frank Shearar

@Gerry: Kabul etti. Muhtemelen tam değerlendirme isteyebilmenizin tek nedeni yan etkilerdir ve şartlı yan etkiler kötü bir fikirdir!
Loren Pechtel

Sadece yorumumu tekrar okuyun 23 yıl 13 olmalı! Bir Tardisim yok
Gerry

1

İkinci stil VBA'da geri tepebilir, çünkü ilk test oluşturulan nesne ise, yine de ikinci test ve hata yapacaktır. Her zaman ilk yöntemi kullanmak için nesne doğrulamasıyla uğraşırken VBA'da alışkanlığım var.


2
Çünkü VBA korkunç bir dildir
Falmarri

@Falmarri, bu konuda bazı korkunç şeyler (ve bazı iyi şeyler) var. Eğer druthers'ım olsaydı birçok şeyi düzeltirdim

2
Kısa devre Boole değerlendirmesinin olmaması her şeyden çok eski bir şeydir. Neden bununla başlamadıklarını bilmiyorum. OrElse ve AndAlso'nun VB.NET "düzeltmesi" biraz sinir bozucu, ancak muhtemelen geriye dönük uyumluluğu bozmadan onunla başa çıkmak için tek seçenek.
JohnFx

1

İkinci form, özellikle her bir cümlenin etrafında {} bloklar kullanıyorsanız daha okunabilirdir, çünkü ilk form, iç içe {} bloklara ve okumak için bir acı olabilecek birden fazla girinti seviyesine yol açacaktır (girinti boşluklarını saymanız gerekir) her bloğun nerede biteceğini bulmak için).


0

Her ikisini de okunabilir buluyorum ve dil değiştirmek için kodun sürdürülebilirliği konusunda endişelenmeniz gerektiği iddiasını kabul etmiyorum.

Bazı dillerde ikinci seçenek daha iyi performans gösterir, bu yüzden o zaman net seçim olacaktır.


0

Seninleyim; İkinci yoldan yapıyorum. Bana göre, bu mantıksal olarak daha net. İlkinde yanlış olarak değerlendirilse bile bazı dillerin ikinci kısmı yürüteceği endişesi bana biraz aptalca geliyor, çünkü hayatımda asla "bazı dillerde" çalışan bir program yazmadım; kodum her zaman belirli bir dilde var gibi görünüyor, ya da bu yapıyı idare edebilir ya da yapamaz. (Ve eğer belirli bir dilin üstesinden gelip gelemeyeceğinden emin değilsem, bu gerçekten öğrenmem gereken bir şey, değil mi?)

Zihnimde, bunu yapmanın ilk yolu ile ilgili tehlike, ifistemediğim zaman yanlışlıkla o yuvalanmış bloğun dışına kod koymaya karşı savunmasız bırakmam. Kuşkusuz ki, bu büyük bir endişe kaynağı değildir, ancak kodumun dil bilincine sahip olup olmadığı konusunda endişelenmekten daha mantıklı görünüyor.


0

İkinci seçeneği tercih ediyorum, çünkü daha okunabilir.

Uyguladığınız mantık daha karmaşıksa (bir dizenin boş olmadığını ve boş olmadığını kontrol etmek sadece bir örnektir), yararlı bir yeniden düzenleme yapabilirsiniz: bir boolean işlevi ayıklayın. "Kod Tamamlandı" notunda mipadi ile beraberim ("tüm diller bunu yaparsa önemli değil ...") Kodunuzun okuyucusu, çıkarılan işlevin içine bakmakla ilgilenmiyorsa, sipariş boolean işlenenlerin değerlendirildiği onlar için tartışmalı bir soru haline gelir.


0
if ((byteArrayVariable != null)
 && (byteArrayVariable.Length != 0)) {
    //Do something with byteArrayVariable 

ama bu temel olarak ikinci seçenek.

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.