Injeksi Dependensi
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan PHP di Coddy. Pelajaran 57 dari 91.
Di pelajaran sebelumnya, kamu melihat bagaimana komposisi memungkinkan sebuah Car memiliki object Engine. Namun, ada masalah saat membuat dependensi di dalam class, yaitu kodemu menjadi kaku dan sulit diuji. Dependency Injection mengatasi masalah ini dengan meneruskan dependensi dari luar, bukan membuatnya di dalam.
Bandingkan dua pendekatan ini:
<?php
// Tanpa DI, dependensi dibuat di dalam
class Car {
private Engine $engine;
public function __construct() {
$this->engine = new Engine(); // Saling bergantung erat
}
}
// Dengan DI, dependensi diteruskan dari luar
class Car {
public function __construct(private Engine $engine) {}
}
$engine = new Engine();
$car = new Car($engine); // Disuntikkan dari luar
Pendekatan kedua adalah dependency injection. Car tidak membuat engine-nya sendiri, tetapi menerima engine. Perubahan sederhana ini memberikan manfaat besar: kamu bisa memberikan berbagai tipe engine, mengganti implementasi untuk pengujian, dan membuat class menjadi lebih fleksibel.
Untuk fleksibilitas yang lebih besar, injeksikan interface alih-alih class konkret:
<?php
interface EngineInterface {
public function start(): string;
}
class Car {
public function __construct(private EngineInterface $engine) {}
public function start(): string {
return $this->engine->start();
}
}
Sekarang Car dapat digunakan dengan class apa pun yang mengimplementasikan EngineInterface, seperti mesin bensin, motor listrik, atau mock untuk pengujian. Pemisahan ini adalah alasan dependency injection menjadi dasar untuk menulis aplikasi PHP yang mudah dipelihara dan diuji.
Tantangan
MudahMari kita bangun sistem notifikasi yang menunjukkan keunggulan injeksi dependensi. Daripada menentukan secara langsung cara pesan dikirim, kamu akan membuat sistem fleksibel yang memungkinkan cara pengiriman diganti dengan mudah.
Kamu akan mengatur kodemu dalam empat file:
MessageSenderInterface.php: Definisikan interface bernamaMessageSenderInterfacedengan satu methodsend(string $recipient, string $message): string. Interface ini menetapkan kontrak yang harus diikuti oleh setiap pengirim pesan.EmailSender.php: Buat classEmailSenderyang mengimplementasikanMessageSenderInterface. Sertakan file interface tersebut. Methodsend()harus mengembalikan"Email to [recipient]: [message]".NotificationService.php: Buat classNotificationServiceyang menerima dependensinya melalui constructor. Sertakan file interface tersebut. Class ini harus:- Menerima
MessageSenderInterfacedi constructornya menggunakan promosi constructor - Memiliki method
notify(string $recipient, string $message)yang meneruskan pemanggilan ke pengirim yang diinjeksi dan mengembalikan hasilnya
NotificationServicebergantung pada interface, bukan class konkret. Artinya, kamu bisa menginjeksi pengirim apa pun yang mengimplementasikan interface tersebut tanpa mengubah service.- Menerima
main.php: Sertakan file EmailSender dan NotificationService. Kamu akan menerima dua input: penerima dan pesan. BuatEmailSender, injeksikan ke dalamNotificationService, lalu panggilnotify()dan cetak hasilnya.
Pola ini membuat NotificationService tetap fleksibel. Service ini dapat bekerja dengan pengirim apa pun yang kamu injeksikan, baik itu email, SMS, maupun sesuatu yang belum kamu buat. Service ini tidak membuat dependensinya sendiri, tetapi menerimanya dari luar.
Coba sendiri
<?php
require_once 'EmailSender.php';
require_once 'NotificationService.php';
// Baca input
$recipient = trim(fgets(STDIN));
$message = trim(fgets(STDIN));
// TODO: Buat instance EmailSender
// TODO: Masukkan instance tersebut ke NotificationService
// TODO: Panggil notify() dan cetak hasilnya
?>Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP
File EksternalPengenalan OOPclass vs objectKata Kunci $thismethodpropertyConstructor (__construct)Destructor (__destruct)Ringkasan: Kalkulator Sederhana4Pewarisan
Pewarisan DasarKata Kunci parent::Penimpaan methodKata Kunci finalClass AbstrakRingkasan: Hierarki Karyawan7Enkapsulasi
Public, Protected, PrivateModifier Akses secara MendalamGetter dan SetterPenyembunyian InformasiPromosi Constructor (8.0)Ulasan: Sistem Catatan Siswa10Konsep OOP Lanjutan
Komposisi vs PewarisanInjeksi Dependensiclass AnonimEnum (PHP 8.1)Fiber (PHP 8.1)Pendalaman Kloning objectGenerator dan Iterator2Namespace dan Autoloading
Pengenalan NamespaceKata Kunci useStandar Autoloading PSR-4Autoloader ComposerRingkasan: Proyek yang Terorganisasi5Interface dan Kontrak
Pengenalan InterfaceMengimplementasikan InterfaceImplementasi Beberapa InterfaceInterface vs Abstract ClassPetunjuk Tipe dengan InterfaceRekap: Kalkulator Bentuk8Magic Methods
Pengantar Magic Methods__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Cloning Object__serialize & __unserializeRingkasan: Koleksi Kustom11Sistem Tipe Data dan Penanganan Error
Deklarasi TipeTipe NullableTipe Union dan IntersectionClass ExceptionHierarki Exception KustomTry, Catch, FinallyRekap: Validator Form3Property dalam class
Property instance vs staticKonstanta dalam classMethod & property staticProperty private & protectedProperty readonly (PHP 8.1)Ulasan: Pengelola Rekening Bank6Polimorfisme
Meninjau Kembali Method OverridingPolimorfisme melalui AntarmukaPetunjuk Tipe dan Tipe UnionPengikatan Statis TertundaRangkuman: Pemroses PembayaranLatihan sendiri: Compiler PHP online