Ada beberapa pertanyaan yang sudah diposting dengan pertanyaan spesifik tentang injeksi ketergantungan , seperti kapan menggunakannya dan kerangka apa yang ada untuk itu. Namun,
Apa itu injeksi ketergantungan dan kapan / mengapa harus atau tidak harus digunakan?
Jawaban:
Dependency Injection adalah meneruskan ketergantungan pada objek atau kerangka kerja lain (dependency injector).
Ketergantungan injeksi membuat pengujian lebih mudah. Injeksi dapat dilakukan melalui konstruktor .
SomeClass()
memiliki konstruktor sebagai berikut:Masalah : Jika
myObject
melibatkan tugas kompleks seperti akses disk atau akses jaringan, sulit untuk melakukan pengujian unitSomeClass()
. Pemrogram harus mengejekmyObject
dan mungkin mencegat panggilan pabrik.Solusi alternatif :
myObject
sebagai argumen ke konstruktormyObject
dapat dilewati secara langsung yang membuat pengujian lebih mudah.Lebih sulit untuk mengisolasi komponen dalam pengujian unit tanpa injeksi ketergantungan.
Pada 2013, ketika saya menulis jawaban ini, ini adalah tema utama di Google Testing Blog . Ini tetap menjadi keuntungan terbesar bagi saya, karena programmer tidak selalu membutuhkan fleksibilitas ekstra dalam desain run-time mereka (misalnya, untuk pencari lokasi atau pola serupa). Pemrogram sering perlu mengisolasi kelas selama pengujian.
sumber
Definisi terbaik yang saya temukan sejauh ini adalah satu oleh James Shore :
Ada sebuah artikel oleh Martin Fowler yang mungkin terbukti bermanfaat juga.
Ketergantungan injeksi pada dasarnya menyediakan objek yang dibutuhkan suatu objek (dependensinya) alih-alih membuatnya membangunnya sendiri. Ini adalah teknik yang sangat berguna untuk pengujian, karena memungkinkan dependensi untuk dipermainkan atau dihilangkan.
Ketergantungan dapat disuntikkan ke objek dengan banyak cara (seperti injeksi konstruktor atau injeksi setter). Satu bahkan dapat menggunakan kerangka kerja injeksi ketergantungan khusus (misalnya Spring) untuk melakukan itu, tetapi mereka tentu tidak diperlukan. Anda tidak perlu kerangka kerja itu untuk memiliki injeksi ketergantungan. Instantiating dan meneruskan objek (dependensi) secara eksplisit sama baiknya dengan injeksi oleh kerangka kerja.
sumber
Saya menemukan contoh lucu ini dalam hal kopling longgar :
Aplikasi apa pun terdiri dari banyak objek yang saling berkolaborasi untuk melakukan beberapa hal berguna. Secara tradisional setiap objek bertanggung jawab untuk mendapatkan referensi sendiri ke objek dependen (dependensi) yang dikolaborasikan dengannya. Ini mengarah ke kelas yang sangat berpasangan dan kode yang sulit untuk diuji.
Sebagai contoh, pertimbangkan
Car
objek.A
Car
tergantung pada roda, mesin, bahan bakar, baterai, dll untuk menjalankan. Secara tradisional kita mendefinisikan merek dari objek dependen tersebut bersama dengan definisiCar
objek.Tanpa Injeksi Ketergantungan (DI):
Di sini,
Car
objek bertanggung jawab untuk membuat objek dependen.Bagaimana jika kita ingin mengubah jenis objek dependennya - katakan
Wheel
- setelahNepaliRubberWheel()
tusukan awal ? Kita perlu membuat ulang objek Mobil dengan ketergantungan baruChineseRubberWheel()
, tetapi hanyaCar
pabrikan yang bisa melakukannya.Lalu apa gunanya
Dependency Injection
bagi kita ...?Saat menggunakan injeksi dependensi, objek diberi dependensinya pada waktu berjalan daripada waktu kompilasi (waktu pembuatan mobil) . Sehingga kita sekarang dapat mengubah
Wheel
kapan saja kita mau. Di sini,dependency
(wheel
) dapat disuntikkan keCar
dalam waktu berjalan.Setelah menggunakan injeksi ketergantungan:
Di sini, kita suntik yang dependensi (roda dan Battery) pada saat runtime. Karena itu istilahnya: Injeksi Ketergantungan.
Sumber: Memahami injeksi ketergantungan
sumber
new
sebuah ban? Bukan saya. Yang harus saya lakukan adalah membeli (menyuntikkan melalui param) dari mereka, menginstal dan wah-lah! Jadi, kembali ke pemrograman, katakanlah proyek C # perlu menggunakan perpustakaan / kelas yang ada, ada dua cara untuk menjalankan / men-debug, 1-tambah referensi ke seluruh proyek ininew
itu, opsi 2 meneruskannya sebagai param. Mungkin tidak akurat, tapi bodoh sederhana mudah dimengerti.Dependency Injection adalah praktik di mana objek dirancang dengan cara di mana mereka menerima instance objek dari potongan kode lain, alih-alih membangunnya secara internal. Ini berarti bahwa objek apa pun yang mengimplementasikan antarmuka yang diperlukan oleh objek dapat diganti tanpa mengubah kode, yang menyederhanakan pengujian, dan meningkatkan decoupling.
Sebagai contoh, pertimbangkan klausa ini:
Dalam contoh ini, implementasi
PersonService::addManager
danPersonService::removeManager
akan membutuhkan instanceGroupMembershipService
untuk dapat melakukan tugasnya. Tanpa Injeksi Ketergantungan, cara tradisional untuk melakukan ini adalah dengan instantiate yang baruGroupMembershipService
di konstruktorPersonService
dan menggunakan atribut instance di kedua fungsi. Namun, jika konstruktorGroupMembershipService
memiliki banyak hal yang diperlukan, atau lebih buruk lagi, ada beberapa "setter" inisialisasi yang perlu dipanggilGroupMembershipService
, kode tumbuh agak cepat, danPersonService
sekarang tergantung tidak hanya padaGroupMembershipService
tetapi juga segala sesuatuGroupMembershipService
tergantung pada. Selain itu, tautan keGroupMembershipService
hardcoded ke dalamPersonService
yang berarti Anda tidak dapat "dummy"GroupMembershipService
untuk tujuan pengujian, atau untuk menggunakan pola strategi di berbagai bagian aplikasi Anda.Dengan Dependency Injection, alih-alih membuat instance di
GroupMembershipService
dalam AndaPersonService
, Anda akan meneruskannya kePersonService
konstruktor, atau menambahkan Properti (pengambil dan penyetel) untuk menetapkan contoh lokal dari itu. Ini berarti bahwa AndaPersonService
tidak perlu lagi khawatir tentang cara membuatGroupMembershipService
, itu hanya menerima yang diberikan, dan bekerja dengan mereka. Ini juga berarti bahwa apa pun yang merupakan subkelas dariGroupMembershipService
, atau mengimplementasikanGroupMembershipService
antarmuka dapat "disuntikkan" kePersonService
, danPersonService
tidak perlu tahu tentang perubahan itu.sumber
Jawaban yang diterima adalah jawaban yang bagus - tetapi saya ingin menambahkan bahwa DI sangat mirip dengan klasik yang menghindari konstanta hardcode dalam kode.
Ketika Anda menggunakan konstanta seperti nama basis data, Anda akan dengan cepat memindahkannya dari bagian dalam kode ke beberapa file konfigurasi dan meneruskan variabel yang berisi nilai tersebut ke tempat yang diperlukan. Alasan untuk melakukan itu adalah bahwa konstanta ini biasanya berubah lebih sering daripada sisa kode. Misalnya jika Anda ingin menguji kode dalam database pengujian.
DI analog dengan ini dalam dunia pemrograman Berorientasi Objek. Nilai-nilai di sana alih-alih literal konstan adalah objek keseluruhan - tetapi alasan untuk memindahkan kode yang membuatnya dari kode kelas serupa - objek lebih sering berubah daripada kode yang menggunakannya. Satu kasus penting di mana perubahan semacam itu diperlukan adalah tes.
sumber
Mari kita coba contoh sederhana dengan kelas Mobil dan Mesin , setiap mobil membutuhkan mesin untuk pergi ke mana pun, setidaknya untuk saat ini. Jadi di bawah ini bagaimana kode akan terlihat tanpa injeksi ketergantungan.
Dan untuk membuat instance kelas Mobil kita akan menggunakan kode berikutnya:
Masalah dengan kode ini yang kami gabungkan dengan erat ke GasEngine dan jika kami memutuskan untuk mengubahnya ke ElectricityEngine maka kami perlu menulis ulang kelas Car. Dan semakin besar aplikasinya, semakin banyak masalah dan sakit kepala yang harus kita tambahkan dan gunakan jenis mesin baru.
Dengan kata lain dengan pendekatan ini adalah bahwa kelas mobil tingkat tinggi kami bergantung pada kelas GasEngine tingkat rendah yang melanggar Prinsip Ketergantungan Inversi (DIP) dari SOLID. DIP menyarankan bahwa kita harus bergantung pada abstraksi, bukan kelas yang konkret. Jadi untuk memuaskan ini kami memperkenalkan antarmuka IEngine dan menulis ulang kode seperti di bawah ini:
Sekarang kelas Mobil kami hanya bergantung pada antarmuka IEngine, bukan implementasi mesin yang spesifik. Sekarang, satu-satunya trik adalah bagaimana kita membuat turunan dari Mobil dan memberikan kelas Mesin beton yang sebenarnya seperti GasEngine atau ElectricityEngine. Di situlah Dependency Injection masuk.
Di sini kita pada dasarnya menyuntikkan (meneruskan) ketergantungan kita (contoh mesin) ke konstruktor Mobil. Jadi sekarang kelas kami memiliki kopling longgar antara objek dan dependensinya, dan kami dapat dengan mudah menambahkan jenis mesin baru tanpa mengubah kelas Mobil.
Manfaat utama Injeksi Ketergantungan bahwa kelas lebih longgar digabungkan, karena mereka tidak memiliki dependensi hard-coded. Ini mengikuti Prinsip Ketergantungan Inversi, yang disebutkan di atas. Alih-alih merujuk implementasi spesifik, kelas meminta abstraksi (biasanya antarmuka ) yang diberikan kepada mereka ketika kelas dibangun.
Juga ketika kita memiliki banyak dependensi, adalah praktik yang sangat baik untuk menggunakan wadah Inversion of Control (IoC) yang dapat kita beri tahu antarmuka mana yang harus dipetakan ke implementasi konkret mana untuk semua dependensi kita dan kita dapat memilikinya menyelesaikan dependensi tersebut untuk kita ketika ia membangun objek kita. Sebagai contoh, kita dapat menentukan dalam pemetaan untuk wadah IoC bahwa ketergantungan IEngine harus dipetakan ke kelas GasEngine dan ketika kita bertanya wadah IoC untuk instance dari kelas Mobil kami , itu akan secara otomatis membangun kelas Mobil kami dengan ketergantungan GasEngine lewat.
UPDATE: Menonton kursus tentang EF Core dari Julie Lerman baru-baru ini dan juga menyukai definisi singkatnya tentang DI.
sumber
Bayangkan Anda ingin memancing:
Tanpa injeksi ketergantungan, Anda perlu mengurus semuanya sendiri. Anda perlu menemukan perahu, membeli pancing, mencari umpan, dll. Itu mungkin, tentu saja, tetapi menempatkan banyak tanggung jawab pada Anda. Dalam istilah perangkat lunak, itu berarti Anda harus melakukan pencarian untuk semua hal ini.
Dengan injeksi ketergantungan, orang lain mengurus semua persiapan dan membuat peralatan yang diperlukan tersedia untuk Anda. Anda akan menerima ("disuntikkan") perahu, pancing, dan umpan - semuanya siap digunakan.
sumber
Ini adalah penjelasan paling sederhana tentang Dependency Injection dan Dependency Injection Container yang pernah saya lihat:
Tanpa Injeksi Ketergantungan
Dengan Injeksi Ketergantungan
Menggunakan Wadah Injeksi Ketergantungan
Ketergantungan Injeksi dan ketergantungan Injeksi Kontainer adalah hal yang berbeda:
Anda tidak perlu wadah untuk melakukan injeksi ketergantungan. Namun sebuah wadah dapat membantu Anda.
sumber
Bukankah "injeksi ketergantungan" hanya berarti menggunakan konstruktor berparameter dan setter publik?
Artikel James Shore menunjukkan contoh-contoh berikut untuk perbandingan .
sumber
new DatabaseThingie()
tidak menghasilkan instance myDatabase yang valid.Untuk membuat konsep Ketergantungan Injeksi mudah dipahami. Mari kita ambil contoh tombol sakelar untuk menghidupkan (mematikan / mematikan) bohlam.
Tanpa Injeksi Ketergantungan
Switch perlu tahu sebelumnya bohlam mana saya terhubung (ketergantungan kode keras). Begitu,
Switch -> PermanentBulb // switch terhubung langsung ke bulb permanen, pengujian tidak mungkin dengan mudah
Dengan Injeksi Ketergantungan
Switch hanya tahu saya harus menghidupkan / mematikan Bulb mana pun yang diberikan kepada saya. Begitu,
Beralih -> Bulb1 ATAU Bulb2 ATAU NightBulb (ketergantungan disuntikkan)
Mengubah Contoh James untuk Switch dan Bulb:
sumber
Apa itu Dependency Injection (DI)?
Seperti yang orang lain katakan, Dependency Injection (DI) menghilangkan tanggung jawab penciptaan langsung, dan manajemen masa hidup, dari instance objek lain yang menjadi dasar ketergantungan kelas kelas kami (kelas konsumen) (dalam arti UML ). Contoh-contoh ini bukannya diteruskan ke kelas konsumen kami, biasanya sebagai parameter konstruktor atau melalui setter properti (pengelolaan objek dependensi yang mem-instans dan meneruskan ke kelas konsumen biasanya dilakukan oleh Inversion of Control (IoC) , tapi itu topik lain) .
DI, DIP dan SOLID
Secara khusus, dalam paradigma prinsip SOLID Obyek Berorientasi Desain Robert C Martin ,
DI
adalah salah satu implementasi yang mungkin dari Dependency Inversion Principle (DIP) . The DIP adalahD
dariSOLID
mantra - implementasi DIP lainnya meliputi Jasa Locator, dan pola Plugin.Tujuan dari DIP adalah untuk memisahkan ketergantungan yang kuat dan konkret antar kelas, dan sebagai gantinya, melonggarkan kopling melalui abstraksi, yang dapat dicapai melalui
interface
,abstract class
ataupure virtual class
, tergantung pada bahasa dan pendekatan yang digunakan.Tanpa DIP, kode kami (saya menyebutnya 'kelas konsumsi') secara langsung digabungkan ke ketergantungan konkret dan juga sering dibebani dengan tanggung jawab untuk mengetahui cara mendapatkan, dan mengelola, contoh ketergantungan ini, yaitu secara konseptual:
Sedangkan setelah penerapan DIP, persyaratan dilonggarkan, dan kekhawatiran untuk mendapatkan dan mengelola umur
Foo
ketergantungan telah dihapus:Mengapa menggunakan DIP (dan DI)?
Decoupling dependensi antara kelas-kelas dengan cara ini memungkinkan substitusi yang mudah dari kelas-kelas dependensi ini dengan implementasi lain yang juga memenuhi prasyarat dari abstraksi (misalnya ketergantungan dapat diubah dengan implementasi lain dari antarmuka yang sama). Selain itu, yang lain telah disebutkan, mungkin yang alasan yang paling umum untuk kelas decouple melalui DIP adalah untuk memungkinkan kelas mengkonsumsi untuk diuji dalam isolasi, karena ini dependensi yang sama sekarang dapat mematikan dan / atau mengejek.
Salah satu konsekuensi dari DI adalah manajemen umur instance objek dependensi tidak lagi dikendalikan oleh kelas konsumsi, karena objek dependensi kini diteruskan ke kelas konsumsi (melalui konstruktor atau injeksi setter).
Ini dapat dilihat dengan berbagai cara:
Create
pada pabrik sesuai kebutuhan, dan membuang mesin virtual tersebut setelah selesai.Kapan harus menggunakan DI?
MyDepClass
apakah thread aman - bagaimana jika kita menjadikannya tunggal dan menyuntikkan contoh yang sama ke semua konsumen?)Contoh
Berikut ini adalah implementasi C # yang sederhana. Diberikan kelas Konsumsi di bawah ini:
Meskipun tampaknya tidak berbahaya, ia memiliki dua
static
dependensi pada dua kelas lain,System.DateTime
danSystem.Console
, yang tidak hanya membatasi opsi keluaran logging (masuk ke konsol tidak akan bernilai jika tidak ada yang menonton), tetapi lebih buruk lagi, sulit untuk secara otomatis menguji mengingat ketergantungan pada jam sistem non-deterministik.Namun kita dapat menerapkan
DIP
ke kelas ini, dengan mengabstraksi keprihatinan timestamping sebagai ketergantungan, danMyLogger
hanya menyambung ke antarmuka sederhana:Kami juga dapat melonggarkan ketergantungan pada
Console
abstraksi, seperti aTextWriter
. Dependency Injection biasanya diimplementasikan sebagaiconstructor
injeksi (meneruskan abstraksi ke dependensi sebagai parameter ke konstruktor dari kelas konsumsi) atauSetter Injection
(melewati ketergantungan melaluisetXyz()
setter atau .Net Properti dengan yang{set;}
ditentukan). Injeksi Konstruktor lebih disukai, karena ini menjamin kelas akan berada dalam keadaan yang benar setelah konstruksi, dan memungkinkan bidang dependensi internal ditandai sebagaireadonly
(C #) ataufinal
(Jawa). Jadi menggunakan injeksi konstruktor pada contoh di atas, ini memberi kita:(Beton
Clock
perlu disediakan, yang tentu saja dapat dikembalikanDateTime.Now
, dan dua dependensi perlu disediakan oleh wadah IoC melalui injeksi konstruktor)Unit Test otomatis dapat dibangun, yang secara definitif membuktikan bahwa logger kami berfungsi dengan benar, karena kami sekarang memiliki kendali atas dependensi - waktu, dan kami dapat memata-matai hasil tertulis:
Langkah selanjutnya
Injeksi ketergantungan selalu terkait dengan wadah Inversion of Control (IoC) , untuk menyuntikkan (menyediakan) contoh ketergantungan beton, dan untuk mengelola contoh umur pakai. Selama proses konfigurasi / bootstrap,
IoC
wadah memungkinkan yang berikut ini untuk didefinisikan:IBar
, kembalikanConcreteBar
contoh" )IDisposable
dan akan mengambil tanggung jawabDisposing
dependensi sejalan dengan manajemen masa pakai yang dikonfigurasi.Biasanya, begitu wadah IoC telah dikonfigurasi / bootstrap, mereka beroperasi dengan mulus di latar belakang yang memungkinkan koder untuk fokus pada kode yang ada daripada khawatir tentang ketergantungan.
Seperti contoh di atas, decoupling of dependency memang memerlukan beberapa upaya desain, dan bagi pengembang, ada perubahan paradigma yang diperlukan untuk menghentikan kebiasaan
new
ketergantungan secara langsung, dan sebaliknya mempercayai wadah untuk mengelola dependensi.Tetapi manfaatnya banyak, terutama dalam kemampuan untuk menguji kelas minat Anda secara menyeluruh.
Catatan : Pembuatan / pemetaan / proyeksi (via
new ..()
) POCO / POJO / Serialisasi DTO / Grafik Entitas / Proyeksi JSON anonim dkk - yaitu kelas atau catatan "Hanya data" - digunakan atau dikembalikan dari metode tidak dianggap sebagai Dependensi (dalam UML sense) dan tidak tunduk pada DI. Menggunakannew
untuk memproyeksikan ini baik-baik saja.sumber
Inti dari Dependency Injection (DI) adalah menjaga kode sumber aplikasi tetap bersih dan stabil :
Secara praktis, setiap pola desain memisahkan masalah untuk membuat perubahan di masa depan memengaruhi file minimum.
Domain spesifik DI adalah pendelegasian konfigurasi dependensi dan inisialisasi.
Contoh: DI dengan skrip shell
Jika Anda sesekali bekerja di luar Jawa, ingat bagaimana
source
sering digunakan dalam banyak bahasa skrip (Shell, Tcl, dll., Atau bahkanimport
dalam Python disalahgunakan untuk tujuan ini).Pertimbangkan
dependent.sh
skrip sederhana :Skrip tergantung: skrip tidak akan berhasil dijalankan dengan sendirinya (
archive_files
tidak ditentukan).Anda mendefinisikan
archive_files
dalamarchive_files_zip.sh
skrip implementasi (menggunakanzip
dalam kasus ini):Alih-alih
source
menjalankan skrip implementasi di dependen, Anda menggunakaninjector.sh
"wadah" yang membungkus kedua "komponen":The
archive_files
ketergantungan baru saja disuntikkan ke dalam tergantung skrip.Anda bisa menyuntikkan ketergantungan yang mengimplementasikan
archive_files
menggunakantar
atauxz
.Contoh: menghapus DI
Jika
dependent.sh
skrip menggunakan dependensi secara langsung, pendekatan akan disebut dependensi lookup (yang berlawanan dengan injeksi dependensi ):Sekarang masalahnya adalah "komponen" yang tergantung harus melakukan inisialisasi sendiri.
Kode sumber "komponen" tidak bersih atau stabil karena setiap perubahan inisialisasi dependensi memerlukan rilis baru untuk file kode sumber "komponen" juga.
Kata-kata terakhir
DI tidak begitu ditekankan dan dipopulerkan seperti dalam kerangka kerja Jawa.
Tapi ini adalah pendekatan umum untuk membagi kekhawatiran:
Menggunakan konfigurasi saja dengan pencarian dependensi tidak membantu karena jumlah parameter konfigurasi dapat berubah per dependensi (mis. Tipe otentikasi baru) serta jumlah tipe dependensi yang didukung (mis. Tipe database baru).
sumber
Semua jawaban di atas baik, tujuan saya adalah untuk menjelaskan konsep dengan cara yang sederhana sehingga siapa pun tanpa pengetahuan pemrograman juga dapat memahami konsep
Injeksi ketergantungan adalah salah satu pola desain yang membantu kita menciptakan sistem yang kompleks dengan cara yang lebih sederhana.
Kita dapat melihat beragam penerapan pola ini dalam kehidupan kita sehari-hari. Beberapa contohnya adalah Tape recorder, VCD, CD Drive dll.
Gambar di atas adalah gambar dari tape recorder portabel Reel-to-reel, pertengahan abad ke-20. Sumber .
Tujuan utama dari mesin perekam adalah untuk merekam atau memutar suara.
Saat mendesain sistem, diperlukan gulungan untuk merekam atau memutar suara atau musik. Ada dua kemungkinan untuk merancang sistem ini
Jika kita menggunakan yang pertama, kita perlu membuka mesin untuk mengubah gulungan. jika kita memilih yang kedua, yaitu memasang hook untuk reel, kita mendapatkan keuntungan tambahan dari memainkan musik apa pun dengan mengubah reel. dan juga mengurangi fungsi hanya untuk memainkan apapun dalam reel.
Seperti injeksi dependensi yang bijaksana adalah proses mengeksternalisasi dependensi untuk fokus hanya pada fungsionalitas spesifik komponen sehingga komponen independen dapat digabungkan bersama untuk membentuk sistem yang kompleks.
Manfaat utama yang kami raih dengan menggunakan injeksi ketergantungan.
Sekarang suatu hari konsep ini membentuk dasar dari kerangka kerja yang terkenal di dunia pemrograman. Spring Angular dll adalah kerangka kerja perangkat lunak terkenal yang dibangun di atas konsep ini
Dependency injection adalah pola yang digunakan untuk membuat instance objek yang diandalkan objek lain tanpa mengetahui pada waktu kompilasi kelas mana yang akan digunakan untuk menyediakan fungsionalitas itu atau sekadar cara menyuntikkan properti ke objek yang disebut dependensi injeksi.
Contoh untuk injeksi Ketergantungan
Sebelumnya kami menulis kode seperti ini
Dengan injeksi Dependency, injector dependensi akan melepas instantiation untuk kita
Anda juga bisa membaca
Perbedaan antara Pembalikan Kontrol & Ketergantungan Injeksi
sumber
Apa itu Injeksi Ketergantungan?
Dependency Injection (DI) artinya memisahkan dua benda yang saling bergantung. Katakanlah objek A bergantung pada Obyek B sehingga idenya adalah untuk memisahkan objek ini dari satu sama lain. Kita tidak perlu membuat hard code objek menggunakan kata kunci baru melainkan berbagi dependensi ke objek pada saat runtime meskipun waktu kompilasi. Jika kita membicarakannya
Cara Kerja Dependency Injection di Spring:
Kita tidak perlu melakukan hard code pada objek menggunakan kata kunci baru melainkan mendefinisikan ketergantungan kacang pada file konfigurasi. Wadah pegas akan bertanggung jawab untuk menghubungkan semua.
Inversion of Control (IOC)
IOC adalah konsep umum dan dapat diekspresikan dengan berbagai cara dan Dependency Injection adalah salah satu contoh nyata IOC.
Dua jenis Injeksi Ketergantungan:
1. Injeksi ketergantungan berbasis konstruktor:
DI berbasis konstruktor dicapai ketika wadah memanggil konstruktor kelas dengan sejumlah argumen, masing-masing mewakili ketergantungan pada kelas lain.
2. Injeksi ketergantungan setter-based:
DI berbasis setter dilakukan oleh kontainer yang memanggil metode setter pada kacang Anda setelah memanggil konstruktor tanpa argumen atau metode pabrik statis tanpa argumen untuk membuat instance kacang Anda.
CATATAN: Ini adalah aturan praktis yang baik untuk menggunakan argumen konstruktor untuk dependensi wajib dan seter untuk dependensi opsional. Perhatikan bahwa jika kita menggunakan anotasi berdasarkan @ annotasi yang dibutuhkan pada setter dapat digunakan untuk menjadikan setter sebagai dependensi yang diperlukan.
sumber
Analogi terbaik yang dapat saya pikirkan adalah ahli bedah dan asistennya di ruang operasi, di mana ahli bedah adalah orang utama dan asistennya yang menyediakan berbagai komponen bedah ketika ia membutuhkannya sehingga ahli bedah dapat berkonsentrasi pada satu hal yang ia lakukan terbaik (operasi). Tanpa asisten ahli bedah harus mendapatkan komponen sendiri setiap kali dia membutuhkannya.
Singkatnya, DI adalah teknik untuk menghilangkan tanggung jawab tambahan umum (beban) pada komponen untuk mengambil komponen dependen, dengan menyediakannya.
DI membawa Anda lebih dekat ke prinsip Tanggung Jawab Tunggal (SR), seperti
surgeon who can concentrate on surgery
.Kapan harus menggunakan DI: Saya akan merekomendasikan menggunakan DI di hampir semua proyek produksi (kecil / besar), terutama di lingkungan bisnis yang selalu berubah :)
Mengapa: Karena Anda ingin kode Anda mudah diuji, dapat dipermainkan dll sehingga Anda dapat dengan cepat menguji perubahan Anda dan mendorongnya ke pasar. Selain itu mengapa Anda tidak ketika Anda memiliki banyak alat / kerangka kerja gratis yang mengagumkan untuk mendukung Anda dalam perjalanan Anda ke basis kode di mana Anda memiliki kontrol lebih.
sumber
Contoh, kami memiliki 2 kelas
Client
danService
.Client
akan menggunakanService
Tanpa Injeksi Ketergantungan
Cara 1)
Jalan 2)
Jalan 3)
1) 2) 3) Menggunakan
Keuntungan
Kekurangan
Client
kelas tesService
konstruktor, kita perlu mengubah kode di semua tempat membuatService
objekGunakan Injeksi Ketergantungan
Cara 1) Injeksi konstruktor
Menggunakan
Cara 2) Setter injection
Menggunakan
Cara 3) Injeksi antarmuka
Periksa https://en.wikipedia.org/wiki/Dependency_injection
===
Sekarang, kode ini sudah mengikuti
Dependency Injection
dan lebih mudah untukClient
kelas uji .Namun, kami masih menggunakan
new Service()
banyak waktu dan itu tidak baik ketika menggantiService
konstruktor. Untuk mencegahnya, kita dapat menggunakan injektor DI seperti1) Manual sederhana
Injector
Menggunakan
2) Gunakan perpustakaan: Untuk Android dagger2
Keuntungan
Service
, Anda hanya perlu mengubahnya di kelas InjectorConstructor Injection
, ketika Anda melihat konstruktorClient
, Anda akan melihat berapa banyak ketergantunganClient
kelasKekurangan
Constructor Injection
,Service
objek dibuat saatClient
dibuat, kadang-kadang kita menggunakan fungsi diClient
kelas tanpa menggunakanService
sehingga dibuatService
terbuang sia-siaDefinisi Injeksi Ketergantungan
https://en.wikipedia.org/wiki/Dependency_injection
sumber
Ini berarti bahwa objek hanya memiliki dependensi sebanyak yang diperlukan untuk melakukan pekerjaannya dan dependensi harus sedikit. Selain itu, dependensi objek harus berada pada antarmuka dan bukan pada objek "konkret", jika memungkinkan. (Objek konkret adalah objek apa pun yang dibuat dengan kata kunci baru.) Kopling longgar mempromosikan penggunaan kembali yang lebih besar, pemeliharaan lebih mudah, dan memungkinkan Anda untuk dengan mudah menyediakan objek "tiruan" di tempat layanan mahal.
"Injeksi Ketergantungan" (DI) juga dikenal sebagai "Inversion of Control" (IoC), dapat digunakan sebagai teknik untuk mendorong sambungan longgar ini.
Ada dua pendekatan utama untuk mengimplementasikan DI:
Injeksi konstruktor
Ini adalah teknik meneruskan ketergantungan objek kepada konstruktornya.
Perhatikan bahwa konstruktor menerima antarmuka dan bukan objek konkret. Juga, perhatikan bahwa pengecualian dilemparkan jika parameter orderDao adalah nol. Ini menekankan pentingnya menerima ketergantungan yang valid. Injeksi Konstruktor adalah, menurut pendapat saya, mekanisme yang disukai untuk memberikan objek ketergantungannya. Jelas bagi pengembang sambil memanggil objek yang dependensi perlu diberikan ke objek "Orang" untuk eksekusi yang tepat.
Setter Injection
Tetapi perhatikan contoh berikut ... Misalkan Anda memiliki kelas dengan sepuluh metode yang tidak memiliki dependensi, tetapi Anda menambahkan metode baru yang memang memiliki ketergantungan pada IDAO. Anda bisa mengubah konstruktor untuk menggunakan Injeksi Konstruktor, tetapi ini mungkin memaksa Anda untuk mengubah semua panggilan konstruktor di semua tempat. Atau, Anda bisa menambahkan konstruktor baru yang menggunakan dependensi, tetapi kemudian bagaimana pengembang dengan mudah tahu kapan harus menggunakan satu konstruktor di atas yang lain. Akhirnya, jika ketergantungan sangat mahal untuk dibuat, mengapa itu harus dibuat dan diteruskan ke konstruktor padahal mungkin hanya jarang digunakan? "Setter Injection" adalah teknik DI lainnya yang dapat digunakan dalam situasi seperti ini.
Setter Injection tidak memaksa ketergantungan untuk diteruskan ke konstruktor. Alih-alih, dependensi diatur ke properti publik yang diekspos oleh objek yang membutuhkan. Seperti yang tersirat sebelumnya, motivator utama untuk melakukan ini meliputi:
Berikut adalah contoh bagaimana kode di atas akan terlihat seperti:
sumber
Saya pikir karena semua orang telah menulis untuk DI, izinkan saya mengajukan beberapa pertanyaan ..
Ini didasarkan pada jawaban @Adam N yang diposting.
Mengapa PersonService tidak perlu lagi khawatir tentang GroupMembershipService? Anda baru saja menyebutkan bahwa GroupMembership memiliki banyak hal (objek / properti) yang tergantung padanya. Jika GMService diperlukan di PService, Anda akan memilikinya sebagai properti. Anda dapat mengejek itu terlepas dari apakah Anda menyuntikkannya atau tidak. Satu-satunya waktu saya ingin disuntikkan adalah jika GMService memiliki kelas anak yang lebih spesifik, yang Anda tidak akan tahu sampai runtime. Maka Anda ingin menyuntikkan subclass. Atau jika Anda ingin menggunakannya sebagai singleton atau prototipe. Sejujurnya, file konfigurasi memiliki semua hardcoded sejauh apa subkelas untuk tipe (antarmuka) yang akan disuntikkan selama waktu kompilasi.
EDIT
Komentar bagus oleh Jose Maria Arranz di DI
DI meningkatkan kohesi dengan menghilangkan kebutuhan untuk menentukan arah ketergantungan dan menulis kode lem.
Salah. Arah dependensi adalah dalam bentuk XML atau sebagai anotasi, dependensi Anda ditulis sebagai kode XML dan anotasi. XML dan anotasi ADALAH kode sumber.
DI mengurangi kopling dengan membuat semua komponen Anda menjadi modular (dapat diganti) dan memiliki antarmuka yang saling ditentukan dengan baik.
Salah. Anda tidak perlu kerangka DI untuk membangun kode modular berdasarkan antarmuka.
Tentang yang dapat diganti: dengan arsip .properties dan Class.forName yang sangat sederhana, Anda dapat menentukan kelas mana yang dapat diubah. Jika kelas APAPUN kode Anda dapat diubah, Java bukan untuk Anda, gunakan bahasa scripting. Omong-omong: anotasi tidak dapat diubah tanpa kompilasi ulang.
Menurut pendapat saya ada satu-satunya alasan untuk kerangka kerja DI: pengurangan pelat ketel. Dengan sistem pabrik yang dilakukan dengan baik, Anda dapat melakukan hal yang sama, lebih terkontrol, dan lebih dapat diprediksi sebagai kerangka kerja DI pilihan Anda, kerangka kerja DI menjanjikan pengurangan kode (XML dan anotasi juga merupakan kode sumber). Masalahnya adalah pengurangan pelat ketel ini hanya nyata dalam kasus yang sangat sangat sederhana (satu instance-per kelas dan serupa), kadang-kadang di dunia nyata memilih objek layanan yang sesuai tidak semudah memetakan kelas ke objek tunggal.
sumber
Jawaban populer tidak membantu, karena mereka mendefinisikan injeksi ketergantungan dengan cara yang tidak berguna. Mari kita sepakati bahwa dengan "ketergantungan" yang kita maksud adalah beberapa objek lain yang sudah ada sebelumnya yang dibutuhkan oleh objek X kita. Tapi kami tidak mengatakan kami melakukan "injeksi ketergantungan" ketika kami mengatakannya
Kami hanya memanggil parameter yang lewat ke konstruktor. Kami telah melakukan itu secara teratur sejak konstruktor ditemukan.
"Injeksi ketergantungan" dianggap sebagai jenis "inversi kontrol", yang berarti bahwa beberapa logika dikeluarkan dari pemanggil. Itu tidak terjadi ketika pemanggil melewati parameter, jadi jika itu DI, DI tidak akan menyiratkan inversi kontrol.
DI berarti ada tingkat menengah antara pemanggil dan konstruktor yang mengelola dependensi. Makefile adalah contoh sederhana injeksi ketergantungan. "Penelepon" adalah orang yang mengetik "make bar" pada baris perintah, dan "konstruktor" adalah kompiler. Makefile menetapkan bahwa bilah bergantung pada foo, dan bilah
sebelum melakukan a
Orang yang mengetik "make bar" tidak perlu tahu bahwa bar tergantung pada foo. Ketergantungan disuntikkan antara "make bar" dan gcc.
Tujuan utama dari tingkat menengah bukan hanya untuk meneruskan dependensi ke konstruktor, tetapi untuk membuat daftar semua dependensi hanya dalam satu tempat , dan untuk menyembunyikannya dari coder (bukan untuk membuat coder menyediakannya).
Biasanya tingkat menengah menyediakan pabrik untuk objek yang dibangun, yang harus memberikan peran yang harus dipenuhi oleh setiap jenis objek yang diminta. Itu karena dengan memiliki tingkat menengah yang menyembunyikan detail konstruksi, Anda sudah dikenai penalti abstraksi yang dikenakan oleh pabrik, jadi sebaiknya Anda menggunakan pabrik.
sumber
Dependency Injection berarti cara (sebenarnya cara apa pun ) untuk satu bagian kode (misalnya kelas) untuk memiliki akses ke dependensi (bagian lain dari kode, misalnya kelas lain, tergantung pada) dengan cara modular tanpa harus dikodekan (jadi mereka dapat berubah atau diganti secara bebas, atau bahkan dimuat pada waktu lain, sesuai kebutuhan)
(dan ps, ya itu telah menjadi nama 25 $ terlalu-hyped untuk konsep, agak sederhana) ,
.25
sen sayasumber
Saya tahu sudah ada banyak jawaban, tetapi saya menemukan ini sangat membantu: http://tutorials.jenkov.com/dependency-injection/index.html
Tidak Ada Ketergantungan:
Ketergantungan:
Perhatikan bagaimana
DataSourceImpl
instantiasi dipindahkan ke konstruktor. Konstruktor mengambil empat parameter yang merupakan empat nilai yang dibutuhkan olehDataSourceImpl
. MeskipunMyDao
kelas masih bergantung pada empat nilai ini, itu tidak lagi memenuhi dependensi itu sendiri. Mereka disediakan oleh kelas apa pun yang membuatMyDao
instance.sumber
Injeksi ketergantungan adalah salah satu solusi yang memungkinkan untuk apa yang secara umum dapat disebut persyaratan "Ketergantungan Kebingungan". Dependency Obfuscation adalah metode untuk menghilangkan sifat 'jelas' dari proses penyediaan ketergantungan pada kelas yang membutuhkannya dan oleh karena itu mengaburkan, dalam beberapa cara, penyediaan ketergantungan tersebut kepada kelas tersebut. Ini belum tentu hal yang buruk. Pada kenyataannya, dengan mengaburkan cara dimana ketergantungan diberikan kepada kelas maka sesuatu di luar kelas bertanggung jawab untuk menciptakan ketergantungan yang berarti, dalam berbagai skenario, implementasi ketergantungan yang berbeda dapat dipasok ke kelas tanpa membuat perubahan apa pun. ke kelas. Ini bagus untuk beralih antara mode produksi dan pengujian (mis., Menggunakan ketergantungan layanan 'mock').
Sayangnya bagian yang buruk adalah bahwa beberapa orang berasumsi bahwa Anda memerlukan kerangka kerja khusus untuk melakukan kebingungan dependensi dan bahwa Anda entah bagaimana merupakan programmer yang 'lebih rendah' jika Anda memilih untuk tidak menggunakan kerangka kerja tertentu untuk melakukannya. Mitos lain yang sangat mengganggu, diyakini oleh banyak orang, adalah bahwa injeksi ketergantungan adalah satu-satunya cara untuk mencapai kebingungan ketergantungan. Ini terbukti dan historis dan jelas 100% salah, tetapi Anda akan kesulitan meyakinkan beberapa orang bahwa ada alternatif untuk injeksi ketergantungan untuk persyaratan kebingungan ketergantungan Anda.
Pemrogram telah memahami persyaratan kebingungan ketergantungan selama bertahun-tahun dan banyak solusi alternatif telah berkembang sebelum dan setelah injeksi ketergantungan dikandung. Ada pola Pabrik tetapi ada juga banyak opsi menggunakan ThreadLocal di mana tidak diperlukan injeksi ke instance tertentu - ketergantungan secara efektif disuntikkan ke thread yang memiliki manfaat membuat objek tersedia (melalui metode pengambil statis yang mudah) untuk setiapkelas yang membutuhkannya tanpa harus menambahkan anotasi ke kelas yang membutuhkannya dan mengatur 'lem' XML yang rumit untuk mewujudkannya. Ketika dependensi Anda diperlukan untuk kegigihan (JPA / JDO atau apa pun) itu memungkinkan Anda untuk mencapai 'kegigihan tranaparen' jauh lebih mudah dan dengan model domain dan kelas model bisnis yang dibuat murni dari POJO (yaitu tidak ada kerangka kerja spesifik / terkunci dalam anotasi).
sumber
Dari Buku, ' Pengembang Java yang Berpijak: Teknik vital Java 7 dan pemrograman polyglot
sumber
Sebelum pergi ke deskripsi teknis, visualisasikan terlebih dahulu dengan contoh nyata karena Anda akan menemukan banyak hal teknis untuk belajar injeksi ketergantungan tetapi waktu maksimum orang-orang seperti saya tidak bisa mendapatkan konsep inti itu.
Pada gambar pertama, Asumsikan bahwa Anda memiliki pabrik mobil dengan banyak persatuan. Mobil sebenarnya dibangun di unit perakitan tetapi membutuhkan mesin , kursi , dan roda . Jadi unit perakitan tergantung pada semua unit ini dan mereka adalah ketergantungan pabrik.
Anda dapat merasakan bahwa sekarang ini terlalu rumit untuk mempertahankan semua tugas di pabrik ini karena seiring dengan tugas utama (Merakit mobil dalam unit Perakitan) Anda harus juga fokus pada unit lain . Sekarang sangat mahal untuk dirawat dan bangunan pabrik sangat besar sehingga dibutuhkan uang ekstra untuk disewa.
Sekarang, lihat gambar kedua. Jika Anda menemukan beberapa perusahaan penyedia yang akan memberi Anda roda , kursi , dan mesin lebih murah daripada biaya produksi sendiri, maka sekarang Anda tidak perlu membuatnya di pabrik Anda. Anda dapat menyewa gedung yang lebih kecil sekarang hanya untuk unit perakitan Anda yang akan mengurangi tugas perawatan Anda dan mengurangi biaya sewa tambahan Anda. Sekarang Anda juga dapat fokus hanya pada tugas utama Anda (Perakitan mobil).
Sekarang kita dapat mengatakan bahwa semua dependensi untuk merakit mobil disuntikkan di pabrik dari penyedia . Ini adalah contoh dari Dependency Injection (DI) kehidupan nyata .
Sekarang dalam kata teknis, injeksi ketergantungan adalah teknik di mana satu objek (atau metode statis) memasok dependensi objek lain. Jadi, mentransfer tugas untuk membuat objek ke orang lain dan langsung menggunakan dependensi disebut dependensi injeksi.
Ini akan membantu Anda sekarang untuk belajar DI dengan beberapa kata techy. Ini akan menunjukkan kapan harus menggunakan DI dan kapan tidak .
.
sumber
dari Book Apress.Spring.Persistence.with.Hibernate.Oct.2010
sumber
Dependency Injection (DI) adalah salah satu dari Pola Desain, yang menggunakan fitur dasar OOP - hubungan dalam satu objek dengan objek lain. Sementara warisan mewarisi satu objek untuk melakukan objek lain yang lebih kompleks dan spesifik, hubungan atau asosiasi hanya membuat pointer ke objek lain dari satu objek menggunakan atribut. Kekuatan DI dalam kombinasi dengan fitur-fitur OOP lainnya seperti antarmuka dan kode penyembunyian. Misalkan, kami memiliki pelanggan (pelanggan) di perpustakaan, yang dapat meminjam hanya satu buku untuk kesederhanaan.
Antarmuka buku:
Selanjutnya kita dapat memiliki banyak jenis buku; salah satu jenisnya adalah fiksi:
Sekarang pelanggan dapat memiliki hubungan dengan buku:
Ketiga kelas dapat disembunyikan untuk implementasi itu sendiri. Sekarang kita dapat menggunakan kode ini untuk DI:
Ada banyak cara berbeda cara menggunakan injeksi ketergantungan. Dimungkinkan untuk menggabungkannya dengan Singleton, dll., Tetapi pada dasarnya itu hanya asosiasi yang diwujudkan dengan membuat atribut tipe objek di dalam objek lain. Kegunaannya hanya dan hanya dalam fitur, kode itu, yang harus kita tulis berulang kali selalu disiapkan dan dilakukan untuk kita maju. Inilah sebabnya mengapa DI begitu terikat erat dengan Inversion of Control (IoC) yang berarti, bahwa program kami melewati kontrol modul berjalan lain, yang melakukan suntikan kacang ke kode kami. (Setiap objek, yang dapat disuntikkan dapat ditandatangani atau dianggap sebagai Bean.) Misalnya di Spring itu dilakukan dengan membuat dan menginisialisasi ApplicationContextwadah, yang ini bekerja untuk kita. Kami hanya dalam kode kami membuat Konteks dan memohon inisialisasi kacang. Pada saat itu injeksi telah dilakukan secara otomatis.
sumber
Ketergantungan Injeksi untuk anak usia 5 tahun.
Ketika Anda pergi dan mengambil sendiri barang-barang dari lemari es, Anda dapat menyebabkan masalah. Anda mungkin membiarkan pintu terbuka, Anda mungkin mendapatkan sesuatu yang Ibu atau Ayah tidak ingin Anda miliki. Anda mungkin bahkan mencari sesuatu yang bahkan tidak kita miliki atau yang telah kedaluwarsa.
Yang harus Anda lakukan adalah menyatakan suatu kebutuhan, "Saya perlu minum dengan makan siang," dan kemudian kami akan memastikan Anda memiliki sesuatu ketika Anda duduk untuk makan.
sumber
Dari Christoffer Noring, buku Pablo Deeleman "Learning Angular - Second Edition":
"Ketika aplikasi kita tumbuh dan berkembang, masing-masing entitas kode kita secara internal akan membutuhkan instance dari objek lain , yang lebih dikenal sebagai dependensi dalam dunia rekayasa perangkat lunak. Tindakan meneruskan dependensi tersebut kepada klien dependen dikenal sebagai injeksi , dan itu juga memerlukan partisipasi dari entitas kode lain, bernama injector . injector akan bertanggung jawab untuk instantiating dan bootstrap yang diperlukan dependensi yangsehingga mereka siap digunakan sejak saat mereka berhasil disuntikkan ke klien. Ini sangat penting karena klien tidak tahu apa-apa tentang instantiate dependensinya sendiri dan hanya mengetahui antarmuka yang mereka implementasikan untuk menggunakannya. "
Dari: Anton Moiseev. buku "Pengembangan Sudut dengan Naskah, Edisi Kedua.":
"Singkatnya, DI membantu Anda menulis kode dengan cara yang digabungkan secara longgar dan membuat kode Anda lebih dapat diuji dan digunakan kembali ."
sumber
Sederhananya, dependensi injection (DI) adalah cara untuk menghilangkan dependensi atau ikatan erat antara objek yang berbeda. Dependency Injection memberikan perilaku kohesif untuk setiap objek.
DI adalah implementasi dari kepala IOC Spring yang mengatakan "Jangan panggil kami, kami akan menghubungi Anda". Menggunakan dependensi injeksi programmer tidak perlu membuat objek menggunakan kata kunci baru.
Objek pernah dimuat dalam wadah Spring dan kemudian kita menggunakannya kembali kapan pun kita membutuhkannya dengan mengambil objek-objek dari wadah Spring menggunakan metode getBean (String beanName).
sumber
Ketergantungan injeksi adalah jantung dari konsep yang terkait dengan Kerangka Kerja Pegas. Sementara menciptakan kerangka kerja dari setiap pegas proyek dapat melakukan peran vital, dan di sini injeksi ketergantungan datang dengan kendi.
Sebenarnya, Misalkan di java Anda membuat dua kelas yang berbeda sebagai kelas A dan kelas B, dan apa pun fungsi yang tersedia di kelas B yang ingin Anda gunakan di kelas A, Jadi pada saat itu ketergantungan injeksi dapat digunakan. di mana Anda dapat membuat objek dari satu kelas di kelas lain, dengan cara yang sama Anda bisa menyuntikkan seluruh kelas di kelas lain untuk membuatnya dapat diakses. dengan cara ini ketergantungan dapat diatasi.
INJEKSI TERGANTUNG ADALAH SEDERHANA MENGGOSOK DUA KELAS DAN PADA SAAT YANG SAMA MENJAGA MEREKA TERPISAH.
sumber