Katakanlah kita memiliki 1001 klien yang membangun dependensi mereka secara langsung daripada menerima suntikan. Refactoring the 1001 bukanlah pilihan menurut bos kami. Kami sebenarnya bahkan tidak diizinkan mengakses sumbernya, hanya file kelas.
Apa yang seharusnya kita lakukan adalah "memodernisasi" sistem yang dilalui oleh 1001 klien ini. Kita dapat memperbaiki itu sesuka kita. Ketergantungan adalah bagian dari sistem itu. Dan beberapa dependensi yang seharusnya kita ubah untuk memiliki implementasi baru.
Apa yang ingin kami lakukan adalah memiliki kemampuan untuk mengkonfigurasi implementasi dependensi yang berbeda untuk memuaskan banyak klien ini. Sayangnya, DI tampaknya bukan pilihan karena klien tidak menerima suntikan dengan konstruktor atau setter.
Opsi:
1) Refactor implementasi layanan yang digunakan klien sehingga ia melakukan apa yang dibutuhkan klien sekarang. Bang kita sudah selesai. Tidak fleksibel. Tidak rumit.
2) Refactor implementasi sehingga mendelegasikan pekerjaannya ke ketergantungan lain yang diperoleh melalui pabrik. Sekarang kita dapat mengontrol implementasi mana yang mereka gunakan dengan refactoring pabrik.
3) Refactor implementasi sehingga mendelegasikan pekerjaannya ke ketergantungan lain yang diperolehnya melalui pencari layanan. Sekarang kita dapat mengontrol implementasi mana yang mereka semua gunakan dengan mengkonfigurasi locator layanan yang mungkin hanya berupa hashmap
string ke objek dengan sedikit casting yang terjadi.
4) Sesuatu yang bahkan belum kupikirkan.
Objektif:
Minimalkan kerusakan desain yang disebabkan oleh menyeret kode klien yang dirancang dengan buruk ke masa depan tanpa menambah kompleksitas yang tidak ada gunanya.
Klien seharusnya tidak mengetahui atau mengendalikan implementasi dependensi mereka tetapi mereka bersikeras untuk membangunnya bersama new
. Kami tidak bisa mengendalikan, new
tetapi kami mengontrol kelas yang mereka bangun.
Pertanyaan saya:
Apa yang gagal saya pertimbangkan?
apakah Anda benar-benar membutuhkan kemungkinan untuk mengkonfigurasi antar implementasi yang berbeda? Untuk tujuan apa?
Kelincahan. Banyak yang tidak diketahui. Manajemen menginginkan potensi perubahan. Kehilangan ketergantungan hanya pada dunia luar. Juga menguji.
apakah Anda memerlukan mekanik waktu berjalan, atau hanya kompilasi waktu mekanik untuk beralih di antara implementasi yang berbeda? Mengapa?
Mekanika waktu kompilasi kemungkinan cukup. Kecuali untuk pengujian.
granularity mana yang Anda perlukan untuk beralih antar implementasi? Semua sekaligus? Per modul (masing-masing berisi sekelompok kelas)? Per kelas?
Dari 1001 hanya satu yang dijalankan melalui sistem pada satu waktu. Mengubah apa yang digunakan semua klien sekaligus kemungkinan besar tidak masalah. Kontrol individu terhadap ketergantungan sepertinya penting.
siapa yang perlu mengendalikan sakelar? Hanya tim pengembang Anda? Administrator? Setiap klien sendiri? Atau pengembang pemeliharaan untuk kode klien? Jadi seberapa mudah / kuat / tidak mudah mekanik perlu?
Dev untuk pengujian. Administrator sebagai perubahan dependensi perangkat keras eksternal. Perlu mudah untuk menguji dan mengonfigurasi.
Tujuan kami adalah untuk menunjukkan bahwa sistem dapat dibuat kembali dengan cepat dan dimodernisasi.
kasus penggunaan aktual untuk sakelar implementasi?
Salah satunya adalah, beberapa data akan disediakan oleh perangkat lunak sampai solusi perangkat keras siap.
sumber
Jawaban:
Yah, saya tidak yakin saya memahami detail teknis dan perbedaan yang tepat dari solusi yang didukung sepenuhnya, tetapi IMHO Anda harus terlebih dahulu mencari tahu jenis fleksibilitas yang Anda butuhkan.
Pertanyaan yang harus Anda tanyakan pada diri sendiri adalah:
apakah Anda benar-benar membutuhkan kemungkinan untuk mengkonfigurasi antar implementasi yang berbeda? Untuk tujuan apa?
apakah Anda memerlukan mekanik waktu berjalan, atau hanya kompilasi waktu mekanik untuk beralih di antara implementasi yang berbeda? Mengapa?
granularity mana yang Anda perlukan untuk beralih antar implementasi? Semua sekaligus? Per modul (masing-masing berisi sekelompok kelas)? Per kelas?
siapa yang perlu mengendalikan sakelar? Hanya tim pengembang Anda? Administrator? Setiap klien sendiri? Atau pengembang pemeliharaan untuk kode klien? Jadi seberapa mudah / kuat / tidak mudah mekanik perlu?
Dengan memikirkan jawaban atas pertanyaan-pertanyaan ini, pilih solusi paling sederhana yang dapat Anda pikirkan yang memberikan Anda fleksibilitas yang dibutuhkan. Jangan menerapkan fleksibilitas apa pun yang Anda tidak yakin tentang "berjaga-jaga" jika itu berarti upaya tambahan.
Sebagai jawaban atas jawaban Anda: jika Anda memiliki setidaknya satu kasing nyata , gunakan kasing untuk memvalidasi keputusan desain Anda. Gunakan kasing itu untuk mencari tahu solusi apa yang paling cocok untuk Anda. Coba saja jika "pabrik" atau "pelacak layanan" memberi Anda apa yang Anda butuhkan, atau jika Anda membutuhkan sesuatu yang lain. Jika Anda berpikir kedua solusi sama-sama baik untuk kasus Anda, lempar dadu.
sumber
Hanya untuk memastikan saya mendapatkan ini dengan benar. Anda memiliki beberapa layanan yang dibuat dari beberapa kelas, misalnya
C1,...,Cn
dan sekelompok klien yang langsung meneleponnew Ci(...)
. Jadi saya pikir saya setuju dengan struktur umum dari solusi Anda yaitu membuat layanan internal baru dengan beberapa kelas baruD1,...,Dn
yang bagus dan modern dan menyuntikkan dependensi mereka (memungkinkan dependensi tersebut melalui stack) dan kemudian menulis ulangCi
untuk melakukan apa-apa selain instantiate dan pindah keDi
. Pertanyaannya adalah bagaimana melakukannya dan Anda menyarankan beberapa cara masuk2
dan3
.Untuk memberikan saran serupa ke
2
. Anda dapat menggunakan injeksi dependensi di seluruhDi
dan secara internal dan kemudian membuat akar komposisi normalR
(menggunakan kerangka kerja jika Anda menganggapnya sesuai) yang bertanggung jawab untuk menyusun objek grafik. Dorong diR
belakang pabrik statis dan biarkan masing-masingCi
menyelesaikannyaDi
. Jadi misalnya Anda mungkin punyaPada dasarnya ini adalah solusi Anda 2, tetapi mengumpulkan semua pabrik Anda ke satu lokasi bersama dengan sisa injeksi ketergantungan.
sumber
getInstance()
?Mulailah dengan implementasi sederhana, tidak mewah, dan tunggal.
Jika nanti Anda perlu membuat implementasi tambahan, itu adalah pertanyaan kapan keputusan implementasi terjadi.
Jika Anda membutuhkan fleksibilitas "waktu pemasangan" (setiap instalasi klien menggunakan implementasi statis tunggal), Anda masih tidak perlu melakukan hal-hal lain. Anda hanya menawarkan DLL atau SO yang berbeda (atau apa pun format lib Anda). Klien hanya perlu meletakkan yang benar di
lib
folder ...Jika Anda membutuhkan fleksibilitas runtime, Anda hanya perlu adaptor tipis dan mekanisme pemilih implementasi. Apakah Anda menggunakan pabrik, pelacak, atau wadah IoC sebagian besar dapat diperdebatkan. Satu-satunya perbedaan signifikan antara adaptor dan pelacak adalah A) Penamaan dan B) Apakah objek yang dikembalikan adalah singleton atau instance khusus. Dan perbedaan besar antara wadah IoC dengan pabrik / pelacak adalah siapa yang memanggil siapa . (Seringkali masalah preferensi pribadi.)
sumber