ELSE kötü programlama kullanıyor mu? [kapalı]


18

Sık sık ELSEyapıyı kullanmaktan kaynaklanan hatalarla karşılaştım . Bunun en iyi örneği, aşağıdakiler doğrultusunda bir şeydir:

If (passwordCheck() == false){
    displayMessage();
}else{
    letThemIn();
}

Bana göre bu güvenlik problemi bağırıyor. PasswordCheck'in bir boolean olacağını biliyorum, ancak uygulamalarımın güvenliğini buna koymam. Bir dize, int vb ise ne olur?

Ben genellikle kullanmaktan kaçınmaya çalışıyorum ELSEve bunun yerine ne beklediğimi test etmek için iki tamamen ayrı IF deyimlerini tercih ediyorum. O zaman ya görmezden gelinir VEYA özel olarak ele alınır.

Elbette bu, uygulamanıza giren hataları / güvenlik sorunlarını önlemenin daha iyi bir yoludur.

Bunu nasıl yapıyorsunuz?


3
Sizin için güvenlik sorunu nedir? "PasswordCheck" ne anlama geliyor? Şifre kontrolü yapıldı mı? Bir şifre kontrolü olmalı mı? Kullanıcı geçti mi? Kullanıcı doğru şifreyi giremedi mi?
LennyProgrammers

20
I know that passwordCheck is likely to be a boolean...Ne demek istiyorsun? Herhangi bir güçlü dilde. passwordCheckne olacak sen olmasını istiyorum.
Bobby

31
Kötü girinti uygulamaları elseifadeleri kullanmaktan daha fazla hataya neden olduğunu düşünüyorum ...
gablin

15
Bu tuhaf görünüyor. İlk olarak, passwordCheck()muhtemelen boolean olmama olasılığından şikayet ediyorsunuz (makul bir endişe olabilir) ve sonra suçluyorsunuz else? elseSebepleri hangi problemleri görmüyorum .
David Thornley

8
mmm, başka kullanmanın kötü olup olmadığını sormak programlama kötü programlama
Muad'Dib

Yanıtlar:


90

elseBlok her zaman varsayılan davranış olmasını istediklerini oluşmalıdır.

Onlardan kaçınmaya gerek yok, sadece uygun şekilde kullanmaya dikkat edin.

Örneğin, varsayılan durum erişime izin vermemelidir. Biraz yeniden düzenleme sizi şunlarla bırakır:

If (passwordCheck)
{
   letThemIn();
}
else
{
   displayMessage();
}

örn. şifre kontrolü çalışırsa, içeri girin, aksi takdirde bazı hata mesajlarını göstermek daima geçerlidir.

Elbette else iftamamen ayrı ififadeler kullanmak yerine mantığınıza ek kontroller ekleyebilirsiniz .


2
@ dave.b örneği bağlamında, sanırım bu bir güvenlik sorunu olurdu, ancak bu, baktığınız kod tabanındaki her yerdeyse, daha fazla kimin yazdığının bir işareti daha fazla uygulama :)
RYFN

9
Birisi bunun güvenlik yönünü açıklayabilir mi? if! Bunun güvenliği açısından farkın ne olduğunu anlamaya çalışıyorum?
Chris

11
@Chris: Bence OP zayıf yazılmış bir dil kullanıyor. Bu nedenle passwordCheckherhangi bir şey, fe olabilir nullkılacak, passwordCheck == falsehiç falseve kullanıcı, bir iç hata nedeniyle oturum olanak sağlayacak.
Bobby

1
@Chris, benim anlayışım, varsayılan durumun mutlaka tavsiye edilmeyen erişime izin vermek olduğu idi.
RYFN

3
Evet, bu çok dile bağlı. C #, içinde ifbir gerektiriyor bool, değişkenler kesinlikle herhangi bir nedenle sırasını düşünemiyorum, bütün yollar vb bir değer döndürmesi gerekir, atanmalıdır ifve elseokunabilirliği yanında önemli olurdu. Yani, if(a){b();}{c();}eşdeğer olmalıdır if(!a){c();{b();}. JavaScript'inizde Öte yandan, sen farkında olmak zorunda passwordCheckolabilir undefinedvs.
Tim Goodman

57

Hayır, yanlış bir şey yok ELSE. ELSEyeni değil GOTO. Aslında, IFyerine iki s kullanmak ELSEbirkaç soruna yol açabilir.

Birinci örnek:

if (this(is(a(very())==complex(check())))) {
   doSomething();
}

if (!this(is(a(very())==complex(check())))) {
   doTheOtherThing();
}

Kopyala-yapıştır'ı görüyor musunuz? Sadece birini değiştirip diğerini unutduğunuz günü bekler.

İkinci örnek:

foreach(x in y) {
  if (first_time) {
    first_time = false;
    doSomething();
  }

  if (!first_time) {
    doTheOtherThing();
  }
}

Gördüğünüz gibi IF, koşul zaten değiştiğinden, ikinci öğe de ilk öğe için yürütülür. Gerçek dünya programlarında, bu tür hataların fark edilmesi daha zordur.


12
Buna katılıyorum. Bir ififadeyi kopyalayıp yapıştırma ve boole ifadesini tersine çevirmekten kaçınmak için else- şimdi bu kötü programlama! Sadece kodu kopyalamakla kalmaz ( kötü programlama), aynı zamanda performansı yavaşlatırsınız (kontrol gerçekten karmaşıksa, şimdi iki kez yapıyorsunuz - ba-- uh, peki, erken optimizasyonlar hakkında ne söylediklerini biliyorsunuz günümüzde ... çok iyi bir programlama değil !).
gablin

Dürüst olmak gerekirse, doğru / yanlış döndürmek için
çekin

İyi örnekler, eğer başka biriyle eşleştirilmişse, bir kontrol yerine 2 kullanmanın performansını unutmayalım. Çoğu dilde bir if / else kullanarak bir koşul ile değil kullanarak iki if ifadeleri kullanarak daha iyi performans varsayalım.
Chris

1
dave.b: tabii, ama basit başlayabilir ve yavaş büyüyebilir; örneğimdeki karmaşık kontrol sorunu daha açık hale getirmek için burada.
user281377

3
Evet - ve koşulların çoğu dilde yan etkileri olabileceğini ve koşullarda gerçekten bakarak söyleyemediğiniz işlevler olduğunu unutmayın.
David Thornley

18

Her zaman bir ELSE vardır. Yazarsan

if(foo)
  bar();

aslında yazıyorsun

if(foo)
{
  bar();
}
else
{
   // do nothing
}

ELSE yoluna koyduğunuz her şey sizin sorumluluğunuzdadır.


7
-1. Bu cevap çok saçma. Ben bunun doğru olmadığını söylemiyorum. Sadece noktayı kaçırıyor.

3
Sorular "ELSE kötü programlama kullanıyor mu?" Cevabım: orada yokmuş gibi davranabilirsiniz, ancak bundan kaçınamazsınız.
LennyProgrammers

5
hangi dil ? Java'da başka bayt
kodunda

@ acidzombie24 - herhangi bir sorudan 'başkasının' ne olduğunu düşünmek çok iyi bir uygulamadır. Bazen sadece - fucntiondaki her şeyi yapın, ancak bunu düşündüğünüzü gösteriyor
Martin Beckett

14

Kişisel elseolarak elimden geldiğince kaçınma eğilimindeyim , ancak bu herhangi bir güvenlik sorunu için değil .

Kodu okurken, iç içe ifadeler mantığı takip etmeyi zorlaştırır, çünkü hangi koşulların orada yol açacağını hatırlamanız gerekir. Bu nedenle, ben erken çıkış büyük bir hayranıyım:

if (checkPassword != OK) { displayMessage(); return; }

letThemIn();

Bu aynı zamanda kullanacağım forve whiledöngüler için de geçerlidir continueve breakne zaman girintiden kaçınırsa.

Chris Lattner bunu LLVM Kodlama Standartlarında benden daha iyi söylüyor .


Katılıyorum. "else" zihinsel bir "çatal" yaratır ve biz insanlar sıralı yaratıklardır.
user187291

Fyi, buna koruma koşulu deniyor
CaffGeek

@Chad: ah teşekkürler, işler için isim almak her zaman güzel :)
Matthieu M.

1
+1. Ben> 1 puan var ben durabilirim tek cevap budur. *writes an answer*

Bu şekilde başkalarından kaçınmaya çalışmıyorum, ama yazdıklarına katılıyorum. Mesele şu ki, test ettiğiniz şey normal durum değil istisna olmalıdır ( stackoverflow.com/questions/114342/… ). Burada kimlik doğrulama hatası istisnadır ve (yalnızca) sınanması gerekir.
hlovdal

5

Sonra onları değiştirin,

If (passwordCheck == true)
{
     letThemIn();
}
else
{
     displayMessage();
}

21
Nasıl If ((passwordCheck == true) == true)? :-)
Hippo

1
Okunabilirliği artırmak benim tarzım. Eğer yazabilirsiniz (! Değer) ama eğer tercih ederim (değer! = Doğru)
Ahmet Kakıcı

7
Okunabilirliği artırmaz. Sadece gürültü ekler. Daha da kötüsü, Boolean operatörlerinden korktukları için yapı yaparlarsa iç içe yazan programcılardır.
ak2

3
Değişken adı açıklayıcıysa, bunun bir nedeni yoktur: if (someBooleanValue == true) gerekli olmalıdır. Bu daha iyi olurdu: if (validPassword) {...
Mark Freedman

Peki ben sadece soru içindeki kod bloklarını değiştirdi. Benim ilk yorum okuduysanız, ben (! Value) yerine if (value! = True) kullanmayı tercih ettiğimi söyledim. Umarım if (değer) ve if (! Değeri) arasındaki farkı görebilirsiniz. Tamamlayıcı operatör kullanmam demek istedim. Aksi takdirde haklısınız, doğru demek doğru demektir.
Ahmet Kakıcı

3

Matthieu M. gibi ben de derinden iç içe geçmiş başka bloklara erken çıkmayı tercih ederim ... İyi savunma programlamasını gösterir (kötü koşullar varsa, devam etmenin anlamı yok). Birçok insan bizimle aynı fikirde değil, çıkış noktasını tercih ediyor; tartışmanın konusu değil (sanırım).

Şimdi, elseözellikle basit, kısa alternatifler için mantıklı olduğunda kesinlikle kullanıyorum . Söylendiği gibi, testi çoğaltmak zaman kaybıdır (programcı ve CPU'lar), karışıklık kaynağı ve daha sonra hatalar (biri değiştiğinde diğeri değil).
Bazen, elsedurumun ne olduğunu (özellikle ifparça uzunsa, örneğin eski kodda) veya alternatifin ne olduğunu hatırlatarak parçaya bir yorum ekliyorum .

İşlevsel programlamanın bazı aşırı taraftarlarının, ifdesen eşleştirme lehine tamamen kurtulmayı önerdiğini unutmayın ... Benim zevkime göre biraz fazla. :-)


1
bir yan not olarak: Eğer saf işlevsel dilinizde bir if yapınız varsa, o zaman gerçekten başka bir şeye sahip olmanız gerekir. Her ifade bir şey döndürmek zorundadır!
tokland

2

ELSE kullanımında yanlış bir şey yok. Ancak, okunması ve anlaşılması zor olan aşırı karmaşık koda yol açabilir. Kötü bir tasarımı gösterebilir. Test edilmesi gereken ek kullanım durumlarını kesinlikle gösterir.

Mümkünse ELSE'leri çıkarmaya çalışın - ancak paranoyak olma. Steve McConnell Code Complete'de bu düz çizgi kodunu çağırır. Yani kodunuzda basit ve net bir yol var.

Sorununuz için denemek için yaklaşımlar:

  • polimorfizm kullanın. Sisteminizin sınırında kullanıcının güvenlik kimlik bilgilerini doğrulayın. Meşru ise, sistemin ilgili bölümlerine erişerek veya bir istisna atarak bir oturum nesnesi döndürün. Ancak bu, sistemi daha karmaşık hale getirebilir. Böylece, neyin daha kolay anlaşılıp sürdürüleceğine siz karar verirsiniz.

Genel olarak - aşağıdakiler kodunuzdaki ELSE'leri azaltmaya yardımcı olabilir:

  • iyi gereksinimler kodda bu tür kararlara duyulan ihtiyacı azaltabilir. Kullanım senaryosunu (başka) hiç uygulamanız gerekmeyebilir.
  • daha net tasarım. Maksimum kohezyon ve kuplajı en aza indirin. Bu, bileşenlerin diğer bileşenlerde alınan kararları kopyalamamasını sağlar.
  • hata durumlarını yönetmek için kural dışı durum işleme.
  • polimorfizm (yukarıdaki örneğe bakınız).
  • anahtar ifadeleri - bunlar yüceltilen ELSE'lerdir, ancak bazı durumlarda daha iyidir.

2
"Karmaşık boole denetimlerini ayrı bir işleve taşı" da eklerdim.
gablin

2

Kodun güvenlik sızıntısı olduğu hakkındaki varsayımınız , kullandığınız dile bağlı olarak doğru olabilir veya olmayabilir . C kodunda bir sorun olabilir (özellikle C'de bir boole yalnızca sıfır veya sıfır olmayan bir int olduğundan) - ancak passwordCheckdeğişken bir boolean olarak bildirilmişse en güçlü yazılan dillerde (yani çalışma zamanı türü denetimi) , ona başka bir şey atamanın bir yolu yok. Aslında, ifmantıksal işleçleri kullanın ya da sadece değeri kullanın, bir yüklemdeki her şey bir boole'ye çözümlenmelidir. Çalışma zamanına bağlı başka bir nesne türünü yönetmeyi başardıysanız, bir tür passwordCheckyasadışı döküm istisnası atar.

Basit if / else yapılarının okunması if / if yapılarından çok daha kolaydır - ve birisi yapıyı çevirmeye çalıştığında yanlışlıkla sorunlara daha az eğilimlidir. Aynı örneği bir saniyeliğine ele alalım:

if(passwordCheck == false) {
    denyAccess();
}

if(passwordCheck) {
    letThemIn();
}

Yukarıda yürütmek istediğiniz birbirini dışlayan tümceciklerin anlamı kaybolur. İf / else yapısının anlattığı budur. Birinin her zaman çalışacağı, birbirini dışlayan iki yürütme dalı. Bu, güvenliğin önemli bir parçasıdır - aradıktan letThemInsonra bunu yapmanın yolu yoktur denyAccess.

Kodun anlaşılır olması ve kritik bölümlerin en iyi şekilde korunmasını sağlamak amacıyla, bunlar birincil fıkra ( ifbölüm) içinde olmalıdır . Varsayılan uyumlu olmayan davranış, alternatif cümlede ( elseparça) olmalıdır. Örneğin:

if(passwordCheck) {
    letThemIn();
} else {
    denyAccess();
}

NOT: Farklı dillerle çalışırken, "ya bir dize olursa?" Sorusunu önlemeye yardımcı olan bir kodlama alışkanlığı geliştirdim. Esasen, sabiti ilk olarak boole ifadesinde koymaktır. Örneğin, kontrol etmek yerine kontrol passwordCheck == falseediyorum false == passwordCheck. Bu ayrıca C ++ 'da yanlışlıkla atama sorununu önler. Bu yaklaşımı kullanarak, derleyici yazmam =yerine şikayet edecek ==. Java ve C # gibi dillerde derleyici, if yan tümcesindeki atamayı hata olarak ele alır, ancak C ++ bunu memnuniyetle kabul eder. Bu yüzden birinciyle null kontrol yapma eğilimindeyim null.

Dilleri düzenli olarak değiştirirseniz, sabiti önce yerleştirmek çok yardımcı olur. Ancak, ekibimde kodlama standardının tersidir ve derleyici bu sorunları yine de yakalar. Kırılması zor bir alışkanlık olabilir.


1

elseProgramlama yaparken kullanmanın kötü olduğunu söylemek, otherwisekonuşma yaparken kullanmanın kötü olduğunu söylemek gibidir .

Elbette, ikisi de kötü şekillerde kullanılabilir, ancak bu, onları dahil eden bir hata yaptığınız için kaçınılması gerektiği anlamına gelmez. Birçok hata default, bir switchifadede eksik bir duruma bağlıysa şaşırmazdım .


1

ElseUygulama akışınızı beyaz listeleyen olarak düşünün . Uygulama akışının devam etmesine izin vermesi gereken koşulları kontrol edersiniz ve bunlar karşılanmazsa, Elsesorunu çözmek, uygulama yürütmeyi durdurmak veya benzer bir şey yapmak için yürütülürsünüz.

Else kendi başına kötü değildir, ancak kötü kullanırsanız, istenmeyen etkiler görebilirsiniz.

Ayrıca,

"PasswordCheck'in büyük olasılıkla bir boole olacağını biliyorum, ancak uygulama güvenliğimi buna koymam."

Geliştirdiğiniz yöntemler için DAİMA bir veri türü döndürür. Her ne kadar PHP Core iki veya daha fazla veri tipi döndüren kodlarla doluysa da, işlev çağrılarını tahmin ettiği için bu kötü bir uygulamadır. Birden fazla veri türü döndürmeniz gerekiyorsa, bir istisna atmayı düşünün (bunun genellikle başka bir veri türünü döndürmek istememin nedeni olduğunu düşünüyorum - bir şey korkunç, korkunç bir şekilde yanlış gitti) veya kodunuzu yeniden yapılandırmayı düşünebilirsiniz. yalnızca bir veri türü döndürür.


Birden fazla veri türü döndüren diller olduğunu bilmiyordum! Polimorfik fonksiyonlardan mı bahsediyorsunuz? Bir işlevi aşırı yüklediğimde, her zaman aynı veri tipini döndürdüğüne inanıyorum, ancak farklı argümanlar alabilir.
Michael K

1
Gevşek yazılan dillerde ve özellikle PHP'de, işlevler birden fazla veri türü döndürebilir. örneğin: stristr- "Eşleşen alt dizeyi döndürür. İğne bulunmazsa FALSE değerini döndürür"
Craige

@Michael, Bir PHP işlevi istediğiniz her şeyi döndürebilir. Veri tipinde herhangi bir kısıtlama yoktur. En karmaşık işlevim true / false / null döndürür, ancak true / integer / null / string / float / array döndüren bir işlev yazmanızı engelleyen (sağduyu hariç) hiçbir şey yoktur.
TRiG

İlginç. PHP ile hiç çalışmadım. Yine de açıklama için teşekkürler - muhtemelen gelecekte bana yardım! Javascript gibi mi?
Michael K

@Michael - Gerçekten Javascript'e oldukça benzer.
Craige

1

Her şeyden önce. LOL! Başka hiçbir şeyden kaçınmak için NEDEN YOKTUR. Herhangi bir şekilde, şekilde veya biçimde kötü uygulama DEĞİLDİR.

Bir şey varsa kod

if(!IsLoggedIn) { ShowBadLoginOrNoAccessPage(); return }

Orada iki ifs yok ve başka yok. Bu benim bir istisna atmak dışında biri benim tüm uygulamaları yapmak. İstisna, uygun sayfanın gösterilmesi için URL'yi kontrol eden işlevimde yakalanır (veya alternatif olarak catch / check'yi asp.net hata işlevine koyabilirim). Yetkilendirmeyen genel bir sayfa yazdırır veya istisnada kullandığım herhangi bir iletiyi yazdırır (her zaman istisna türünü kontrol eder ve http durum kodunu ayarlarım).

-Edit- ammoQ örnek 2'de gösterildiği gibi eğer gülünçse. Gerçekten başka bir if kadar iyi veya daha iyi. Eğer bir şey ifs kaçınılması gereken (ben şahsen dont rağmen. Ama i dönüş ve çok kırmak kullanın) onun söylendiği gibi daha fazla kod yolları hata olasılığını artırmak. Bakınız Siklomatik Karmaşıklık

-Düzenle 2- if / else kullanımı konusunda endişeleriniz varsa. Ayrıca tercihimin en kısa kod bloğunu en üste koymak olduğunu da belirteceğim.

if(cond == false) {
    a()
    b()
    c()
    onetwothree()
}
else
{
    a()
    b()
    c()
    more()
    onetwothree()
    code()
    longer()
}

Aksine o zaman

if(cond) 
{
    a()
    b()
    c()
    more()
    onetwothree()
    code()
    longer()
}
else
{
    a()
    b()
    c()
    onetwothree()
}

0

Yapabildiğim zaman koşullardan önce bir varsayılan ayarlamayı seviyorum. Okumak biraz daha kolay ve biraz daha açık gibi hissediyorum, ama bu sadece bir tercih. Ben denemek ve benim kod negatif koşulları önlemek için bir eğilim var. Ben! Foo veya false == foo için büyük bir hayran değilim ve başka tür bir negatif koşullu eşdeğer olduğunu hissediyorum.

foo = bar;

if ('fubar' == baz) {
    foo = baz;
}

onun yerine ...

if ('fubar' == baz) {
    foo = baz;
} else {
    foo = bar;
}

Önceki kod bloğunu okumak benim için biraz daha kolay görünüyor. Kodum hakkında bir tür şüpheci paranoya sahip olmak benim için daha doğal görünüyor. Herhangi bir koşuldan bağımsız olarak varsayılan bir ayar yapmak beni rahat hissettiriyor: P


0

Her türlü dallanma mantığından mümkün olduğunca kaçınılması gerektiğini savunuyorum. ELSE veya IF ile ilgili hiçbir şey yanlış olmasa da, herhangi bir dallanma mantığı kullanma ihtiyacını en aza indirmek için kod yazmanın birçok yolu vardır. Dallanma mantığının tamamen ortadan kaldırılabileceğini söylemiyorum - bazı yerlerde gerekli olacak - ama iyi bir yığınını ortadan kaldırmak için kodu yeniden düzenlemek mümkün. Çoğu durumda bu, kodunuzun anlaşılırlığını ve doğruluğunu artıracaktır.

Örnek olarak, üçlü operatörler de genellikle iyi adaylardır:

If VIP Then 
  Discount = .25
Else
  Discount = 0
End If
Total = (1 - Discount) * Total

Üçlü bir yaklaşım kullanarak:

Discount = VIP ? .25 : 0
Total = (1 - Discount) * Total

Üçlü operatörler dallanmayı sağa doğru iyi bir şekilde kaydırır.

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.