Dependency Injection dan Implementasinya di PHP
Dependency Injection (DI) adalah sebuah design pattern yang memungkinkan kita untuk menulis kode yang lebih baik, dimana DI menitikberatkan pada penulisan kode yang loosely coupled, highly modular dimana ketergantungan antar class tidaklah tinggi, sehingga kita dapat mengubah sebuah class tanpa diliputi rasa khawatir class tersebut membuat break class-class lain yang bergantung pada class yang kita rubah tadi.
Dependency Injection sendiri bukanlah sebuah design pattern yang baru, melainkan sudah banyak digunakan dalam bahasa pemrograman seperti Java. Namun di dunia PHP sendiri, DI menjadi populer karena digunakan di framework-framework PHP yang populer seperti Laravel dan Symfony.
Nah, sebenarnya apakah Dependency Injection itu ?
Berikut adalah definisi Dependency Injection yang ditulis di wikipedia :
In software engineering, dependency injection is a technique whereby one object supplies the dependencies of another object. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client’s state.[1] Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.
Jika definisi di atas masih terasa membingungkan, tidak perlu khawatir karena kita akan membahasnya dalam pembahasan yang lebih practical. Mari kita sederhanakan definisi di atas menjadi
Dependency Injection adalah proses memasukkan (inject) sebuah class ke dalam class lain.
Ada alasan tertentu mengapa saya menggunakan istilah memasukkan / inject bukan memanggil / call. Karena implementasi dari inject dan call akan sangat berbeda. Langsung saja kita lihat contohnya :
Kita membuat sebuah class kendaraan yaitu Motorcycle.php
dan Car.php
. Class ini memerlukan sebuah class lain yang bernama Premium.php
untuk dipanggil pada method fillUp()
. Catatan : kode dibawah tidak mengimplementasikan Dependency Injection.
Lalu kita membuat sebuah file baru bernama MyVehicle.php
yang memanggil object berdasarkan class Motorcycle.php
dan Car.php
Ketika kita jalankan MyVehicle.php
, maka hasilnya adalah
Hmm.. sekilas tidak ada masalah dengan implementasi kode diatas. Namun masalah mulai muncul ketika kita ingin mengganti bahan bakar kendaraan kita dari Premium ke Pertamax. Dengan metode yang kita gunakan diatas, kita memanggil class Premium.php
di dalam class Motorcycle.php
dan Car.php
. Perhatikan kode berikut :
require_once('Premium.php');...$this->fuel = new Premium();
Jika kita ingin mengganti class Premium.php
ke Pertamax.php
maka kita harus mengganti satu per satu di masing-masing class yang memanggil Premium.php
. Kalau class yang depend hanya 2 seperti contoh diatas tentu tidak akan menjadi masalah. tapi bagaimana kalau ada 100 class ?
Kejadian seperti ini sering terjadi di dunia nyata. Seperti implementasi mail server atau database engine. Awalnya kita menggunakan MySQL sebagai database engine pada aplikasi kita. Ternyata ditengah jalan, kita mengganti database engine dari MySQL ke Oracle misalnya. Padahal class MySQL sudah terlanjur direferensikan oleh 100 atau lebih file. Tentu saja hal ini akan memusingkan si developer. Sebagai catatan, ini sangat mungkin terjadi jika kita koding menggunakan PHP Native atau framework dengan struktur yang arbitrary seperti flask-nya Python atau express-nya NodeJs. Namun untuk framework dengan struktur yang jelas seperti Laravel hal ini sudah di handle out-of-the-box.
Selanjutnya kita akan coba me-refactor kode di atas menggunakan Dependency Injection. Pertama, kita akan membuat sebuah interface bernama Fuel.php
untuk memastikan Pertamax.php
dan Premium.php
memiliki fungsi yang ada pada interface Fuel.php
.
Selanjutnya adalah file Pertamax.php
Lalu file Motorcycle.php
dan Car.php
yang sudah di-refactor dengan menggunakan Dependency Injection
Perhatikan metode __construct pada masing-masing class di atas. Terlihat ada parameter berupa class Fuel yang di-injeksi-kan pada metode tersebut. Inilah yang disebut dengan Dependency Injection, dimana kita memasukkan sebuah class ke dalam constructor atau method class lainnya.
Sekarang kita lihat versi MyVehicle.php
yang telah di-refactor menggunakan DI
Di MyVehicle.php
versi terbaru ini, terlihat kode tersebut memanggil class Pertamax.php
lalu menginjeksikan variable Fuel
(yang merupakan instansi dari class Pertamax)ke dalam class Car
dan Motorcycle
. Dan hasilnya adalah
Voila! hasilnya secara otomatis menampilkan Pertamax sebagai bahan bakar yang dipakai oleh kendaraan kita. Bagaimana jika kita ingin mengganti Pertamax dengan bahan bakar lain ? kita hanya perlu merubah dua baris kode yaitu
require_once('Pertamax.php');...$fuel = new Pertamax();
Dan otomatis hasilnya akan mengikuti class yang kita instantiate pada variable $fuel
. Mudah dan menyenangkan bukan ? :)
Sedikit tambahan, Dependency Injection tidak hanya terbatas pada constructor saja melainkan bisa juga di-inject langsung ke method yang dimiliki oleh class tersebut. Contoh kasus yang akan kita pakai adalah jika kita ingin class Car
menggunakan Pertamax
, sedangkan class Motorcycle
menggunakan Premium
. Perhatikan file Motorcycle.php
dan Car.php
berikut ini
Pada 2 file di atas kita langsung menginjeksikan class Fuel
ke dalam method fillUp()
. Sedangkan implementasi pada file MyVehicle.php
adalah sebagai berikut
Dan hasilnya
Familiar ? tidak heran karena framework terkenal seperti Laravel sangat berbasis DI. Mungkin tanpa sadar kita sudah menggunakannya sehari-hari.
use App\Http\Request;...public function get(Request $request)
{$input = $request->all()...}
Demikian sedikit ulasan kami tentang Dependency Injection. Semoga bermanfaat :)