Cara terbaik untuk memformat pernyataan if dengan beberapa kondisi


90

Jika Anda ingin menjalankan beberapa kode berdasarkan dua atau lebih kondisi, manakah cara terbaik untuk memformat pernyataan if itu?

contoh pertama: -

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

Contoh kedua: -

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

yang paling mudah untuk dipahami dan dibaca dengan mengingat bahwa setiap kondisi dapat berupa nama fungsi yang panjang atau semacamnya.


Sayangnya tidak ada orang di halaman ini yang menyebut substring "cepat" atau "performa". Itulah yang saya pelajari di sini.
Presiden Dreamspace

Jawaban:


133

Saya lebih suka Opsi A

bool a, b, c;

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

Jika Anda memiliki variabel / kondisi metode yang sangat panjang, Anda dapat memutus barisnya saja

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

Jika lebih rumit lagi, saya akan mempertimbangkan untuk melakukan metode kondisi secara terpisah di luar pernyataan if

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 Satu-satunya alasan untuk opsi 'B' adalah jika Anda memiliki elsefungsi terpisah untuk dijalankan untuk setiap kondisi.

misalnya

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

Saya suka itu. Meskipun saya bukan penggemar ide metode, kecuali metode tersebut sudah ada dan mengembalikan nilai boolean.
Thomas Owens

2
Bukankah Anda mengevaluasi semuanya tanpa alasan pada contoh kedua?
Odys

Saya akan menggunakan '&&' sebelum kondisi. Sulit untuk memiliki kondisi dengan panjang karakter yang sama seperti pada contoh.
AdrianN

29

Jawaban lain menjelaskan mengapa opsi pertama biasanya yang terbaik. Namun jika Anda memiliki beberapa kondisi, pertimbangkan untuk membuat fungsi (atau properti) terpisah dengan melakukan pemeriksaan kondisi di opsi 1. Ini membuat kode lebih mudah dibaca, setidaknya saat Anda menggunakan nama metode yang baik.

if(MyChecksAreOk()) { Code to execute }

...

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

Jika kondisinya hanya bergantung pada variabel cakupan lokal, Anda dapat membuat fungsi baru menjadi statis dan meneruskan semua yang Anda butuhkan. Jika ada campuran, berikan barang-barang lokal.


2
Saya menemukan ini menjadi yang paling efektif dan lebih mudah untuk menambahkan kondisi nanti
pbojinov

+1 pada awalnya saya mengangkat alis tetapi ini benar-benar jawaban terbaik imho. memiliki boolean itu isOkToDoWhateversebagai properti sangat masuk akal.
grinch

1
Tapi ini hanya memindahkan kondisi kompleks yang sama ke tempat lain di mana ia juga perlu dibaca jadi kita kembali ke titik awal dengan ini. Ini bukan hanya tentang ifketerbacaan pernyataan tetapi lebih kepada keterbacaan kondisi.
Robert Koritnik

@RobertKoritnik Saya mengerti apa yang Anda katakan, tapi saya rasa kita tidak kembali ke titik awal karena kita telah mengurangi kerumitan yang perlu dipertimbangkan pembaca sekaligus. Dia mungkin melihat kondisi, ATAU dia mungkin melihat kode menggunakan kondisi di mana kondisi memiliki nama yang (semoga) bagus. Setidaknya saya sering merasa ini lebih mudah untuk digores, tetapi terkadang menyenangkan memiliki semua detail di satu tempat. Seperti biasa, itu tergantung.
Torbjørn

Poin bagus menggunakan nama metode yang baik dan refactoring logika.
JB Lovell

10

Contoh pertama lebih "mudah dibaca".

Sebenarnya, menurut saya Anda hanya boleh menggunakan yang kedua setiap kali Anda harus menambahkan beberapa "logika lain", tetapi untuk Kondisional sederhana, gunakan rasa pertama. Jika Anda khawatir tentang kondisi yang lama, Anda selalu dapat menggunakan sintaks berikutnya:

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

Semoga berhasil!


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

Memformat beberapa ekspresi bersyarat dalam pernyataan if-else seperti ini:

  1. memungkinkan untuk meningkatkan keterbacaan:
    a. semua operasi logika biner {&&, ||} dalam ekspresi yang ditampilkan pertama
    b. kedua operan bersyarat dari setiap operasi biner jelas karena sejajar secara vertikal
    c. Operasi ekspresi logis bersarang dibuat jelas menggunakan indentasi, seperti pernyataan bersarang di dalam klausa
  2. membutuhkan tanda kurung eksplisit (tidak bergantung pada aturan prioritas operator)
    a. ini untuk menghindari kesalahan analisis statis yang umum
  3. memungkinkan debugging lebih mudah
    a. nonaktifkan tes bersyarat tunggal individu hanya dengan //
    b. menetapkan titik istirahat tepat sebelum atau sesudah
    ...
// 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
{
   ... ;
}

Ini adalah metode saya. Satu-satunya masalah yang saya miliki adalah saya belum menemukan
penghias

9

Pertanyaan yang diajukan dan sejauh ini telah dijawab seolah-olah keputusan harus dibuat murni atas dasar "sintaksis".

Saya akan mengatakan bahwa jawaban yang benar tentang bagaimana Anda mengatur sejumlah kondisi dalam jika, harus bergantung pada "semantik" juga. Jadi kondisi harus dipecah dan dikelompokkan sesuai dengan apa yang berjalan bersama "secara konseptual".

Jika dua tes benar-benar merupakan dua sisi dari mata uang yang sama misalnya. if (x> 0) && (x <= 100) lalu gabungkan keduanya pada baris yang sama. Jika kondisi lain secara konseptual jauh lebih jauh misalnya. user.hasPermission (Admin ()) lalu letakkan di barisnya sendiri

Misalnya.

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

4

Yang kedua adalah contoh klasik dari Pola Anti Panah Jadi saya akan menghindarinya ...

Jika kondisi Anda terlalu lama, ekstrak ke dalam metode / properti.


3

Yang pertama lebih mudah, karena, jika Anda membacanya dari kiri ke kanan Anda mendapatkan: "Jika sesuatu DAN sesuatu yang lain DAN sesuatu yang lain THEN", yang merupakan kalimat yang mudah dipahami. Contoh kedua berbunyi "Jika sesuatu MAKA jika sesuatu lain MAKA jika sesuatu yang lain MAKA", yang janggal.

Juga, pertimbangkan jika Anda ingin menggunakan beberapa OR dalam klausa Anda - bagaimana Anda melakukannya dalam gaya kedua?


0

Di Perl Anda bisa melakukan ini:

{
  ( 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
}

Jika salah satu kondisi gagal, itu akan terus berlanjut, setelah pemblokiran. Jika Anda mendefinisikan variabel apa pun yang ingin Anda pertahankan setelah blok, Anda perlu mendefinisikannya sebelum blok.


1
Itu terlihat Perlish - di bagian "it does WHAT?" sense;) Tapi itu sebenarnya bisa dibaca, setelah Anda terbiasa.
Piskvor meninggalkan gedung

-2

Saya sudah lama menghadapi dilema ini dan saya masih belum bisa menemukan solusi yang tepat. Menurut pendapat saya, satu-satunya cara yang baik adalah dengan mencoba menyingkirkan kondisi sebelumnya terlebih dahulu sehingga Anda tidak tiba-tiba membandingkan 5 di antaranya.

Jika tidak ada alternatif maka seperti yang disarankan orang lain - pecahkan menjadi yang terpisah dan persingkat nama atau kelompokkan mereka dan misalnya jika semua harus benar maka gunakan sesuatu seperti "jika tidak ada salah dalam larik x maka jalankan".

Jika semua gagal @Eoin Campbell memberikan ide yang cukup bagus.


Ini tidak menambahkan sesuatu yang baru ke jawaban yang sudah ada.
jerney

-4

Ketika kondisi sangat kompleks, saya menggunakan gaya berikut (contoh kehidupan nyata PHP):

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
        )
    )
)

Saya percaya ini lebih bagus dan mudah dibaca daripada menyusun beberapa tingkat if(). Dan dalam beberapa kasus seperti ini Anda tidak dapat memecah kondisi kompleks menjadi beberapa bagian karena jika tidak, Anda harus mengulangi pernyataan yang sama di if() {...}blok berkali-kali.

Saya juga percaya bahwa menambahkan sedikit "udara" ke dalam kode selalu merupakan ide yang bagus. Ini sangat meningkatkan keterbacaan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.