Pengantar
Pengalaman saya sebagai software developer khususnya backend, saya pernah di fase tidak memikirkan code structure (ambyarrr ndess). Hal ini tentunya menyebabkan beberapa kekurangan paling tidak 2 point ini:
- Code Readibillity -> kesusahan untuk membaca flow bisnis dalam code
- Performance -> potensi memory leak ketika initiate suatu koneksi ke tcp/ip berkali-kali.
Jika hal ini dibiarkan maka niscaya terciptalah sebuah coding serba ada nan ndangkik-ndangkik dengan nama cukup familiar : sphageti code. Sedangkan harapannya adalah kebalikan dari kekurangan tersebut, tentunya ingin mudah dibaca, dan performance bagus.
Pembahasan
- Code Readibillity
Kenapa pada fase pengalaman saya diatas ada kekurangan? Hal ini biasanya saya tidak memisahkan istilah2 umum seperti routing, handler, usecase, library, repository. Penjelasan :
- Routing -> function yang berisi definisi endpoint yang akan saya publish ketika service backend saya running
- Handler -> function yang menangani trafik yang masuk sesuai definisi endpoint yang diarahkan ke sini.
- Usecase -> function yang berisi bisnis proses
- Library -> function yang berisi tools yg sering dipakai yang tidak berkaitan dengan bisnis proses.
- Repository -> function yg berisi definisi koneksi ke sistem lain seperti database, message broker, service API lainnya.
- Performance
Dalam pengalaman saya ketika mengerjakan code, saya hanya berorientasi pada kesesuaian hasil dengan bisnis proses, sehingga mengesampingkan hal-hal seperti koneksi ke sistem lain yang sifatnya TCP misal: database, message broker, service API lain, dan lain-lain.
Kesalahan yang saya alami adalah: seringnya saya melakukan inisiasi (open conncetion) berkali-kali yanng tentunya ini memnyebabkan memory leak pada service aplikasi. Padahal menurut situs ini -> Software Engineering: Dependencies, salah satu faktor penting yakni dependencies. Nah pada artikel ini kita kebetulan membahas mengenai penerapan dependcy injection dalam bahasa yang saya harap mudah tanpa perlu njlimet. So lets go kita ke bab selanjutnya.
Penerapan
Berikut adalah contoh sederhana penggunaan Dependency Injection dalam bahasa Go untuk manajemen pengguna (user management) yang menggunakan database PostgreSQL.
Pertama, Anda harus mengatur koneksi ke database PostgreSQL. Kemudian, kita akan membuat struktur untuk manajemen pengguna yang akan menyimpan koneksi database sebagai dependensinya.
Dalam contoh ini, kita menggunakan database/sql untuk berinteraksi dengan PostgreSQL. Kemudian, kita membuat sebuah interface UserManager yang mendefinisikan operasi yang dapat dilakukan untuk manajemen pengguna, yaitu membuat pengguna baru dan mendapatkan informasi pengguna berdasarkan nama pengguna.
Kemudian, kita memiliki struct DBUserManager yang mengimplementasikan interface UserManager. Struktur ini memiliki properti DB yang merupakan koneksi ke database PostgreSQL. Metode-metode pada DBUserManager menggunakan koneksi ini untuk berinteraksi dengan database.
Di dalam main(), kita membuat objek DBUserManager dengan menyediakan koneksi database PostgreSQL, dan kemudian menggunakan objek tersebut untuk membuat pengguna baru dan mendapatkan informasi pengguna berdasarkan nama pengguna.
Dengan menggunakan Dependency Injection, kita memungkinkan untuk dengan mudah mengganti implementasi manajemen pengguna atau database yang digunakan tanpa mengubah logika bisnis di tempat lain.
Kesimpulan
Mari kita tinjau kesimpulan dari contoh di atas dengan menggunakan pendekatan SOLID:
- Single Responsibility Principle (SRP):
- Setiap struktur dalam contoh tersebut memiliki tanggung jawab yang terpisah.
- DBUserManager bertanggung jawab atas manajemen pengguna, termasuk operasi seperti membuat pengguna baru dan mendapatkan informasi pengguna.
- Koneksi ke database ditangani secara terpisah, sesuai dengan prinsip ini.
- Open/Closed Principle (OCP):
- Struktur DBUserManager terbuka untuk ekstensi dengan memungkinkan penambahan fungsi-fungsi baru dalam manajemen pengguna.
- Jika kita ingin menambahkan fungsionalitas tambahan, seperti menghapus pengguna, kita dapat melakukannya dengan menambahkan metode baru tanpa mengubah struktur yang sudah ada.
- Liskov Substitution Principle (LSP):
- Dalam contoh ini, tidak ada pewarisan atau substitusi kelas yang jelas yang terjadi. Namun, ketika kita menggunakan Dependency Injection, kita memungkinkan untuk mengganti implementasi UserManager tanpa mempengaruhi bagian lain dari kode.
- Misalnya, kita bisa memiliki implementasi UserManager yang berbeda yang menggunakan penyimpanan data yang berbeda tanpa mengubah bagian dari kode yang menggunakan UserManager.
- Interface Segregation Principle (ISP):
- Interface UserManager telah diorganisir dengan baik. Ini hanya menyertakan operasi yang diperlukan untuk manajemen pengguna, yaitu membuat pengguna baru dan mendapatkan informasi pengguna berdasarkan nama pengguna.
- Prinsip ini memastikan bahwa antarmuka tidak menjadi terlalu besar atau berisi lebih banyak operasi daripada yang diperlukan, sehingga menghindari ketergantungan yang tidak perlu.
- Dependency Inversion Principle (DIP):
- Prinsip ini sangat diterapkan dalam contoh ini. Koneksi database disuntikkan ke dalam DBUserManager sebagai dependensinya, yang memungkinkan fleksibilitas dalam penggunaan berbagai implementasi koneksi database.
- Dengan menggunakan Dependency Injection, kita menghindari ketergantungan langsung pada implementasi spesifik, seperti PostgreSQL, dan kita dapat dengan mudah mengganti atau menguji kembali koneksi database tanpa mengubah logika bisnis pada struktur lainnya.
- Dengan menerapkan prinsip-prinsip SOLID, kita dapat membuat kode yang lebih bersih, terstruktur, dan mudah diubah dan diperluas di masa depan. Hal ini membantu dalam membangun sistem yang lebih kokoh, terjamin, dan mudah di-maintain.