Dalam desain program saya, saya sering sampai pada titik di mana saya harus melewati instance objek melalui beberapa kelas. Misalnya, jika saya memiliki pengontrol yang memuat file audio, dan kemudian meneruskannya ke pemain, dan pemain meneruskannya ke playerRunnable, yang meneruskannya lagi di tempat lain dll. Terlihat agak buruk, tapi saya tidak tahu bagaimana menghindarinya. Atau apakah boleh melakukan ini?
EDIT: Mungkin contoh pemain bukan yang terbaik karena saya bisa memuat file nanti, tetapi dalam kasus lain itu tidak berfungsi.
sumber
Menarik bahwa belum ada yang membicarakan objek yang tidak dapat berubah . Saya berpendapat bahwa melewatkan objek abadi di sekitar semua lapisan sebenarnya adalah hal yang baik daripada membuat banyak objek berumur pendek untuk setiap lapisan.
Ada beberapa diskusi hebat tentang ketidakberdayaan oleh Eric Lippert di blog-nya
Di sisi lain saya berpendapat bahwa melewatkan objek yang bisa berubah di antara lapisan adalah desain yang buruk . Pada dasarnya Anda membuat layer dengan janji bahwa layer di sekitarnya tidak akan mengubahnya dengan cara memecahkan kode Anda.
sumber
Melewatkan contoh objek di sekitar adalah hal biasa untuk dilakukan. Ini mengurangi kebutuhan untuk menjaga keadaan (misalnya variabel instan) dan memisahkan kode dari konteks eksekusi.
Salah satu masalah yang mungkin Anda hadapi adalah refactoring, ketika Anda harus mengubah tanda tangan beberapa metode di sepanjang rantai doa sebagai tanggapan terhadap perubahan persyaratan parameter metode di dekat bagian bawah rantai itu. Namun, ini dapat dikurangi dengan penggunaan alat pengembangan perangkat lunak modern yang membantu dalam refactoring.
sumber
Mungkin kecil, tetapi ada risiko menempatkan referensi ini di suatu tempat di salah satu lapisan yang berpotensi menyebabkan referensi yang menggantung atau kebocoran memori di kemudian hari ..
sumber
Jika Anda melewati objek hanya karena dibutuhkan di daerah terpencil kode Anda, menggunakan inversi kontrol dan pola desain injeksi dependensi bersama dengan opsional wadah IoC yang tepat dapat dengan baik memecahkan masalah tentang membawa contoh objek sekitar. Saya telah menggunakannya pada proyek berukuran sedang dan tidak akan pernah lagi mempertimbangkan untuk menulis sepotong besar kode server tanpa menggunakannya.
sumber
Melewati data melalui banyak lapisan bukanlah hal yang buruk, ini satu-satunya cara sistem layered dapat bekerja tanpa melanggar struktur layered. Tanda ada masalah adalah ketika Anda mengirimkan data Anda ke beberapa objek di lapisan yang sama untuk mencapai tujuan Anda.
sumber
Jawaban Cepat: Tidak ada yang salah dalam melewati instance objek. Seperti yang juga disebutkan, intinya adalah melompati pemberian referensi ini di semua lapisan yang berpotensi menyebabkan referensi yang menggantung atau kebocoran memori.
Dalam proyek kami, kami menggunakan praktik ini untuk lulus DTO (objek transfer data) antara lapisan dan itu adalah praktik yang sangat membantu. Kami juga menggunakan kembali objek dto kami untuk membangun lebih kompleks sekali, seperti untuk informasi ringkasan.
sumber
Saya terutama seorang web UI dev tetapi bagi saya sepertinya ketidaknyamanan intuitif Anda mungkin kurang tentang contoh pass-through dan lebih banyak tentang fakta bahwa Anda akan sedikit prosedural dengan controller itu. Haruskah controller Anda berkeringat semua detail ini? Mengapa bahkan referensi lebih dari satu nama objek lain untuk mendapatkan audio diputar?
Dalam desain OOP, saya cenderung berpikir tentang apa yang selalu hijau dan apa yang lebih mungkin berubah. Subjek untuk mengubah hal-hal adalah apa yang Anda ingin cenderung untuk dimasukkan ke dalam kotak objek yang lebih besar sehingga Anda dapat mempertahankan antarmuka yang konsisten bahkan ketika pemain berubah atau opsi baru ditambahkan. Atau Anda menemukan diri Anda ingin menukar objek audio atau komponen di dalamnya secara grosir.
Dalam hal ini, pengontrol Anda perlu mengidentifikasi bahwa ada kebutuhan untuk memutar file audio dan kemudian memiliki cara yang konsisten / selalu hijau untuk membuatnya diputar. Hal-hal pemutar audio di sisi lain dapat dengan mudah berubah ketika teknologi dan platform diubah atau pilihan baru ditambahkan. Semua perincian itu harus berada di bawah antarmuka objek komposit yang lebih besar, IMO, dan Anda tidak perlu menulis ulang pengontrol Anda saat perincian tentang bagaimana audio dimainkan berubah. Kemudian ketika Anda melewatkan contoh objek dengan detail seperti lokasi file ke objek yang lebih besar semua yang bertukar dilakukan di interior konteks yang sesuai di mana seseorang cenderung melakukan sesuatu yang konyol dengannya.
Jadi dalam hal ini saya tidak berpikir bahwa objek objek yang dilempar yang mungkin mengganggu Anda. Kapten Picard berlari ke ruang mesin untuk menghidupkan inti warp, berlari kembali ke jembatan untuk merencanakan koordinat, dan kemudian menekan tombol "punch-it" setelah menyalakan perisai alih-alih hanya mengatakan "Ambil kita ke planet X di Warp 9. Jadikan begitu. " dan membiarkan krunya memilah detailnya. Karena ketika dia menanganinya seperti itu, dia bisa menjadi kapten kapal apa pun di armada tanpa mengetahui tata letak setiap kapal dan bagaimana semuanya bekerja. Dan itulah akhirnya kemenangan desain OOP terbesar untuk IMO.
sumber
Ini adalah desain yang cukup umum yang akhirnya terjadi walaupun Anda mungkin memiliki masalah latensi jika aplikasi Anda sensitif terhadap hal semacam itu.
sumber
Masalah ini dapat diselesaikan dengan variabel cakupan dinamis, jika bahasa Anda memilikinya, atau penyimpanan thread-lokal. Mekanisme ini memungkinkan kami mengaitkan beberapa variabel khusus dengan rantai aktivasi atau untaian kontrol, sehingga kami tidak harus meneruskan nilai-nilai ini ke dalam kode yang tidak ada hubungannya dengan mereka hanya agar dapat dikomunikasikan ke beberapa kode lain yang memang membutuhkannya.
sumber
Seperti yang ditunjukkan oleh jawaban lain, ini bukan desain yang buruk. Itu dapat membuat kopling ketat antara kelas bersarang dan yang bersarang, tetapi melonggarkan kopling mungkin bukan opsi yang valid jika bersarang referensi memberikan nilai pada desain.
Salah satu solusi yang mungkin adalah "meratakan" referensi bersarang di kelas controller.
Alih-alih melewatkan parameter beberapa kali melalui objek bersarang, Anda bisa mempertahankan referensi kelas pengontrol ke semua objek bersarang.
Bagaimana tepatnya ini diterapkan (atau jika itu bahkan solusi yang valid) tergantung pada desain sistem saat ini, seperti:
Ini adalah masalah yang saya temui dalam pola desain MVC untuk klien GXT. Komponen GUI kami berisi komponen GUI bersarang untuk beberapa lapisan. Ketika data model diperbarui, kami akhirnya melewati beberapa lapisan sampai mencapai komponen yang sesuai. Itu menciptakan kopling yang tidak diinginkan antara komponen GUI karena jika kami ingin kelas komponen GUI baru untuk menerima data model, kami harus membuat metode untuk memperbarui data model di semua komponen GUI yang berisi kelas baru.
Untuk memperbaikinya, kami memelihara di kelas Lihat peta referensi untuk semua komponen GUI bersarang sehingga setiap kali data model diperbarui, Lihat dapat mengirim data model yang diperbarui langsung ke komponen GUI yang membutuhkannya, akhir cerita . Ini bekerja dengan baik karena hanya ada satu contoh dari setiap komponen GUI. Saya bisa melihatnya tidak berfungsi dengan baik jika ada beberapa contoh beberapa komponen GUI, membuatnya sulit untuk mengidentifikasi salinan mana yang perlu diperbarui.
sumber
Apa yang Anda gambarkan adalah yang disebut pola desain Chain Of Responsibility . Apple menggunakan pola ini untuk sistem penanganan acara mereka, untuk apa nilainya.
sumber