Ada perdebatan lama yang terus-menerus tentang cara terbaik untuk melakukan injeksi ketergantungan.
Potongan asli pegas yang dipakai objek polos, dan kemudian menyuntikkan dependensi melalui metode setter.
Tetapi kemudian sejumlah besar orang bersikeras bahwa menyuntikkan dependensi melalui parameter konstruktor adalah cara yang tepat untuk melakukannya.
Kemudian, akhir-akhir ini, ketika menggunakan refleksi menjadi lebih umum, menetapkan nilai-nilai anggota pribadi secara langsung, tanpa argumen setters, menjadi kemarahan.
Jadi konstruktor pertama Anda konsisten dengan pendekatan kedua untuk injeksi ketergantungan. Hal ini memungkinkan Anda untuk melakukan hal-hal bagus seperti menyuntikkan mock untuk pengujian.
Tetapi konstruktor no-argumen memiliki masalah ini. Karena ini adalah instantiate kelas implementasi untuk PaypalCreditCardProcessor
dan DatabaseTransactionLog
, itu menciptakan ketergantungan, waktu kompilasi yang sulit pada PayPal dan Database. Dibutuhkan tanggung jawab untuk membangun dan mengonfigurasi seluruh pohon dependensi dengan benar.
Bayangkan bahwa prosesor PayPay adalah subsistem yang sangat rumit, dan juga menarik banyak perpustakaan pendukung. Dengan membuat ketergantungan waktu kompilasi pada kelas implementasi itu, Anda membuat tautan yang tidak bisa dipecahkan ke seluruh pohon dependensi itu. Kompleksitas grafik objek Anda baru saja melonjak dengan urutan besarnya, mungkin dua.
Banyak dari item-item di pohon dependensi akan transparan, tetapi banyak dari mereka juga perlu instantiated. Kemungkinannya adalah, Anda tidak akan bisa hanya instantiate a PaypalCreditCardProcessor
.
Selain instantiasi, masing-masing objek akan membutuhkan properti yang diterapkan dari konfigurasi.
Jika Anda hanya memiliki ketergantungan pada antarmuka, dan memungkinkan pabrik eksternal untuk membangun dan menyuntikkan dependensi, mereka yang Anda potong seluruh pohon ketergantungan PayPal, dan kompleksitas kode Anda berhenti di antarmuka.
Ada manfaat lain, seperti untuk menentukan kelas implementasi di dalam konfigurasi (yaitu pada saat runtime daripada waktu kompilasi), atau memiliki spesifikasi ketergantungan yang lebih dinamis yang bervariasi, misalnya, berdasarkan lingkungan (pengujian, integrasi, produksi).
Misalnya, katakanlah bahwa Prosesor PayPal memiliki 3 objek dependen, dan masing-masing dependensi tersebut memiliki dua objek lagi. Dan semua objek tersebut harus menarik properti dari konfigurasi. Kode apa adanya akan memikul tanggung jawab untuk membangun semua itu, mengatur properti dari konfigurasi, dll. - semua masalah yang akan ditangani oleh kerangka kerja DI.
Pada awalnya mungkin tidak terlihat jelas apa yang Anda lindungi dengan menggunakan kerangka kerja DI, tetapi hal itu bertambah dan menjadi sangat jelas dari waktu ke waktu. (lol Saya berbicara dari pengalaman setelah mencoba melakukannya dengan cara yang sulit)
...
Dalam prakteknya, bahkan untuk program yang sangat kecil, saya menemukan saya akhirnya menulis dengan gaya DI, dan memecah kelas menjadi pasangan implementasi / pabrik. Artinya, jika saya tidak menggunakan kerangka kerja DI seperti Spring, saya hanya mengumpulkan beberapa kelas pabrik sederhana.
Itu memberikan pemisahan keprihatinan sehingga kelas saya bisa melakukan hal itu, dan kelas pabrik mengambil tanggung jawab untuk membangun & mengonfigurasi hal-hal.
Bukan pendekatan yang diperlukan, tetapi FWIW
...
Secara umum, pola DI / antarmuka mengurangi kompleksitas kode Anda dengan melakukan dua hal:
Selain itu, karena instantiasi dan konfigurasi objek adalah tugas yang cukup akrab, kerangka kerja DI dapat mencapai banyak skala ekonomis melalui notasi standar & menggunakan trik seperti refleksi. Menyebarkan kekhawatiran yang sama di sekitar kelas akhirnya menambah lebih banyak kekacauan daripada yang dipikirkan orang.