Saya menerima tinjauan kode dari pengembang senior hari ini dengan bertanya, "Ngomong-ngomong, apa keberatan Anda untuk mengirim fungsi dengan menggunakan pernyataan switch?" Saya telah membaca di banyak tempat tentang bagaimana memompa argumen melalui metode switch to call adalah OOP yang buruk, tidak dapat diperluas, dll. Namun, saya tidak dapat benar-benar memberikan jawaban yang pasti untuknya. Saya ingin menyelesaikan ini untuk diri saya sendiri sekali dan untuk semua.
Berikut adalah saran kode kami yang bersaing (php digunakan sebagai contoh, tetapi dapat diterapkan secara lebih universal):
class Switch {
public function go($arg) {
switch ($arg) {
case "one":
echo "one\n";
break;
case "two":
echo "two\n";
break;
case "three":
echo "three\n";
break;
default:
throw new Exception("Unknown call: $arg");
break;
}
}
}
class Oop {
public function go_one() {
echo "one\n";
}
public function go_two() {
echo "two\n";
}
public function go_three() {
echo "three\n";
}
public function __call($_, $__) {
throw new Exception("Unknown call $_ with arguments: " . print_r($__, true));
}
}
Bagian dari argumennya adalah "Ini (beralih metode) memiliki cara yang jauh lebih bersih dalam menangani kasus default daripada apa yang Anda miliki dalam metode sihir __call () generik."
Saya tidak setuju tentang kebersihan dan bahkan lebih suka menelepon, tetapi saya ingin mendengar apa yang orang lain katakan.
Argumen yang bisa saya kemukakan dalam mendukung Oop
skema:
- Sedikit lebih bersih dalam hal kode yang harus Anda tulis (lebih sedikit, lebih mudah dibaca, lebih sedikit kata kunci untuk dipertimbangkan)
- Tidak semua tindakan didelegasikan ke metode tunggal. Tidak banyak perbedaan dalam eksekusi di sini, tetapi setidaknya teks lebih terkotak.
- Dalam nada yang sama, metode lain dapat ditambahkan di mana saja di kelas daripada tempat tertentu.
- Metode diberi nama, yang bagus.
- Tidak berlaku di sini, tetapi mempertimbangkan kasus di mana
Switch::go()
dioperasikan pada anggota daripada parameter. Anda harus mengubah anggota terlebih dahulu, lalu memanggil metode. UntukOop
Anda dapat memanggil metode secara mandiri kapan saja.
Argumen yang bisa saya kemukakan dalam mendukung Switch
skema:
- Demi argumen, metode yang lebih bersih untuk menangani permintaan default (tidak diketahui)
- Tampaknya kurang ajaib, yang mungkin membuat pengembang asing merasa lebih nyaman
Adakah yang punya sesuatu untuk ditambahkan di kedua sisi? Saya ingin memiliki jawaban yang bagus untuknya.
sumber
Oop
memungkinkan untuk memiliki phpdoc untuk menggambarkan setiap metode, yang dapat diuraikan oleh beberapa IDE (misalnya, NetBeans).Jawaban:
Saklar dianggap bukan OOP karena sering polimorfisme dapat melakukan trik.
Dalam kasus Anda, implementasi OOP bisa seperti ini:
sumber
untuk contoh ini:
OKE, hanya bercanda sebagian di sini. Argumen untuk / terhadap penggunaan pernyataan switch tidak dapat dengan kuat dibuat dengan contoh sepele seperti itu, karena sisi OOP tergantung pada semantik yang terlibat, bukan hanya mekanisme pengiriman .
Pernyataan pergantian sering merupakan indikasi kelas yang hilang atau klasifikasi, tetapi tidak harus. Terkadang pernyataan switch hanyalah pernyataan switch .
sumber
Mungkin bukan jawaban, tetapi dalam kasus kode non-switch, sepertinya ini akan menjadi pasangan yang lebih baik:
Sebagian besar teka-teki untuk menilai adalah apa yang terjadi ketika Anda perlu membuat
NewSwitch
atauNewOop
. Apakah programmer Anda harus melewati rintangan dengan satu metode atau yang lain? Apa yang terjadi ketika aturan Anda berubah, dll.sumber
is_callable
, tetapi meninggalkan call_user_func karena (bukan bagian dari pertanyaan ini), mungkin ada argumen lain untuk diteruskan. Tapi sekarang ini telah pindah ke programmer, saya pasti setuju bahwa jawaban @ Andrea jauh lebih baik :)Alih-alih hanya menempatkan kode eksekusi Anda ke dalam fungsi mengimplementasikan pola perintah penuh dan menempatkan masing-masing di kelas mereka sendiri yang mengimplementasikan antarmuka umum. Metode ini memungkinkan Anda untuk menggunakan IOC / DI untuk menghubungkan berbagai "kasus" kelas Anda dan memungkinkan Anda untuk dengan mudah menambah dan menghapus kasus dari kode Anda dari waktu ke waktu. Ini juga memberi Anda sedikit kode yang tidak melanggar prinsip pemrograman SOLID.
sumber
Saya pikir contohnya buruk. Jika ada fungsi go () yang menerima argumen $ where, if valid untuk menggunakan switch di function. Memiliki fungsi single go () memudahkan untuk memodifikasi perilaku semua go_where () scenarious. Selain itu, Anda akan mempertahankan antarmuka kelas - jika Anda menggunakan berbagai metode, Anda memodifikasi antarmuka kelas dengan setiap tujuan baru.
Sebenarnya switch tidak boleh diganti dengan set metode, tetapi dengan set kelas - ini adalah polimorfisme. Kemudian tujuan akan ditangani oleh setiap subclass, dan akan ada metode single go () untuk mereka semua. Ganti kondisional dengan polimorfisme adalah salah satu refactoring dasar, yang dijelaskan oleh Martin Fowler. Tapi Anda mungkin tidak perlu polimorfisme, dan beralih adalah cara untuk pergi.
sumber
go()
ia dapat dengan mudah melanggar prinsip Pergantian Liskov. Jika Anda menambahkan fungsionalitas lebih kego()
, Anda jangan ingin mengubah antarmuka sejauh yang saya concerend.