Cara untuk menghilangkan kode sakelar [ditutup]

175

Apa cara untuk menghilangkan penggunaan kode saklar?

Mariano
sumber
18
Mengapa Anda ingin menghilangkan sakelar, bila digunakan dengan tepat? Tolong bisakah Anda menguraikan pertanyaan Anda.
RB.
Saya memilih pertanyaan ini menjadikan komunitas dapat diedit karena semua orang mengatakan hal yang sama dan mungkin menyenangkan untuk menggabungkan semua pendapat;)
Josh
2
Saklar tidak standar seperti instruksi lainnya. Misalnya, dalam C ++, Anda cenderung melupakan 'break' dan kemudian Anda akan mendapatkan hasil yang tidak terduga. Selain itu, 'break' ini terlalu mirip dengan GOTO. Saya belum pernah mencoba menghilangkan sakelar, tetapi yang pasti itu bukan instruksi favorit saya. ;)
2
Saya pikir dia mengacu pada konsep switch dan bukan pernyataan C ++ atau Java switch. Switch juga bisa berupa rantai blok 'jika-lain jika'.
Outlaw Programmer
2
Anda mungkin merasa terhibur: ada sejumlah besar programmer terkenal dari komunitas lincah yang bergabung dengan kampanye anti-IF: antiifcampaign.com/supporters.html
Mike A

Jawaban:

267

Switch-statement bukan merupakan antipattern per se, tetapi jika Anda mengkode objek berorientasi Anda harus mempertimbangkan jika penggunaan switch lebih baik diselesaikan dengan polimorfisme daripada menggunakan pernyataan switch.

Dengan polimorfisme, ini:

foreach (var animal in zoo) {
    switch (typeof(animal)) {
        case "dog":
            echo animal.bark();
            break;

        case "cat":
            echo animal.meow();
            break;
    }
}

menjadi ini:

foreach (var animal in zoo) {
    echo animal.speak();
}
mlarsen
sumber
2
Saya dihancurkan karena saran yang sama di stackoverflow.com/questions/374239/... Begitu banyak ppl yang tidak percaya pada polimorfisme :) Contoh yang sangat bagus.
Nazgob
30
-1: Saya tidak pernah menggunakan pernyataan switch dengan typeof, dan jawaban ini tidak menyarankan cara atau alasan untuk bekerja di sekitar pernyataan switch dalam situasi lain.
Kevin
3
Saya setuju dengan @Kevin - contoh yang diberikan tidak benar-benar menunjukkan cara menghilangkan beralih oleh polimorfisme. Contoh sederhana: dapatkan nama enum dengan mengganti nilainya, atau lakukan beberapa kode dengan nilai yang sesuai dalam beberapa jenis algoritma.
HotJard
Saya bertanya-tanya bagaimana cara menghilangkannya sebelum Anda dapat mengandalkan implementasi khusus con, yaitu di pabrik. Dan saya menemukan contoh yang bagus di sini stackoverflow.com/a/3434505/711855
juanmf
1
contoh yang sangat sepele.
GuardianX
239

Lihat Beralih Pernyataan Bau :

Biasanya, pernyataan switch yang serupa tersebar di seluruh program. Jika Anda menambah atau menghapus klausa dalam satu saklar, Anda sering harus menemukan dan memperbaiki yang lain juga.

Baik Refactoring dan Refactoring to Patterns memiliki pendekatan untuk menyelesaikannya.

Jika kode (semu) Anda terlihat seperti:

class RequestHandler {

    public void handleRequest(int action) {
        switch(action) {
            case LOGIN:
                doLogin();
                break;
            case LOGOUT:
                doLogout();
                break;
            case QUERY:
               doQuery();
               break;
        }
    }
}

Kode ini melanggar Prinsip Terbuka Terbuka dan rentan terhadap setiap jenis kode tindakan baru yang muncul. Untuk memperbaiki ini, Anda bisa memperkenalkan objek 'Perintah':

interface Command {
    public void execute();
}

class LoginCommand implements Command {
    public void execute() {
        // do what doLogin() used to do
    }
}

class RequestHandler {
    private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
    public void handleRequest(int action) {
        Command command = commandMap.get(action);
        command.execute();
    }
}

Jika kode (semu) Anda terlihat seperti:

class House {
    private int state;

    public void enter() {
        switch (state) {
            case INSIDE:
                throw new Exception("Cannot enter. Already inside");
            case OUTSIDE:
                 state = INSIDE;
                 ...
                 break;
         }
    }
    public void exit() {
        switch (state) {
            case INSIDE:
                state = OUTSIDE;
                ...
                break;
            case OUTSIDE:
                throw new Exception("Cannot leave. Already outside");
        }
    }

Maka Anda bisa memperkenalkan objek 'Negara'.

// Throw exceptions unless the behavior is overriden by subclasses
abstract class HouseState {
    public HouseState enter() {
        throw new Exception("Cannot enter");
    }
    public HouseState leave() {
        throw new Exception("Cannot leave");
    }
}

class Inside extends HouseState {
    public HouseState leave() {
        return new Outside();
    }
}

class Outside extends HouseState {
    public HouseState enter() {
        return new Inside();
    }
}

class House {
    private HouseState state;
    public void enter() {
        this.state = this.state.enter();
    }
    public void leave() {
        this.state = this.state.leave();
    }
}

Semoga ini membantu.

toolkit
sumber
7
Terima kasih atas contoh yang bagus tentang cara memperbaiki kode. Meskipun saya dapat mengatakan di awal itu agak sulit dibaca (karena kita harus beralih di antara beberapa file untuk benar-benar memahaminya)
rshimoda
8
Argumen terhadap switch valid selama Anda menyadari bahwa solusi polimorfik mengorbankan kesederhanaan kode. Selain itu, jika Anda selalu menyimpan kotak saklar di enum, beberapa kompiler akan memperingatkan Anda bahwa status hilang dari sakelar.
Harvey
1
Ini adalah contoh yang bagus tentang operasi lengkap / tidak lengkap dan tentu saja menyusun ulang kode menjadi OOP. Terima kasih banyak. Saya pikir ini akan berguna jika pendukung OOP / Pola Desain menyarankan untuk memperlakukan konsep OOP seperti operator daripada konsep . Maksud saya "extends", "factory", "implements", dll sering digunakan di file, kelas, cabang. Mereka harus sederhana seperti operator seperti "+", "-", "+ =", "?:", "==", "->" dll. Ketika seorang programmer menggunakannya dalam pikirannya hanya sebagai operator, hanya kemudian dia dapat berpikir di perpustakaan kelas penuh tentang keadaan program dan (dalam) operasi lengkap.
namespaceform
13
Saya mulai berpikir bahwa SWITCH jauh lebih mudah dimengerti dan logis, dibandingkan dengan ini. Dan saya biasanya sangat menyukai OOP, tetapi resolusi ini tampaknya terlalu abstrak untuk saya
JK
1
Dengan objek Command, apakah kode yang akan dihasilkan Map<Integer, Command>tidak perlu switch?
ataulm
41

Switch adalah pola, apakah diimplementasikan dengan pernyataan switch, jika rantai lain, tabel pencarian, oop polimorfisme, pencocokan pola atau sesuatu yang lain.

Apakah Anda ingin menghilangkan penggunaan " beralih pernyataan " atau " beralih pola "? Yang pertama dapat dihilangkan, yang kedua, hanya jika pola / algoritma lain dapat digunakan, dan sebagian besar waktu itu tidak mungkin atau itu bukan pendekatan yang lebih baik untuk melakukannya.

Jika Anda ingin menghilangkan pernyataan switch dari kode, pertanyaan pertama yang harus ditanyakan adalah di mana masuk akal untuk menghilangkan pernyataan switch dan menggunakan beberapa teknik lainnya. Sayangnya jawaban untuk pertanyaan ini adalah spesifik domain.

Dan ingat bahwa kompiler dapat melakukan berbagai optimasi untuk mengganti pernyataan. Jadi misalnya jika Anda ingin melakukan pemrosesan pesan secara efisien, pernyataan beralih cukup banyak cara untuk pergi. Tetapi di sisi lain menjalankan aturan bisnis berdasarkan pernyataan switch mungkin bukan cara terbaik untuk pergi dan aplikasi harus di-ulang.

Berikut adalah beberapa alternatif untuk beralih pernyataan:

Pop Catalin
sumber
1
Bisakah seseorang memberikan perbandingan pemrosesan pesan menggunakan sakelar versus alternatif lain?
Mike A
37

Beralih itu sendiri tidak terlalu buruk, tetapi jika Anda memiliki banyak "switch" atau "if / else" pada objek dalam metode Anda, itu mungkin merupakan tanda bahwa desain Anda sedikit "prosedural" dan bahwa objek Anda hanya bernilai ember. Pindahkan logika ke objek Anda, aktifkan metode pada objek Anda dan biarkan mereka memutuskan bagaimana meresponsnya.

Lars Westergren
sumber
Dengan asumsi tentu saja, bahwa dia tidak menulis dalam bahasa C. :)
Bernard
1
di C, ia dapat (ab?) menggunakan pointer fungsi dan struct untuk membangun sesuatu seperti objek;)
Tetha
Anda dapat menulis FORT ^ H ^ H ^ H ^ H Java dalam bahasa apa pun. ; p
Bernard
Sepenuhnya setuju - beralih adalah cara yang bagus untuk mengurangi baris kode, tetapi jangan bermain dengannya juga mach.
HotJard
21

Saya pikir cara terbaik adalah menggunakan Peta yang bagus. Menggunakan kamus Anda dapat memetakan hampir semua input ke beberapa nilai / objek / fungsi lainnya.

kode Anda akan terlihat seperti (psuedo) seperti ini:

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}
Josh
sumber
4
Tergantung pada bahasanya. Ini bisa menjadi jauh lebih mudah dibaca daripada sebuah saklar
Vinko Vrsalovic
Ini adalah solusi elegan yang bagus dalam situasi yang tepat. Saya melakukan pemetaan kode kunci baru-baru ini, dan sepertinya membaca oke untuk tujuan itu.
Bernard
Ini benar, saya mungkin tidak akan menggunakan ini untuk hal yang sederhana, tetapi memberikan sejumlah fleksibilitas dalam hal konfigurasi melalui pernyataan switch. Kamus dapat disiapkan dengan cepat sementara sakelar akan selalu dikodekan dengan keras.
Josh
Dapat lebih bersih dalam beberapa keadaan. Juga lebih lambat, karena membutuhkan panggilan fungsi.
Nick Johnson
1
Itu tergantung pada kunci Anda. Kompiler dapat mengkompilasi pernyataan switch menjadi pencarian sederhana atau pencarian biner statis yang sangat cepat, dalam kedua kasus tanpa memerlukan pemanggilan fungsi.
Nick Johnson
12

Semua orang suka if elseblok BESAR . Sangat mudah dibaca! Saya ingin tahu mengapa Anda ingin menghapus pernyataan switch. Jika Anda memerlukan pernyataan switch, Anda mungkin perlu pernyataan switch. Serius, saya akan mengatakan itu tergantung pada apa kode lakukan. Jika semua switch lakukan adalah memanggil fungsi (katakanlah) Anda bisa melewati pointer fungsi. Apakah itu solusi yang lebih baik masih bisa diperdebatkan.

Bahasa juga merupakan faktor penting di sini.

Bernard
sumber
13
Saya berasumsi itu sarkasme :)
Craig Day
6

Saya pikir apa yang Anda cari adalah Pola Strategi.

Ini dapat diimplementasikan dalam beberapa cara, yang telah disebutkan dalam jawaban lain untuk pertanyaan ini, seperti:

  • Peta nilai -> fungsi
  • Polimorfisme. (sub-jenis objek akan memutuskan bagaimana ia menangani proses tertentu).
  • Fungsi kelas satu.
AJ.
sumber
5

switch pernyataan akan baik untuk diganti jika Anda menemukan diri Anda menambahkan negara baru atau perilaku baru ke pernyataan:

keadaan int;

String getString () {
   beralih (status) {
     kasus 0: // perilaku untuk status 0
           kembalikan "nol";
     kasus 1: // perilaku untuk negara 1
           kembalikan "satu";
   }
   melempar IllegalStateException baru ();
}

gandakan getDouble () {

   switch (this.state) {
     kasus 0: // perilaku untuk status 0
           return 0d;
     kasus 1: // perilaku untuk negara 1
           kembalikan 1d;
   }
   melempar IllegalStateException baru ();
}

Menambahkan perilaku baru memerlukan menyalin switch, dan menambahkan status baru berarti menambahkan yang lain caseuntuk setiap switch pernyataan.

Di Jawa, Anda hanya bisa mengganti sejumlah tipe primitif yang sangat terbatas yang nilainya Anda ketahui saat runtime. Ini menghadirkan masalah dalam dan dari dirinya sendiri: negara diwakili sebagai angka ajaib atau karakter.

Pencocokan pola , dan banyak if - elseblok dapat digunakan, meskipun benar-benar memiliki masalah yang sama ketika menambahkan perilaku baru dan status baru.

Solusi yang orang lain sarankan sebagai "polimorfisme" adalah contoh dari pola Negara :

Ganti masing-masing negara bagian dengan kelasnya sendiri. Setiap perilaku memiliki metode sendiri di kelas:

Kondisi miring;

String getString () {
   return state.getString ();
}

gandakan getDouble () {
   return state.getDouble ();
}

Setiap kali Anda menambahkan status baru, Anda harus menambahkan implementasi IStateantarmuka baru. Di switchdunia, Anda akan menambahkan casemasing-masing switch.

Setiap kali Anda menambahkan perilaku baru, Anda perlu menambahkan metode baru ke IStateantarmuka, dan masing-masing implementasinya. Ini adalah beban yang sama seperti sebelumnya, meskipun sekarang kompiler akan memeriksa apakah Anda memiliki implementasi perilaku baru pada setiap negara yang sudah ada sebelumnya.

Yang lain sudah mengatakan, bahwa ini mungkin terlalu berat, jadi tentu saja ada titik Anda mencapai di mana Anda berpindah dari satu ke yang lain. Secara pribadi, kedua kalinya saya menulis saklar adalah titik di mana saya refactor.

jamesh
sumber
4

jika ada

Saya menyangkal premis bahwa saklar pada dasarnya buruk.

Iain Holder
sumber
3

Yah, untuk satu hal, saya tidak tahu menggunakan sakelar adalah pola anti.

Kedua, switch selalu bisa diganti dengan pernyataan if / else.

SCdF
sumber
tepatnya - switch hanyalah metadon sintaksis untuk sekelompok if / elsifs.
Mike A
3

Mengapa kamu mau? Di tangan kompiler yang baik, pernyataan switch bisa jauh lebih efisien daripada jika blok lain (dan juga lebih mudah dibaca), dan hanya switch terbesar yang mungkin dipercepat jika diganti oleh apa pun struktur data pencarian-tidak langsung.

Nick Johnson
sumber
2
Pada titik Anda menebak-nebak kompiler, dan membuat perubahan pada desain Anda berdasarkan internal kompiler. Desain harus mengikuti sifat masalah, bukan sifat dari kompiler.
Mike A
3

'switch' hanyalah konstruksi bahasa dan semua konstruksi bahasa dapat dianggap sebagai alat untuk menyelesaikan pekerjaan. Seperti alat nyata, beberapa alat lebih cocok untuk satu tugas daripada yang lain (Anda tidak akan menggunakan palu godam untuk memasang kait gambar). Bagian penting adalah bagaimana 'menyelesaikan pekerjaan' didefinisikan. Apakah itu perlu dipertahankan, apakah perlu cepat, apakah perlu skala, apakah perlu diperpanjang dan seterusnya.

Pada setiap titik dalam proses pemrograman biasanya ada berbagai konstruksi dan pola yang dapat digunakan: switch, urutan if-else-if, fungsi virtual, tabel lompatan, peta dengan pointer fungsi dan sebagainya. Dengan pengalaman, seorang programmer akan secara naluriah mengetahui alat yang tepat untuk digunakan untuk situasi tertentu.

Harus diasumsikan bahwa siapa pun yang memelihara atau meninjau kode setidaknya sama terampilnya dengan penulis asli sehingga setiap konstruk dapat digunakan dengan aman.

Mendesis
sumber
OK, tapi mengapa kita perlu 5 cara berbeda dan berlebihan untuk melakukan hal yang sama - eksekusi bersyarat?
Mike A
@ mike.amy: Karena setiap metode memiliki manfaat dan biaya yang berbeda dan ini semua tentang mendapatkan manfaat paling banyak dengan biaya paling sedikit.
Skizz
1

Jika saklar ada untuk membedakan berbagai jenis objek, Anda mungkin kehilangan beberapa kelas untuk menggambarkan objek-objek itu dengan tepat, atau beberapa metode virtual ...

Xavier Nodet
sumber
1

Untuk C ++

Jika Anda merujuk ke yaitu AbstractFactory, saya pikir metode registerCreatorFunc (..) biasanya lebih baik daripada harus menambahkan case untuk setiap pernyataan "baru" yang diperlukan. Kemudian membiarkan semua kelas membuat dan mendaftarkan creatorFunction (..) yang dapat dengan mudah diimplementasikan dengan makro (jika saya berani menyebutkan). Saya percaya ini adalah pendekatan umum yang dilakukan banyak kerangka kerja. Saya pertama kali melihatnya di ET ++ dan saya pikir banyak kerangka kerja yang membutuhkan makro DECL dan IMPL menggunakannya.

epatel
sumber
1

Dalam bahasa prosedural, seperti C, maka beralih akan lebih baik daripada alternatif lainnya.

Dalam bahasa berorientasi objek, maka hampir selalu ada alternatif lain yang tersedia yang lebih baik memanfaatkan struktur objek, terutama polimorfisme.

Masalah dengan pernyataan switch muncul ketika beberapa blok switch sangat mirip terjadi di beberapa tempat dalam aplikasi, dan dukungan untuk nilai baru perlu ditambahkan. Sangat umum bagi pengembang untuk lupa menambahkan dukungan untuk nilai baru ke salah satu blok sakelar yang tersebar di sekitar aplikasi.

Dengan polimorfisme, maka kelas baru menggantikan nilai baru, dan perilaku baru ditambahkan sebagai bagian dari penambahan kelas baru. Perilaku pada titik-titik switch ini kemudian diwarisi dari superclass, diganti untuk memberikan perilaku baru, atau diimplementasikan untuk menghindari kesalahan kompilator ketika metode super abstrak.

Di mana tidak ada polimorfisme yang jelas terjadi, mungkin ada baiknya menerapkan pola Strategi .

Tetapi jika alternatif Anda adalah JIKA besar ... LALU ... LAGI blok, lupakan saja.

Bill Michell
sumber
1

Gunakan bahasa yang tidak dilengkapi dengan pernyataan sakelar bawaan. Perl 5 muncul di pikiran.

Serius, mengapa Anda ingin menghindarinya? Dan jika Anda memiliki alasan yang baik untuk menghindarinya, mengapa tidak menghindarinya saja?

innaM
sumber
1

Function pointer adalah salah satu cara untuk mengganti pernyataan switch chunky besar, mereka sangat baik dalam bahasa di mana Anda dapat menangkap fungsi dengan nama mereka dan membuat barang dengan mereka.

Tentu saja, Anda seharusnya tidak memaksakan pernyataan peralihan dari kode Anda, dan selalu ada kemungkinan Anda melakukan semuanya salah, yang menghasilkan potongan kode berlebihan yang bodoh. (Terkadang hal ini tidak dapat dihindari, tetapi bahasa yang baik harus memungkinkan Anda untuk menghapus redundansi saat tetap bersih.)

Ini adalah contoh pembagian & taklukkan yang hebat:

Katakanlah Anda memiliki semacam juru bahasa.

switch(*IP) {
    case OPCODE_ADD:
        ...
        break;
    case OPCODE_NOT_ZERO:
        ...
        break;
    case OPCODE_JUMP:
        ...
        break;
    default:
        fixme(*IP);
}

Sebagai gantinya, Anda dapat menggunakan ini:

opcode_table[*IP](*IP, vm);

... // in somewhere else:
void opcode_add(byte_opcode op, Vm* vm) { ... };
void opcode_not_zero(byte_opcode op, Vm* vm) { ... };
void opcode_jump(byte_opcode op, Vm* vm) { ... };
void opcode_default(byte_opcode op, Vm* vm) { /* fixme */ };

OpcodeFuncPtr opcode_table[256] = {
    ...
    opcode_add,
    opcode_not_zero,
    opcode_jump,
    opcode_default,
    opcode_default,
    ... // etc.
};

Perhatikan bahwa saya tidak tahu cara menghapus redundansi opcode_table di C. Mungkin saya harus mengajukan pertanyaan tentang itu. :)

Riang
sumber
0

Jawaban yang paling jelas, tidak tergantung pada bahasa, adalah menggunakan serangkaian 'jika'.

Jika bahasa yang Anda gunakan memiliki pointer fungsi (C) atau memiliki fungsi yang merupakan nilai kelas 1 (Lua), Anda dapat mencapai hasil yang mirip dengan "switch" menggunakan array (atau daftar) fungsi (pointer ke) fungsi.

Anda harus lebih spesifik pada bahasa tersebut jika Anda menginginkan jawaban yang lebih baik.

Remo.D
sumber
0

Pernyataan pergantian sering kali dapat diganti dengan desain OO yang bagus.

Misalnya, Anda memiliki kelas Akun, dan menggunakan pernyataan switch untuk melakukan perhitungan berbeda berdasarkan jenis akun.

Saya menyarankan bahwa ini harus diganti oleh sejumlah kelas akun, mewakili berbagai jenis akun, dan semua yang mengimplementasikan antarmuka Akun.

Peralihan kemudian menjadi tidak perlu, karena Anda dapat memperlakukan semua jenis akun sama dan berkat polimorfisme, perhitungan yang sesuai akan dijalankan untuk jenis akun.

jason
sumber
0

Tergantung mengapa Anda ingin menggantinya!

Banyak penerjemah menggunakan 'goto yang dikomputasi' alih-alih beralih pernyataan untuk eksekusi opcode.

Apa yang saya lewatkan tentang C / C ++ switch adalah Pascal 'in' dan rentang. Saya juga berharap saya bisa mengaktifkan string. Tapi ini, meskipun sepele bagi penyusun untuk makan, adalah kerja keras ketika dilakukan menggunakan struktur dan iterator dan hal-hal lainnya. Jadi, sebaliknya, ada banyak hal yang saya harap bisa saya ganti dengan saklar, jika saja saklar C () lebih fleksibel!

Akan
sumber
0

Switch bukanlah cara yang baik untuk pergi karena melanggar Open Close Principal. Beginilah cara saya melakukannya.

public class Animal
{
       public abstract void Speak();
}


public class Dog : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Hao Hao");
   }
}

public class Cat : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Meauuuu");
   }
}

Dan inilah cara menggunakannya (mengambil kode Anda):

foreach (var animal in zoo) 
{
    echo animal.speak();
}

Pada dasarnya yang kami lakukan adalah mendelegasikan tanggung jawab ke kelas anak alih-alih meminta orang tua memutuskan apa yang harus dilakukan dengan anak-anak.

Anda mungkin juga ingin membaca tentang "Prinsip Pergantian Liskov".

Sheraz
sumber
0

Dalam JavaScript menggunakan array asosiatif:
ini:

function getItemPricing(customer, item) {
    switch (customer.type) {
        // VIPs are awesome. Give them 50% off.
        case 'VIP':
            return item.price * item.quantity * 0.50;

            // Preferred customers are no VIPs, but they still get 25% off.
        case 'Preferred':
            return item.price * item.quantity * 0.75;

            // No discount for other customers.
        case 'Regular':
        case
        default:
            return item.price * item.quantity;
    }
}

menjadi ini:

function getItemPricing(customer, item) {
var pricing = {
    'VIP': function(item) {
        return item.price * item.quantity * 0.50;
    },
    'Preferred': function(item) {
        if (item.price <= 100.0)
            return item.price * item.quantity * 0.75;

        // Else
        return item.price * item.quantity;
    },
    'Regular': function(item) {
        return item.price * item.quantity;
    }
};

    if (pricing[customer.type])
        return pricing[customer.type](item);
    else
        return pricing.Regular(item);
}

Kesopanan

Premraj
sumber
-12

Voting lain untuk / lainnya. Saya bukan penggemar kasus atau beralih pernyataan karena ada beberapa orang yang tidak menggunakannya. Kode kurang dapat dibaca jika Anda menggunakan kasing atau sakelar. Mungkin tidak kurang mudah dibaca oleh Anda, tetapi bagi mereka yang tidak pernah perlu menggunakan perintah.

Hal yang sama berlaku untuk pabrik objek.

Jika / selain itu blok adalah konstruksi sederhana yang didapat semua orang. Ada beberapa hal yang dapat Anda lakukan untuk memastikan bahwa Anda tidak menyebabkan masalah.

Pertama - Jangan mencoba dan membuat indentasi jika pernyataan lebih dari beberapa kali. Jika Anda menemukan indentasi, maka Anda melakukan kesalahan.

 if a = 1 then 
     do something else 
     if a = 2 then 
         do something else
     else 
         if a = 3 then 
             do the last thing
         endif
     endif 
  endif

Benar-benar buruk - lakukan ini sebagai gantinya.

if a = 1 then 
   do something
endif 
if a = 2 then 
   do something else
endif 
if a = 3 then 
   do something more
endif 

Optimasi terkutuk. Itu tidak membuat banyak perbedaan dengan kecepatan kode Anda.

Kedua, saya tidak segan untuk keluar dari If Block selama ada cukup pernyataan break yang tersebar melalui blok kode tertentu untuk membuatnya jelas

procedure processA(a:int)
    if a = 1 then 
       do something
       procedure_return
    endif 
    if a = 2 then 
       do something else
       procedure_return
    endif 
    if a = 3 then 
       do something more
       procedure_return
    endif 
end_procedure

EDIT : On Switch dan mengapa saya pikir sulit untuk grok:

Berikut adalah contoh pernyataan beralih ...

private void doLog(LogLevel logLevel, String msg) {
   String prefix;
   switch (logLevel) {
     case INFO:
       prefix = "INFO";
       break;
     case WARN:
       prefix = "WARN";
       break;
     case ERROR:
       prefix = "ERROR";
       break;
     default:
       throw new RuntimeException("Oops, forgot to add stuff on new enum constant");
   }
   System.out.println(String.format("%s: %s", prefix, msg));
 }

Bagi saya masalahnya di sini adalah bahwa struktur kontrol normal yang berlaku dalam bahasa seperti C telah benar-benar rusak. Ada aturan umum bahwa jika Anda ingin menempatkan lebih dari satu baris kode di dalam struktur kontrol, Anda menggunakan tanda kurung kurawal atau awal / akhir.

misalnya

for i from 1 to 1000 {statement1; statement2}
if something=false then {statement1; statement2}
while isOKtoLoop {statement1; statement2}

Bagi saya (dan Anda dapat mengoreksi saya jika saya salah), pernyataan Case membuang aturan ini dari jendela. Blok kode yang dieksekusi secara kondisional tidak ditempatkan di dalam struktur awal / akhir. Karena itu, saya percaya bahwa Case secara konseptual cukup berbeda untuk tidak digunakan.

Semoga itu menjawab pertanyaan Anda.

seanyboy
sumber
Wow - jelas jawaban yang kontroversial. Saya tertarik untuk mengetahui kesalahan saya.
seanyboy
Eh, beralih karena terlalu rumit? Saya tidak tahu ... menurut saya tidak akan ada banyak fitur bahasa yang dapat Anda gunakan. :) Juga, dalam contoh utama Anda, bukankah akan lebih pintar jika (a == 1 || a == 2 || a == 3) melakukan sesuatu?
Lars Westergren
Juga, dalam contoh terakhir Anda, "break" tidak akan melakukan apa pun di sebagian besar bahasa-yang keluar dari blok terdekat (biasanya loop), yang dalam kasus Anda tetap terjadi pada baris berikutnya (endif). Jika Anda menggunakan bahasa di mana istirahat adalah "kembali", banyak pengembalian juga disukai (kecuali untuk "pernyataan penjaga")
Lars Westergren
4
"Optimasi terkutuk. Itu tidak membuat banyak perbedaan dengan kecepatan kode Anda." Kode saya berjalan di platform seluler. Optimalisasi penting. Lebih lanjut, sakelar dapat membuat kode terlihat SANGAT bersih (dibandingkan dengan jika..elseif..elseif..elseif ...) jika digunakan dengan benar. Belum pernah melihatnya? Pelajari mereka.
Swati
Switch tidak rumit sama sekali, tetapi saya selalu berusaha meminimalkan jumlah konstruksi yang digunakan dalam kode untuk mengurangi gesekan dalam pemahaman.
seanyboy