Haruskah jika pernyataan diatur oleh kelangkaan kasus atau sulitnya menanganinya?

18

Dalam beberapa kode yang saya tulis sekarang, saya memiliki sesuatu seperti ini:

if (uncommon_condition) {
    do_something_simple();
} else {
    do();
    something();
    long();
    and();
    complicated();
}

Sebagian dari saya berpikir, "Tidak masalah dengan cara penulisannya. Kasing sederhana harus didahulukan dan kasing rumit selanjutnya." Tetapi bagian lain mengatakan: "Tidak! elseKode harus berada di bawah if, karena ifuntuk menangani kasus yang tidak biasa dan elseuntuk menangani semua kasus lainnya." Mana yang benar atau lebih disukai?

LAMBANG
sumber
4
Pesan berdasarkan kesederhanaan / pemahaman kondisi! Sisanya dapat diurus oleh optimisers, prediktor cabang, dan refactoring.
Marjan Venema
Inilah mengapa kita dibayar mahal: untuk membuat keputusan sulit ini.

Jawaban:

24

Diurutkan berdasarkan kemungkinan mereka dieksekusi. Kondisi yang paling umum, kemungkinan besar, dll. Harus didahulukan.

"Kesulitan berurusan dengan mereka" harus ditangani dengan struktur kode, abstraksi, dll. Dalam contoh blok lain dapat di refactored menjadi pemanggilan metode tunggal. Anda ingin ifklausa Anda berada pada tingkat abstrak yang sama.

if ( ! LotteryWinner ) {
    GoToWorkMonday();
} else {
    PlanYearLongVacation();
}
radarbob
sumber
6
Untuk kinerja saya mungkin setuju. Tetapi sekali lagi, sebagian besar optimisers dan prediktor cabang benar-benar mampu mengatasinya. Untuk keterbacaan saya mungkin setuju jika kasus yang paling mungkin memiliki garis lebih banyak daripada kasus yang kemungkinan lebih kecil. Tetapi bagi saya itu akan lebih cepat menunjukkan perlunya mengekstrak suatu metode daripada menggunakan a not. Secara pribadi saya akan berkonsentrasi pada menghindari notkondisi. Mereka telah terbukti menginduksi lebih banyak beban kognitif untuk memahami daripada kondisi "positif" dan merugikan keterbacaan / pemahaman kode. Saya cenderung menggunakannya dalam pernyataan penjaga saja.
Marjan Venema
2
@ Marsjanen, saya bisa mengerti maksud Anda tentang "tidak". Tetapi dobel negatif adalah WTF "bukan" yang asli. Suatu hari saya menemukan ini dalam kode kami doesNotAllowxxFiles = false. Cukup buruk tetapi kemudian lakukan iniif(! doesNotAllowxxFiles)
radarbob
Ya, dua kali lipat negatif, negatif dikombinasikan dengan dan dan / atau (sic!) Dan negatif dikombinasikan dengan metode / var dengan Tidak dalam nama, buat otak saya berputar setiap kali :-)
Marjan Venema
jika Anda mengalami kesulitan memahami apa yang sedang terjadi, saya pikir sering berguna untuk melakukan hal seperti: simpleBool = (! (complexBool || randomfFlag)) &&! randomFlag
TruthOf42
2
Saya setuju dengan Anda, kecuali keberadaan Klausa Penjaga (yang selalu memiliki kondisi luar biasa di bagian THEN dari pernyataan IF, bukan kondisi umum).
Robert Harvey
5

Cobalah untuk meningkatkan keterbacaan. Salah satu caranya adalah dengan menempatkan blok kode yang lebih panjang ke bagian yang lain.

if (s == null)
     // short code
else 
     // long 
     // code
     // block

lebih mudah dibaca daripada

if (s != null)
    // long
    // code
    // block
else
    // short code
CWallach
sumber
2
mengapa lebih mudah dibaca? Saya melihat tidak ada perbedaan antara keduanya dalam hal keterbacaan
John Demetriou
2
@JohnDemetriou Yang Lain lebih terlihat jika Kemudian pendek. Orang-orang memindai struktur terlebih dahulu, lalu menetapkan artinya. Kode tanpa Else berbeda dari kode dengan Else, sehingga membuat Else lebih terlihat lebih mudah dimengerti. (Semua hal lain dianggap sama, pada hari Selasa ketika tidak hujan, dll)
4

Tidak ada aturan baku seperti itu yang saya dengar tentang penggunaan tetapi saya ikuti seperti ini

if(usual)
{
(more often)
}
else (unusual)
{
(rarely occurring)
}

Tetapi jika keduanya memiliki fungsi yang sama dengan properti yang berbeda maka lebih baik menggunakan yang tidak biasa terlebih dahulu dari biasanya sehingga Anda dapat menyimpan satu instruksi.


if(x == 0)  // 1
  {x = 1;}  // 2
else
  {x = 2;}  // 3

Untuk kode di atas kode assembly akan menjadi seperti ini:

1. 000d 837DFC00        cmpl    $0, -4(%ebp)
   0011 7509            jne .L2

2. 0013 C745FC01        movl    $1, -4(%ebp)
   001a EB07            jmp .L3

    .L2:
3.001c C745FC02         movl    $2, -4(%ebp)

        .L3:

Jika kondisi di dalam jika benar maka aliran adalah 1-> 2 (4 instruksi)
JIKA kondisi di dalam jika salah maka aliran adalah 1-> 3 (3 instruksi)

Jadi lebih baik untuk menempatkan kejadian yang tidak biasa atau jarang terjadi jika bagian dan kondisi normal di tempat lain sehingga kita dapat menyimpan satu instruksi setiap kali ;-)

Santosh Mudhol
sumber
2

Saya telah menemukan bahwa pola sebaliknya yang tepat mengarah pada kode yang lebih mudah dibaca, dan mengurangi atau menghilangkan pernyataan bersarang jika. Saya menyebutnya sebagai pola "tantangan". (Dalam bercerita, tantangan akan menjadi serangkaian tantangan yang harus dipenuhi dengan sukses sebelum tugas akhir selesai.) Dengan menangani casing tepi Anda terlebih dahulu , Anda membiarkan badan utama kode Anda menjadi bersih dan ringkas:

if(gauntlet_1){ handle the first gauntlet condition }; 
if(gauntlet_2){ handle the second gauntlet condition };
...
// All preconditions (gauntlets) have been successfully handled

// Perform your main task here
Byron Jones
sumber
Jadi bagian "handle gauntlet" harus berupa transfer kontrol, seperti pernyataan lemparan atau pengembalian, atau harus benar-benar memperbaiki kesalahan. Beberapa orang tidak menyukai serangkaian pernyataan pengembalian ..., tapi saya tidak melakukannya dan ternyata itu membuat kode lebih mudah dibaca, seperti yang Anda katakan.
1
Jika kondisi tantangan adalah sesuatu yang akan mencegah fungsi dari berhasil, ia mengembalikan kesalahan segera. Jika kondisi tantangan dapat ditangani, saya melakukannya sebelum memasukkan kode utama bila memungkinkan. Saya terutama berusaha untuk menghindari pernyataan IF bersarang, yang dalam pengalaman saya adalah salah satu penyebab utama kesalahan pengkodean yang tidak jelas dan sulit di-debug.
Byron Jones
0

Bagi saya ini lebih tentang kondisi daripada kompleksitas kode yang mereka jalankan. Anda perlu memesan kondisi agar dapat menjebak kondisi yang tidak biasa terlebih dahulu, kemudian yang lebih umum setelah. Juga, jika kode lain sangat panjang dan rumit, saya mungkin akan membuat sub untuk itu, untuk menjaga bagian bersyarat yang jelas bagi pembaca.

Steve Thomas
sumber
-1

Saya tidak memiliki aturan baku, tetapi umumnya saya mengikuti ini - pertama, pertimbangkan di mana ada pola desain yang terlewat yang akan menyebabkan hal ini. Jika tidak, saya menuliskannya sehingga kondisi di if adalah yang paling jelas dipahami. Yaitu, menghindari dobel negatif dan sejenisnya.

Don Branson
sumber