Birden çok koşul içeren if ifadesini biçimlendirmenin en iyi yolu


90

İki veya daha fazla koşula göre çalıştırılacak bir kod istiyorsanız, if ifadesini biçimlendirmenin en iyi yolu hangisidir?

ilk örnek: -

if(ConditionOne && ConditionTwo && ConditionThree)
{
   Code to execute
}

İkinci örnek: -

if(ConditionOne)
{
   if(ConditionTwo )
   {
     if(ConditionThree)
     {
       Code to execute
     }
   }
}

Bu, her koşulun uzun bir işlev adı veya başka bir şey olabileceğini akılda tutarak anlaşılması ve okunması en kolay yoldur.


Bu sayfadaki hiç kimsenin "hızlı" veya "performans" alt dizesinden bahsetmemesi üzücü. Ben de bunu öğrenmek için geldim.
Dreamspace President

Yanıtlar:


133

A seçeneğini tercih ederim

bool a, b, c;

if( a && b && c )
{
   //This is neat & readable
}

Özellikle uzun değişkenleriniz / yöntem koşullarınız varsa, bunları satırlara ayırabilirsiniz.

if( VeryLongConditionMethod(a) &&
    VeryLongConditionMethod(b) &&
    VeryLongConditionMethod(c))
{
   //This is still readable
}

Daha da karmaşıklarsa, koşul yöntemlerini if ​​ifadesinin dışında ayrı ayrı yapmayı düşünürdüm.

bool aa = FirstVeryLongConditionMethod(a) && SecondVeryLongConditionMethod(a);
bool bb = FirstVeryLongConditionMethod(b) && SecondVeryLongConditionMethod(b);
bool cc = FirstVeryLongConditionMethod(c) && SecondVeryLongConditionMethod(c);

if( aa && bb && cc)
{
   //This is again neat & readable
   //although you probably need to sanity check your method names ;)
}

IMHO 'B' seçeneğinin tek nedeni else, her koşul için ayrı işlevlerin çalıştırılması olabilir.

Örneğin

if( a )
{
    if( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}

Bunu sevdim. Yöntem fikrinin büyük bir hayranı olmasam da, yöntemler zaten mevcut değilse ve bir boole değeri döndürmedikçe.
Thomas Owens

2
İkinci örnekte her şeyi sebepsiz değerlendirmiyor musunuz?
Odys

Koşuldan önce '&&' kullanırdım. Örnekteki ile aynı karakter uzunluğuna sahip koşullara sahip olmak zordur.
AdrianN

29

Diğer cevaplar, ilk seçeneğin normalde neden en iyi olduğunu açıklar. Ancak birden fazla koşulunuz varsa, seçenek 1'deki koşul denetimlerini yaparak ayrı bir işlev (veya özellik) oluşturmayı düşünün. Bu, en azından iyi yöntem adları kullandığınızda kodun daha kolay okunmasını sağlar.

if(MyChecksAreOk()) { Code to execute }

...

private bool MyChecksAreOk()
{ 
    return ConditionOne && ConditionTwo && ConditionThree;
}

Koşullar yalnızca yerel kapsam değişkenlerine dayanır, yeni işlevi statik hale getirebilir ve ihtiyacınız olan her şeyi iletebilirsiniz. Bir karışım varsa, yerel şeyleri de aktarın.


2
Bunu daha sonra koşul eklemek için en etkili ve daha kolay
buldum

+1 ilk başta bir kaşımı kaldırdım ama bu gerçekten en iyi cevap imho. isOkToDoWhateverbir özellik olarak bu boole değerine sahip olmak çok mantıklı.
grinch

1
Ancak bu aynı karmaşık durumu, okunabilir olması gereken başka bir yere taşır, bu yüzden bununla başa döndük. Bu sadece ififade okunabilirliği ile ilgili değil, daha çok koşul okunabilirliği ile ilgili.
Robert Koritnik

@RobertKoritnik Ne dediğini anlıyorum, ancak tekrar başa döndüğümüzü sanmıyorum çünkü okuyucunun tek seferde düşünmesi gereken karmaşıklığı azalttık. Koşullara bakabilir VEYA koşulların (umarım) güzel bir isme sahip olduğu koşulları kullanarak koda bakabilir. En azından sık sık bunu daha kolay buluyorum, ama bazen tüm ayrıntıların tek bir yerde olması güzel. Her zaman olduğu gibi duruma göre değişir.
Torbjørn

İyi yöntem adlarının kullanılması ve mantığın yeniden düzenlenmesi harika bir nokta.
JB Lovell

10

İlk örnek daha "okunması kolay" dır.

Aslında, bana göre ikincisini sadece biraz "başka mantık" eklemeniz gerektiğinde kullanmalısınız, ancak basit bir Koşul için, ilk çeşidi kullanın. Koşulun uzunluğu konusunda endişeliyseniz, her zaman sonraki sözdizimini kullanabilirsiniz:

if(ConditionOneThatIsTooLongAndProbablyWillUseAlmostOneLine
                 && ConditionTwoThatIsLongAsWell
                 && ConditionThreeThatAlsoIsLong) { 
     //Code to execute 
}

İyi şanslar!


10
if (   ( single conditional expression A )
    && ( single conditional expression B )
    && ( single conditional expression C )
   )
{
   opAllABC();
}
else
{
   opNoneABC();
}

Bir if-else ifadesinde birden çok koşullu ifadeyi şu şekilde biçimlendirme:

  1. gelişmiş okunabilirliğe izin verir:
    a. ilk gösterilen ifadedeki tüm ikili mantıksal işlemler {&&, ||}
    b. her ikili işlemin her iki koşullu işlenen de açıktır çünkü bunlar dikey olarak hizalanırlar
    . iç içe geçmiş mantıksal ifadeler işlemleri, tıpkı cümle içindeki ifadeler gibi iç içe yerleştirme gibi girinti kullanılarak açık hale getirilir
  2. açık parantez gerektirir (operatör öncelik kurallarına bağlı değildir)
    a. bu, yaygın bir statik analiz hatalarını önler
  3. daha kolay hata ayıklamaya olanak tanır
    a. tek tek koşullu testleri yalnızca a //
    b ile devre dışı bırakın. herhangi bir test
    ceg'inden hemen önce veya sonra bir kırılma noktası belirleyin ...
// disable any single conditional test with just a pre-pended '//'
// set a break point before any individual test
// syntax '(1 &&' and '(0 ||' usually never creates any real code
if (   1
    && ( single conditional expression A )
    && ( single conditional expression B )
    && (   0
        || ( single conditional expression C )
        || ( single conditional expression D )
       )
   )
{
   ... ;
}

else
{
   ... ;
}

Bu benim yöntemim. Sahip olduğum tek sorun, bunu bir seçenek olarak sunan bir kod güzelleştirici bulamadım
Speed8ump

9

Soru soruldu ve şimdiye kadar, kararın tamamen "sözdizimsel" gerekçelerle verilmesi gerektiği gibi yanıtlandı.

Bir if içinde bir dizi koşulu nasıl düzenlediğinize dair doğru cevabın da "anlambilim" e bağlı olması gerektiğini söyleyebilirim . Bu yüzden koşullar, işlerin "kavramsal olarak" birlikte yürüdüğüne göre parçalanmalı ve gruplandırılmalıdır.

İki test gerçekten aynı madalyonun iki yüzü ise, örneğin. eğer (x> 0) && (x <= 100) o zaman onları aynı satırda bir araya getirin. Başka bir koşul kavramsal olarak çok daha uzaksa, örneğin. user.hasPermission (Admin ()) sonra kendi satırına koyun

Örneğin.

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}

4

İkincisi, Ok Anti-deseninin klasik bir örneğidir. yüzden ondan kaçınırdım ...

Koşullarınız çok uzunsa, bunları yöntemlere / özelliklere çıkarın.


3

İlki daha kolaydır, çünkü eğer onu soldan sağa okursanız şunu elde edersiniz: "Eğer bir şey VE başka bir şey VE DAHA SONRA", anlaşılması kolay bir cümle. İkinci örnek, sakar olan "Eğer bir şey olursa SONRA başka bir şeyse SONRA başka bir şey olursa" yazmaktadır.

Ayrıca, yan tümcenizde bazı OR'leri kullanmak isteyip istemediğinizi düşünün - bunu ikinci stilde nasıl yapardınız?


0

Perl'de bunu yapabilirsiniz:

{
  ( VeryLongCondition_1 ) or last;
  ( VeryLongCondition_2 ) or last;
  ( VeryLongCondition_3 ) or last;
  ( VeryLongCondition_4 ) or last;
  ( VeryLongCondition_5 ) or last;
  ( VeryLongCondition_6 ) or last;

  # Guarded code goes here
}

Koşullardan herhangi biri başarısız olursa, bloktan sonra devam edecektir. Bloktan sonra tutmak istediğiniz herhangi bir değişkeni tanımlıyorsanız, bunları bloktan önce tanımlamanız gerekecektir.


1
Bu Perlish'e benziyor - "NE YAPAR?" anlamda;) Ama alıştığınızda aslında okunabilir.
Piskvor

-2

Uzun zamandır bu ikilemle karşı karşıyayım ve hala uygun bir çözüm bulamıyorum. Bana göre tek iyi yol, önce koşullardan kurtulmaya çalışmaktır, böylece birdenbire 5 tanesini karşılaştırmazsınız.

Eğer başka bir alternatif yoksa, o zaman başkalarının önerdiği gibi - onu ayrı ayrı parçalara ayırın ve isimleri kısaltın veya gruplandırın ve örneğin, eğer hepsi doğru ise, o zaman "x dizisinde yanlış yoksa o zaman çalıştırın" gibi bir şey kullanın.

Her şey başarısız olursa @Eoin Campbell oldukça iyi fikirler verdi.


Bu, zaten var olan cevaplara yeni bir şey eklemiyor.
jerney

-4

Koşul gerçekten karmaşık olduğunda aşağıdaki stili kullanırım (PHP gerçek hayat örneği):

if( $format_bool &&
    (
        ( isset( $column_info['native_type'] )
            && stripos( $column_info['native_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['driver:decl_type'] )
            && stripos( $column_info['driver:decl_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['pdo_type'] )
            && $column_info['pdo_type'] == PDO::PARAM_BOOL
        )
    )
)

Bence birden fazla seviyeyi iç içe geçirmekten daha güzel ve okunabilir if(). Ve bunun gibi bazı durumlarda karmaşık durumu parçalara ayıramazsınız çünkü aksi takdirde aynı ifadeleri burada tekrarlamanız gerekirdi.if() {...} birçok kez blok .

Ayrıca koda biraz "hava" eklemenin her zaman iyi bir fikir olduğuna inanıyorum. Okunabilirliği büyük ölçüde geliştirir.

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.