Saya baru mengenal injeksi ketergantungan dan saya memiliki beberapa pertanyaan tentang gaya apa yang harus saya gunakan dalam aplikasi saya. Saya baru saja membaca Inversion of Control Containers dan pola Dependency Injection oleh Martin Fowler, tetapi saya tidak bisa mendapatkan perbedaan praktis antara konstruktor, setter, dan injeksi antarmuka.
Sepertinya saya bahwa alasan untuk menggunakan satu di atas yang lain hanya masalah pembersihan kode dan / atau kejelasan. Apa bedanya? Apakah ada kelebihan atau kekurangan yang kuat untuk menggunakan salah satu dari yang lain, atau hanya seperti yang saya katakan sebelumnya?
Menurut pendapat saya, injeksi konstruktor adalah yang paling intuitif dari semua, serta injeksi antarmuka adalah yang paling sedikit. Di sisi lain, setter injection adalah istilah jangka menengah, tetapi, apakah Anda seharusnya bisa mengubah instance objek dependensi yang awalnya Anda injeksi? Apakah gaya injeksi ini menjamin bahwa objek yang membutuhkan ketergantungan akan selalu disuntikkan? Saya tidak percaya, tapi tolong perbaiki saya jika saya salah.
Jawaban:
Injeksi Konstruktor memiliki keunggulan yang menjadikan ketergantungan eksplisit dan memaksa klien untuk memberikan contoh. Itu juga dapat menjamin bahwa klien tidak dapat mengubah instance nanti. Satu kelemahan (kemungkinan) adalah Anda harus menambahkan parameter ke konstruktor.
Setter Injection memiliki keunggulan karena tidak perlu menambahkan parameter ke konstruktor. Itu juga tidak mengharuskan klien untuk mengatur instance. Ini berguna untuk dependensi opsional. Ini mungkin juga berguna jika Anda ingin kelas untuk membuat, misalnya, repositori data nyata secara default, dan kemudian dalam tes Anda bisa menggunakan setter untuk menggantinya dengan contoh pengujian.
Antarmuka Injeksi , sejauh yang saya tahu, tidak jauh berbeda dari injeksi setter. Dalam kedua kasus Anda (opsional) menetapkan ketergantungan yang dapat diubah nanti.
Pada akhirnya ini adalah masalah preferensi dan apakah ketergantungan diperlukan atau tidak . Secara pribadi, saya menggunakan injeksi konstruktor hampir secara eksklusif. Saya suka itu membuat dependensi kelas eksplisit dengan memaksa klien untuk memberikan contoh di konstruktor. Saya juga suka bahwa klien tidak dapat mengubah instance setelah fakta.
Sering kali, satu-satunya alasan saya untuk melewati dua implementasi terpisah adalah untuk pengujian. Dalam produksi, saya dapat lulus dalam
DataRepository
, tetapi dalam pengujian, saya akan lulus dalam aFakeDataRepository
. Dalam hal ini saya biasanya akan memberikan dua konstruktor: satu tanpa parameter, dan lainnya yang menerima aIDataRepository
. Kemudian, di dalam konstruktor tanpa parameter, saya akan membuat panggilan ke konstruktor kedua dan meneruskan anew DataRepository()
.Berikut ini contoh dalam C #:
Ini dikenal sebagai Injeksi Ketergantungan Orang Miskin. Saya suka karena dalam kode klien produksi, saya tidak perlu mengulangi diri saya dengan memiliki beberapa pernyataan berulang yang terlihat seperti
Namun, saya masih bisa meneruskan implementasi alternatif untuk pengujian. Saya menyadari bahwa dengan DIA Poor Man, saya membuat hardcoding ketergantungan saya, tetapi itu dapat diterima bagi saya karena saya kebanyakan menggunakan DI untuk pengujian.sumber
Perbedaan antara konstruktor dan injeksi setter sudah dijelaskan di atas, jadi saya tidak akan menguraikan lebih lanjut tentang mereka.
Antarmuka injeksi adalah bentuk injeksi yang lebih maju yang berguna karena memungkinkan ketergantungan untuk diputuskan pada saat digunakan daripada selama inisialisasi objek yang akan menggunakannya. Ini memungkinkan sejumlah opsi berguna:
Ketergantungan dapat dicakup secara berbeda dengan objek yang disuntikkan; misalnya Anda dapat menggunakan injeksi antarmuka untuk memberikan objek yang ada satu per sesi pengguna atau per utas ke singleton global. Setiap kali objek membutuhkan dependensi, ia akan memanggil metode pengambil yang disediakan oleh framework, dan ini dapat mengembalikan hasil yang berbeda tergantung pada situasi di mana ia dipanggil.
Ini memungkinkan inisialisasi malas - tidak perlu ketergantungan diinisialisasi sampai akan digunakan
Ini memungkinkan dependensi untuk dimuat dari salinan cache ketika mereka ada atau diinisialisasi ulang ketika mereka tidak (misalnya menggunakan
SoftReference
di Jawa).Jelas teknik-teknik canggih seperti ini memiliki kelemahan; dalam hal ini, masalah utama adalah kode menjadi kurang jelas (kelas yang digunakan dalam kode Anda menjadi abstrak, dan tidak ada implementasi nyata yang jelas, yang dapat membingungkan jika Anda tidak terbiasa) dan Anda menjadi lebih tergantung pada kerangka injeksi ketergantungan Anda (tentu saja masih memungkinkan untuk membuat objek Anda secara manual, tetapi lebih sulit daripada dengan gaya injeksi lainnya).
sumber