Saya telah diberi beberapa kode Java untuk dilihat, yang mensimulasikan perlombaan mobil, yang mencakup implementasi mesin keadaan dasar. Ini bukan mesin negara ilmu komputer klasik, tetapi hanya sebuah objek yang dapat memiliki beberapa negara, dan dapat beralih di antara negara-negara berdasarkan serangkaian perhitungan.
Untuk menjelaskan masalahnya, saya punya kelas Mobil, dengan kelas enum bersarang yang mendefinisikan beberapa konstanta untuk kondisi Mobil (seperti OFF, IDLE, DRIVE, REVERSE, dll). Di dalam kelas Mobil yang sama ini saya memiliki fungsi pembaruan, yang pada dasarnya terdiri dari pernyataan sakelar besar yang mengaktifkan keadaan mobil saat ini, melakukan beberapa perhitungan dan kemudian mengubah keadaan mobil.
Sejauh yang saya bisa lihat, keadaan Cars hanya digunakan dalam kelasnya sendiri.
Pertanyaan saya adalah, apakah ini cara terbaik untuk berurusan dengan implementasi mesin negara yang dijelaskan di atas? Memang terdengar seperti solusi yang paling jelas, tetapi di masa lalu saya selalu mendengar bahwa "pernyataan switch buruk".
Masalah utama yang dapat saya lihat di sini adalah bahwa pernyataan switch mungkin menjadi sangat besar karena kami menambahkan lebih banyak status (jika dianggap perlu) dan kode dapat menjadi sulit digunakan dan sulit untuk dipelihara.
Apa solusi yang lebih baik untuk masalah ini?
sumber
object.state = object.function(object.state);
Jawaban:
Saya mengubah mobil menjadi semacam mesin negara menggunakan Pola Negara . Perhatikan tidak ada
switch
atauif-then-else
pernyataan yang digunakan untuk pemilihan negara.Dalam hal ini semua negara bagian adalah kelas dalam tetapi bisa diterapkan sebaliknya.
Setiap negara bagian berisi status valid yang dapat diubah.
Pengguna diminta untuk keadaan berikutnya jika lebih dari satu mungkin, atau hanya untuk mengonfirmasi jika hanya satu yang mungkin.
Anda dapat mengompilasinya dan menjalankannya untuk mengujinya.
Saya menggunakan kotak dialog grafik karena lebih mudah untuk menjalankannya secara interaktif di Eclipse.
Diagram UML diambil dari sini .
sumber
Ini semacam penyederhanaan yang memberi pemrograman berorientasi objek nama yang buruk. Menggunakan
if
sama buruknya dengan menggunakan pernyataan switch. Bagaimanapun Anda tidak mengirim secara polimorfik.Jika Anda harus memiliki aturan yang sesuai dengan gigitan suara coba yang ini:
Pernyataan beralih yang tidak digandakan di tempat lain dalam basis kode kadang-kadang dapat dikelola untuk tidak menjadi jahat. Jika kasusnya tidak umum, tetapi dikemas, itu benar-benar urusan orang lain. Terutama jika Anda tahu bagaimana dan kapan refactor ke dalam kelas. Hanya karena Anda tidak dapat berarti Anda harus melakukannya. Itu karena Anda dapat melakukannya sehingga kurang penting untuk melakukannya sekarang.
Jika Anda menemukan diri Anda mencoba untuk mendorong lebih banyak dan lebih banyak hal ke dalam pernyataan peralihan, menyebarkan pengetahuan tentang kasus-kasus di sekitar, atau berharap itu tidak begitu jahat untuk hanya membuat salinannya maka sudah waktunya untuk mengubah kasus ke dalam kelas yang terpisah.
Jika Anda punya waktu untuk membaca lebih dari beberapa gigitan suara tentang pernyataan penggantian refactoring c2 memiliki halaman yang sangat seimbang tentang bau pernyataan switch .
Bahkan dalam kode OOP, tidak setiap switch buruk. Begitulah cara Anda menggunakannya, dan mengapa.
sumber
Mobil adalah jenis mesin negara. Pernyataan peralihan adalah cara paling sederhana untuk mengimplementasikan mesin status yang tidak memiliki super state dan sub state.
sumber
Pergantian pernyataan tidak buruk. Jangan dengarkan orang yang mengatakan hal-hal seperti "alihkan statments itu buruk"! Beberapa penggunaan tertentu dari pernyataan switch adalah antipattern, seperti menggunakan switch untuk meniru subclassing. (Tetapi Anda juga dapat menerapkan antipattern ini dengan if, jadi saya kira jika buruk juga!).
Implementasi Anda terdengar bagus. Anda benar adalah akan sulit untuk mempertahankan jika Anda menambahkan lebih banyak negara. Tapi ini bukan hanya masalah implementasi - memiliki objek dengan banyak negara dengan perilaku berbeda itu sendiri merupakan masalah. Pencitraan mobil Anda memiliki 25 negara bagian yang masing-masing menunjukkan perilaku yang berbeda dan aturan yang berbeda untuk transisi negara. Hanya untuk menentukan dan mendokumentasikan perilaku ini akan menjadi tugas yang sangat besar. Anda akan memiliki ribuan aturan transisi negara! Ukuran
switch
hanya akan menjadi gejala dari masalah yang lebih besar. Jadi jika mungkin hindari jalan ini.Obat yang mungkin adalah memecah negara menjadi substrat independen. Misalnya, apakah REVERSE benar-benar keadaan yang berbeda dari DRIVE? Mungkin status mobil dapat dipecah menjadi dua: Status engine (OFF, IDLE, DRIVE) dan arah (FORWARD, REVERSE). Status dan arah engine mungkin sebagian besar independen, sehingga Anda mengurangi duplikasi logika dan aturan transisi state. Lebih banyak objek dengan status lebih sedikit lebih mudah untuk dikelola daripada objek tunggal dengan banyak status.
sumber
Dalam contoh Anda, mobil hanyalah mesin negara dalam pengertian ilmu komputer klasik. Mereka memiliki sekelompok negara kecil yang didefinisikan dengan baik dan semacam logika transisi negara.
Saran pertama saya adalah mempertimbangkan memecah logika transisi ke fungsinya sendiri (atau kelas, jika bahasa Anda tidak mendukung fungsi kelas satu).
Saran kedua saya adalah untuk mempertimbangkan memecah logika transisi ke negara itu sendiri, yang akan memiliki fungsinya sendiri (atau kelas, jika bahasa Anda tidak mendukung fungsi kelas satu).
Dalam skema mana pun, proses untuk keadaan transisi akan terlihat seperti ini:
atau
Yang kedua, tentu saja, sepele bisa dibungkus dalam kelas mobil agar terlihat seperti yang pertama.
Dalam kedua skenario, menambahkan negara baru (katakanlah, DRAFT), hanya akan melibatkan menambahkan objek negara jenis baru dan mengubah objek yang secara khusus beralih ke keadaan baru.
sumber
Itu tergantung pada seberapa besar
switch
mungkin.Dalam contoh Anda, saya pikir a
switch
tidak apa-apa karena sebenarnya tidak ada negara lain yang dapat saya pikirkan yangCar
dapat Anda miliki, sehingga tidak akan bertambah besar seiring waktu.Jika satu-satunya masalah adalah memiliki saklar besar di mana masing-masing
case
memiliki banyak instruksi, maka cukup buat metode pribadi yang berbeda untuk masing-masing.Kadang-kadang orang menyarankan pola desain keadaan , tetapi lebih tepat ketika Anda berurusan dengan logika yang kompleks, dan menyatakan membuat keputusan bisnis yang berbeda untuk banyak operasi yang berbeda. Kalau tidak, masalah sederhana harus memiliki solusi sederhana.
Dalam beberapa skenario, Anda bisa memiliki metode yang hanya melakukan tugas ketika negara adalah A atau B, tetapi bukan C atau D, atau memiliki beberapa metode dengan operasi yang sangat sederhana yang bergantung pada negara. Maka satu atau beberapa
switch
pernyataan akan lebih baik.sumber
Ini kedengarannya seperti mesin state-school lama dari jenis yang digunakan sebelum siapa pun melakukan pemrograman Berorientasi Objek, apalagi Pola Desain. Ini dapat diimplementasikan dalam bahasa apa pun yang memiliki pernyataan peralihan, seperti C.
Seperti yang orang lain katakan, pada dasarnya tidak ada yang salah dengan pernyataan pergantian. Alternatifnya seringkali lebih rumit dan lebih sulit untuk dipahami.
Kecuali jika jumlah sakelar menjadi sangat besar, masalahnya tetap dapat dikelola. Langkah pertama agar tetap mudah dibaca adalah mengganti kode dalam setiap kasus dengan pemanggilan fungsi untuk mengimplementasikan perilaku negara.
sumber