Apa cara untuk menghilangkan penggunaan kode saklar?
design-patterns
Mariano
sumber
sumber
Jawaban:
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:
menjadi ini:
sumber
typeof
, dan jawaban ini tidak menyarankan cara atau alasan untuk bekerja di sekitar pernyataan switch dalam situasi lain.Lihat Beralih Pernyataan Bau :
Baik Refactoring dan Refactoring to Patterns memiliki pendekatan untuk menyelesaikannya.
Jika kode (semu) Anda terlihat seperti:
Kode ini melanggar Prinsip Terbuka Terbuka dan rentan terhadap setiap jenis kode tindakan baru yang muncul. Untuk memperbaiki ini, Anda bisa memperkenalkan objek 'Perintah':
Jika kode (semu) Anda terlihat seperti:
Maka Anda bisa memperkenalkan objek 'Negara'.
Semoga ini membantu.
sumber
Map<Integer, Command>
tidak perlu switch?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:
sumber
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.
sumber
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:
sumber
Semua orang suka
if else
blok 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.
sumber
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:
sumber
switch
pernyataan akan baik untuk diganti jika Anda menemukan diri Anda menambahkan negara baru atau perilaku baru ke pernyataan:Menambahkan perilaku baru memerlukan menyalin
switch
, dan menambahkan status baru berarti menambahkan yang laincase
untuk setiapswitch
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 - else
blok 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:
Setiap kali Anda menambahkan status baru, Anda harus menambahkan implementasi
IState
antarmuka baru. Diswitch
dunia, Anda akan menambahkancase
masing-masingswitch
.Setiap kali Anda menambahkan perilaku baru, Anda perlu menambahkan metode baru ke
IState
antarmuka, 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.
sumber
jika ada
Saya menyangkal premis bahwa saklar pada dasarnya buruk.
sumber
Yah, untuk satu hal, saya tidak tahu menggunakan sakelar adalah pola anti.
Kedua, switch selalu bisa diganti dengan pernyataan if / else.
sumber
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.
sumber
'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.
sumber
Jika saklar ada untuk membedakan berbagai jenis objek, Anda mungkin kehilangan beberapa kelas untuk menggambarkan objek-objek itu dengan tepat, atau beberapa metode virtual ...
sumber
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.
sumber
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.
sumber
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?
sumber
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.
Sebagai gantinya, Anda dapat menggunakan ini:
Perhatikan bahwa saya tidak tahu cara menghapus redundansi opcode_table di C. Mungkin saya harus mengajukan pertanyaan tentang itu. :)
sumber
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.
sumber
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.
sumber
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!
sumber
Switch bukanlah cara yang baik untuk pergi karena melanggar Open Close Principal. Beginilah cara saya melakukannya.
Dan inilah cara menggunakannya (mengambil kode Anda):
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".
sumber
Dalam JavaScript menggunakan array asosiatif:
ini:
menjadi ini:
Kesopanan
sumber
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.
Benar-benar buruk - lakukan ini sebagai gantinya.
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
EDIT : On Switch dan mengapa saya pikir sulit untuk grok:
Berikut adalah contoh pernyataan beralih ...
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
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.
sumber