Saya membaca tentang pola desain, dan saya membaca bahwa pola desain prototipe tidak menghilangkan subclass yang berlebihan.
Mengapa subklas buruk? Apa keuntungan menggunakan prototipe jika dibandingkan dengan subklas?
Saya membaca tentang pola desain, dan saya membaca bahwa pola desain prototipe tidak menghilangkan subclass yang berlebihan.
Mengapa subklas buruk? Apa keuntungan menggunakan prototipe jika dibandingkan dengan subklas?
Jawaban:
Mengapa subklas terlalu buruk
"Terlalu banyak" adalah panggilan penilaian; tetapi ambil dari saya itu buruk. Kode yang saya gunakan memiliki pewarisan DEEP dan kodenya sulit dibaca, dimengerti, diikuti, ditelusuri, didebug, dll. Secara efektif tidak mungkin untuk menulis kode uji untuk hal-hal ini.
Pola prototipe tidak jauh dengan subclassing
Atau apakah pertanyaannya berarti "tidakkah terlalu banyak subklas?". Pola ini membutuhkan kloning objek "templat" untuk menghindari subklasifikasi, setidaknya pada saat itu. Tidak ada aturan yang mengatakan bahwa "templat" tidak boleh menjadi subkelas.
Komposisi nikmat daripada warisan
Gagasan ini di sini juga mencakup delegasi dan agregasi. Mengikuti heuristik ini berarti perangkat lunak Anda cenderung lebih fleksibel, lebih mudah dirawat, diperluas, dan digunakan kembali.
Ketika kelas terdiri dari bagian-bagian Anda dapat mengganti bagian-bagian tersebut saat runtime . Ini memiliki efek mendalam pada testabilitas.
Pengujian lebih mudah . Anda dapat menggunakan bagian palsu (mis. "Mengejek", "ganda" dan ujicoba lainnya). Warisan mendalam kode kami berarti kami harus membuat seluruh hierarki untuk menguji sedikit pun. Dalam kasus kami itu tidak mungkin tanpa menjalankan kode di lingkungan nyata itu. Sebagai contoh, kita memerlukan database untuk membuat instance objek bisnis.
Perubahan datang dengan efek samping dan ketidakpastian - Semakin "dasar" kelas semakin luas efeknya, baik atau buruk. Mungkin ada perubahan yang Anda tidak berani lakukan karena efek samping yang tidak pasti. Atau perubahan yang baik untuk suatu tempat dalam rantai warisan kita adalah buruk untuk yang lain. Ini tentu saja pengalaman saya.
Saya pikir salah satu alasan ini telah dianggap sebagai praktik yang buruk adalah bahwa seiring waktu setiap subclass dapat berisi atribut dan metode yang tidak masuk akal untuk objek yang semakin Anda turun rantai (dalam hierarki yang kurang berkembang). Anda bisa berakhir dengan kelas membengkak yang berisi item yang tidak masuk akal untuk kelas itu.
Saya agnostik tentang ini sendiri. Tampaknya dogmatis untuk mengatakan itu buruk. Apa pun buruk ketika disalahgunakan.
Dua alasan.
Apakah kinerja runtime. Setiap kali Anda memanggil subkelas dari superclass, Anda melakukan pemanggilan metode, jadi jika Anda telah membuat lima kelas dan memanggil metode di kelas dasar, Anda akan melakukan lima pemanggilan metode. Sebagian besar kompiler / runtime akan mencoba mengenali hal ini dan mengoptimalkan panggilan tambahan pergi tetapi hanya aman untuk melakukan ini untuk kasus yang sangat sederhana.
Apakah kewarasan sesama programmer Anda. Jika Anda bersarang lima kelas saya harus memeriksa keempat kelas induk untuk memastikan Anda benar-benar memanggil metode di kelas dasar, itu akan membosankan. Saya mungkin juga harus melangkah melalui lima metode doa ketika saya men-debug program.
"Terlalu banyak" adalah panggilan penilaian.
Seperti kebanyakan hal dalam pemrograman, sub-klasifikasi secara inheren tidak buruk ketika masuk akal. Ketika model solusi masalah Anda lebih masuk akal sebagai hierarki daripada komposisi bagian, subklas mungkin pilihan yang disukai.
Yang mengatakan, lebih menyukai komposisi daripada warisan adalah aturan praktis yang baik.
Ketika Anda subkelas, pengujian bisa lebih sulit (seperti yang dicatat radarbob ). Dalam hierarki yang mendalam, mengisolasi kode bermasalah lebih sulit karena instantiating subclass membutuhkan membawa seluruh hirarki superclass dan banyak kode tambahan. Dengan pendekatan komposisi, Anda dapat mengisolasi dan menguji setiap komponen objek agregat Anda dengan unit test, objek tiruan, dll.
Subkelas juga dapat menyebabkan Anda mengekspos detail implementasi yang mungkin tidak Anda inginkan. Ini membuatnya sulit untuk mengontrol akses ke representasi data Anda yang mendasarinya dan itu mengikat Anda pada implementasi tertentu dari model dukungan Anda.
Salah satu contoh yang bisa saya pikirkan adalah java.util.Properties, yang diwarisi dari Hashtable. Kelas Properties hanya dimaksudkan untuk menyimpan pasangan String-String (ini dicatat di Javadocs). Karena pewarisan, metode put dan putAll dari Hashtable telah terpapar ke pengguna Properties. Sementara cara "benar" untuk menyimpan properti adalah dengan setProperty (), sama sekali tidak ada yang mencegah pengguna untuk memanggil put () dan mengirimkan String dan Object.
Pada dasarnya, semantik Properti tidak didefinisikan dengan baik karena warisan. Selain itu, jika ada orang yang ingin mengubah objek dukungan untuk Properti, dampaknya akan memiliki dampak yang jauh lebih besar pada kode yang menggunakan Properti daripada jika Properti telah mengambil pendekatan yang lebih komposisional.
Warisan dapat merusak enkapsulasi dalam beberapa kasus, dan jika itu terjadi itu buruk. Baca lebih lanjut.
Di masa lalu yang baik tanpa warisan, perpustakaan akan menerbitkan API dan aplikasi yang menggunakannya memanfaatkan apa yang dapat dilihat secara publik , dan perpustakaan sekarang memiliki caranya sendiri untuk menangani roda gigi internal yang terus berubah tanpa merusak Aplikasi.
Seiring dengan perkembangan kebutuhan, perpustakaan dapat berkembang dan dapat memiliki lebih banyak pelanggan; atau dapat memberikan fungsionalitas yang diperluas dengan mewarisi dari kelasnya sendiri dengan rasa lain. Sejauh ini baik.
Namun, hal mendasarnya adalah, jika sebuah aplikasi mengambil kelas dan mulai subkelasnya, sekarang sebuah subkelas sebenarnya adalah klien daripada mitra internal. Namun, tidak seperti cara jelas yang jelas bahwa API publik didefinisikan, subclass sekarang jauh lebih dalam di dalam perpustakaan (akses ke semua variabel pribadi dan sebagainya). Ini belum buruk, tetapi karakter jahat dapat menjembatani API yang terlalu banyak di dalam APP maupun di perpustakaan-
Intinya sementara ini mungkin tidak selalu terjadi tetapi,
Sangat mudah untuk menyalahgunakan warisan untuk memecah enkapsulasi
Mengizinkan subclassing bisa salah jika saat itu.
Jawaban Cepat Singkat:
Tergantung pada apa yang Anda lakukan.
Jawaban Membosankan yang Diperpanjang:
Pengembang dapat membuat aplikasi. menggunakan salah satu, subclassing atau templat (prototypal). Terkadang satu teknik bekerja lebih baik. Terkadang techinque lain bekerja lebih baik.
Memilih dengan teknik berfungsi paling baik, juga membutuhkan, untuk mempertimbangkan apakah skenario "Warisan Berganda" hadir. Bahkan jika bahasa pemrograman hanya mendukung pewarisan tunggal, templat atau prototipe.
Catatan Pelengkap:
Beberapa jawaban terkait dengan "pewarisan berganda". Sebenarnya, bukan pertanyaan utama, itu terkait dengan subjek. Ada beberapa posting yang serupa tentang "pewarisan berganda vs komposisi". Saya punya kasus di mana saya mencampur keduanya.