SOLID - Prinsip Desain Arsitektur Di Dalam Pemrograman Object Oriented (Dependency Inversion Principal)
Akhirnya kita sampai di bagian paling akhir dari seri tulisan SOLID Principal yaitu untuk huruf D.
Ketika kita bekerja menggunakan bahasa pemrograman berorientasi object, kita pasti akan menggunakan Class. Class tersebut pada akhirnya akan saling terkait / ketergantungan satu dan yang lain untuk melakukan tugas tertentu. Ketergantungan ini disebut dengan istilah Dependency. Dependency ini bisa terjadi antar Class di dalam satu Code Base yang sama, atau bahkan antar Library. Controhnya seperti potongan kode berikut.
<?php namespace App\DependencyInversion; /** * Description of Engine * * @author programmer */ class Engine { private KeihinCarburator $carburator; private NGKSpark $spark; public function __construct(KeihinCarburator $carburator, NGKSpark $spark) { $this->carburator = $carburator; $this->spark = $spark; } public function start():bool { $this->carburator->open(); $this->spark->nyalakan(); } } class KeihinCarburator { public function open():?string { return "karburator terbuka"; } } class NGKSpark { public function nyalakan():?string { return "busi menyala"; } }
Pada kode di atas, terlihat bahwa Class Mesin membutuhkan object dari Class KeihinCarburator dan Class NGKSpark untuk bisa berjalan sebagaimana mestinya.
<?php namespace App\DependencyInversion; class MotorManager { public static function createEngine():Engine { return new Engine(new KeihinCarburator(), new NGKSpark()); } }
Latar Belakang
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend on details. Details should depend on abstractions.
Kode yang saya tulis diatas memiliki ketergantungan yang kuat antara Class Mesin dengan Class KeihinCarburator juga Class NGKSpark. Ketergantungan yang kuat (tighly-coupled) seperti ini perlu dihindari agar kode yang kita punya menjadi lebih mudah untuk di maintenance juga dikembangkan.
Sekarang mari kita coba bayangkan skenarionya.
Andaikan kode diatas sudah berjalan dan motor sudah berfungsi sebagaimana mestinya. Kemudian suatu hari Busi dari motor tersebut mati dan harus diganti yang baru. Namun, dipasaran sudah tidak ada stok busi Merk NGK yang ternyata sudah dihentikan produksinya. Akhirnya mau tidak mau kita harus memodifikasi Class Mesin agar support dengan Busi jenis IgnimaxSpark. Kemudian masalah lain muncul karena motor sudah diproduksi dan dipakai oleh ribuan orang. Apakah akhirnya kita akan menarik produk motor tersebut dan menggantinya dengan Motor yang baru ? tentu tenaga dan biaya akan sangat mahal hanya karena masalah Busi yang tidak support.
Sekarang kembali ke koding, apabila Class Mesin sudah di pakai di ratusan kode kita yang lain, tentu akan merepotkan jika kita harus menggantinya satu per satu di semua tempat agar kode kita dapat berjalan ?
Karena permasalahan tersebut, maka dicetuskan konsep Dependency Inversion. Dependency Inversion singkatnya adalah merubah ketergantungan antar Class tersebut kedalam bentuk abstraksi.
Solusi
Didalam Dependency Inversion, Class yang terdapat di dalam module High Level tidak boleh tergantung pada Class yang terdapat di module Low Level.
High Level disini merupakan modul yang memuat proses bisnis utama yang merupakan suatu proses yang melakukan tugas utama tertentu. Di dalam kasus kode di atas, High Level modul kita adalah Class Engine yang berfungsi menjalankan fungsi utama sebuah mesin. Atau bisa jadi merupakan library pihak ketiga yang kita tambahkan di project kita.
Low Level module merupakan kode yang memuat implementasi dari bagian-bagian tertentu yang mungkin akan punya banyak variasi. Didalam kasus kode kita, Low level merupakan kode yang memuat kode sparepart seperti karburator, busi dll yang kemungkinan bisa kita ganti-ganti sesuai kebutuhan. Atau kalau di kode pada umumnya ini adalah kode yang kita tulis di folder src.
High Level disini tidak boleh tergantung terhadap Class yang terdapat di Low Level. Karena itu, Class Engine kita ubah menjadi seperti berikut.
<?php interface CarburatorInterface { public function open():?string; } interface SparkInterface { public function nyalakan():?string; } abstract class Engine { private CarburatorInterface $carburator; private SparkInterface $spark; public function __construct(CarburatorInterface $carburator, SparkInterface $spark) { $this->carburator = $carburator; $this->spark = $spark; } public function start():bool { $this->carburator->open(); $this->spark->nyalakan(); } }
Sekarang Class Engine mempunyai ketergantungan tidak lagi kepada Concrete Class, tetapi sekarang terhadap abstraksi yang dalam kasus ini terhadap interface CarburatorInterface dan SparkInterface. Jadi Class Engine bisa lebih fleksibel.
Kemudian untuk Low Level Module kita modifikasi menjadi beberapa Class implementasi dari interface yang terdapat dari module High Level di atas.
<?php class HondaEngine extends Engine { } class YamahaEngine extends Engine { } class KeihinCarburator implements CarburatorInterface { public function open():?string { return "karburator terbuka"; } } class NGKSpark implements SparkInterface { public function nyalakan():?string { return "NGK => busi menyala"; } } class HondaSpark implements SparkInterface { public function nyalakan():?string { return "Honda => busi menyala"; } }
pada kode di atas, saya menambahkan 2 buah Concrete Class dari interface SparkInterface. Kita sudah punya 2 buah Busi yaitu Merk NGK dan Honda. JUga punya dua buah mesin yaitu Honda dan Yamaha.
kemudian di class Manager kita sebagai pengguna bisa dengan leluasa bongkar pasang Class sesuai dengan kebutuhan seperti kode berikut.
<?php class EngineManager { public static function createHondaEngine():Engine { return new HondaEngine( new KeihinCarburator(), new HondaSpark() ); } public static function createYamahaEngine():Engine { return new YamahaEngine( new KeihinCarburator(), new NGKSpark() ); } public static function createHondaCustomEngine():Engine { return new HondaEngine( new KeihinCarburator(), new NGKSpark() ); } }
Kesimpulan
Akhirnya dengan prinsip Dependency Inversion, kode yang kita buat menjadi lebih mudah untuk di kembangkan juga perbaiki. Ini juga memudahkan kita untuk mekerja secara kolaborasi juga membagikan kode dengan developer lain secara lebih mudah.
untuk tulisan terkait SOLID yang lain:
Komentar
Posting Komentar