Bagaimana menangani flag di banyak if-else

10

Sepertinya saya cukup sering melihatnya dalam kode saya dan yang lainnya. Tidak ada apa-apa tentang hal itu yang kelihatannya sangat salah, tetapi itu mengganggu saya karena sepertinya itu bisa dilakukan dengan lebih baik. Saya kira pernyataan kasus, mungkin sedikit lebih masuk akal, tetapi seringkali variabel adalah tipe yang tidak berfungsi dengan baik atau sama sekali dengan pernyataan kasus (tergantung pada bahasa)

If variable == A
    if (Flag == true)
        doFooA()
    else
        doFooA2

else if variable == B
    if (Flag == true)
        doFooB()
    else
        doFooB2
else if variable == C
    if (Flag == true)
        doFooC()
    else
        doFooC2

Tampaknya ada beberapa cara untuk "faktor" ini, seperti 2 set if-elses, di mana satu set menangani ketika Bendera == true.

Apakah ada "cara yang baik" untuk memfaktorkan hal ini, atau mungkin ketika algoritma if-else ini terjadi biasanya berarti Anda melakukan sesuatu yang salah?

TruthOf42
sumber
6
mungkinkah untuk meneruskan variabel Flag ke doFooX yang dapat menangani flag itu sendiri?
Jean-François Côté
tentu tetapi kemudian Anda hanya memiliki metode doFooX, yang mengevaluasi apakah flag itu benar dan kemudian apakah doFooX1 atau doFooX2
TruthOf42
5
IMHO, masih akan lebih jelas untuk dibaca. Maka itu tergantung apa yang doFooA dan doFooA2 lakukan ...
Jean-François Côté
2
Mengapa menulis, if (Flag == true)bukan hanya If (Flag)? Jika Anda pikir itu If (Flag == true)lebih baik, mengapa tidak if ((Flag == true) == true)?
Keith Thompson
1
Yang paling penting dibawa pulang dari sebagian besar jawaban di bawah ini adalah bahwa kesederhanaan dan keterbacaan jauh lebih penting daripada trik pintar ketika datang ke aliran logis dan mempertahankan kode ke masa depan.
Patrick Hughes

Jawaban:

18

Itu bisa ditangani dengan polimorfisme.

factory(var, flag).doFoo();

Setiap kali Anda memiliki sekelompok if / else memeriksa jenis sesuatu, Anda dapat mempertimbangkan memusatkan if / else memeriksa dalam metode pabrik, kemudian memanggil doFoo () secara polimorfis. Tapi ini bisa menjadi over-kill untuk solusi 1-off.

Mungkin Anda bisa membuat peta kunci / nilai di mana kuncinya adalah var / flag, dan nilainya adalah fungsinya sendiri.

do[var, flag]();
mike30
sumber
2
+1: Pencarian tabel mengalahkan pernyataan if bersarang hampir setiap waktu.
kevin cline
1
Saya ingin mengatakan ini adalah solusi terbaik.
The Muffin Man
6

Jika banyak bersarang meningkatkan kompleksitas siklomatik dari kode. Hingga baru-baru ini, memiliki beberapa titik keluar dalam suatu fungsi dianggap sebagai kode terstruktur yang buruk, tetapi sekarang, selama kode itu sederhana, dan singkat , Anda dapat melakukannya, membuat kode itu sepele untuk dibaca:

    if (variable == A && Flag) {
        doFooA();
        return;
    }

    if (variable == A) {
        doFooA2();
        return;
    }

    if (variable == B && Flag){
        doFooB();
        return;
    }

    if (variable == B){
        doFooB2();
        return;
    }

    if (variable == C && Flag){
         doFooC();
         return;
    }

    if (variable == C){
         doFooC2();
    }

    return;
Tulains Córdova
sumber
3

Pilihan lain adalah menggabungkan if dan switch. Ini tidak lebih unggul dari teknik bersarang jika Anda, tetapi dapat mengurangi jumlah tes duplikat (jika saklar dioptimalkan ke tabel lompatan).


if (flag)
{
    switch (variable)
    {
        case A:
           ... blah
           break;

        case B:
           ... blah
           break;

        case C:
           ... blah
           break;

        default:
           ... log an error.
           ... maybe do a default action.
           break;
    }
}
else // flag == false
{
    switch (variable)
    {
        case A:
           ... blah
           break;

        case B:
           ... blah
           break;

        case C:
           ... blah
           break;

        default:
           ... log an error.
           ... maybe do a default action.
           break;
}
DwB
sumber
0

Yah, selalu ada ini ...

if variable == A && Flag
    doFooA()
else if variable == A 
    doFooA2    
else if variable == B && Flag
    doFooB()
else if variable == B
    doFooB2
else if variable == C && Flag
     doFooC()
else if variable == C
     doFooC2

Tapi sejujurnya, saya pikir kode asli tidak setengah buruk di tempat pertama.

Ross Patterson
sumber
0

Gunakan polimorfisme dan rulearray

interface IRule() {
  boolean applicable(args...);
  obj apply(args...);
}

static final Array<IRule> rules = [new MeaningfulNameRule1(), new MeaningfulNameRule2(), ...];

/* where */
class MeaningfulNameRuleX extends IRule{ /* */ }

/* In your method */

for (rule in rules) {
  if (rule.applicable(a,b,c)){
    return rule.apply(e,f,g);
  }
}

Atau seperti yang mike30disarankan: Jika kondisi aturan dapat dengan mudah membentuk kunci maka hashmap adalah cara terbaik untuk pergi.

Matya
sumber