SOLID Principle: Best Practice in Software Development? (Personal Experience)

Adietya Christian
4 min readApr 18, 2023

--

Image source: https://blog.knoldus.com/all-you-need-to-know-about-solid-principles/

Apa kabar teman-teman? Semoga kalian semua dalam keadaan baik. Pada artikel ini saya ingin menceritakan pengalaman saya selama menggunakan SOLID Principle dalam programming. SOLID Principle adalah sekumpulan prinsip yang digunakan untuk mendevelop suatu software. Sedangkan best practice sendiri adalah teknik atau cara yang dianjurkan atau disarankan untuk digunakan dalam pengembangan perangkat lunak. Best practice ini didasarkan pada pengalaman dan pengetahuan yang teruji dan telah terbukti efektif dalam membantu memastikan keamanan, kualitas, dan konsistensi pada kode program.

SOLID Principle merupakan salah satu best practice dalam programming yang sangat penting. SOLID Principle memberikan panduan untuk merancang dan mengembangkan kode program yang lebih maintainable, scalable, dan mudah diubah sesuai kebutuhan.

SOLID Principle sendiri terdiri dari 5 prinsip yaitu Single Responsibility Principle (SRP), Open/Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation Principle (ISP), dan Dependency Inversion Principle (DIP).

Mari kita lihat setiap prinsip SOLID Principle beserta contoh dan penjelasannya:

  1. Single Responsibility Principle (SRP)

SRP adalah prinsip yang mengatakan bahwa setiap kelas atau modul harus bertanggung jawab atas satu fungsionalitas tertentu. Dengan menerapkan SRP, kita dapat menghindari pembuatan kelas yang terlalu kompleks dan sulit di-maintain kedepannya.

Sebagai contoh, misal kita mau membuat class Produk yang memiliki atribut nama dan harga. Setelah itu kita mau melakukan kalkulasi jumlah pajak untuk produk tersebut. Mungkin kita akan membuat classnya seperti ini:

class Produk {
String nama;
String harga;
double ratePajak;

Produk(nama, harga, ratePajak) {
this.nama = nama;
this.harga = harga;
this.ratePajak = ratePajak;
}
kalkulasiPajak() {
return this.harga * this.ratePajak;
}
}

Meskipun terlihat sudah baik, sebenarnya method kalkulasiPajak tidak boleh menjadi bagian dari kelas, karena setiap kali kita mengubah kalkulasi, kelas produk juga akan ikut terlibat. Kita bisa mengekstrak kalkulasi ke dalam class lain, misalnya KalkulatorPajak.

class Produk {
String nama;
String harga;
double ratePajak;

Produk(nama, harga, ratePajak) {
this.nama = nama;
this.harga = harga;
this.ratePajak = ratePajak;
}
getHarga() {
return this.harga;
}
getRatePajak() {
return this.ratePajak;
}
}

class KalkulatorPajak {
static kalkulasiPajak(produk) {
return produk.getHarga() * product.getRatePajak();
}
}

Dengan dua class seperti ini, perhitungan pajak dapat dilakukan secara terpisah tanpa melibatkan class Produk. Namun, sebenarnya masih ada satu hal yang bisa dilakukan, yaitu memisahkan ratePajak dari class Produk. Secara intuisi maupun di dalam kehidupan nyata, ratePajak biasanya ditentukan oleh suatu negara / instansi yang terkait dan bersifat konstan. Sehingga, alangkah lebih baik kalau ratePajak dikeluarkan dari class Produk, seperti berikut ini.

class Produk {
String nama;
String harga;

Produk(nama, harga) {
this.nama = nama;
this.harga = harga;
}
getHarga() {
return this.harga;
}
}

class KalkulatorPajak {
static double taxRate = 0.11;

static kalkulasiPajak(produk) {
return produk.getHarga() * taxRate;
}
}

Dengan begini, setiap class memiliki tanggung jawabnya masing-masing.

2. Open/Closed Principle (OCP)

OCP adalah prinsip yang mengatakan bahwa suatu class harus terbuka untuk ekstensi/extend, namun tertutup untuk modifikasi/perubahan. Artinya, Kita seharusnya dapat menambahkan behavior baru tanpa perlu mengubah fungsionalnya.

Tujuan dari prinsip ini untuk menghindari kemungkinan terjadinya bug-bug baru ketika kita merubah implementasi code yang sudah uda.

Sebagai contoh, misal kita memiliki 3 Role dalam aplikasi yaitu Learner , Tutor , dan Admin . Lalu kita mau membuat class constructor sederhana bernama User . Mungkin kita akan membuatnya seperti ini

class User {
String role;

User(String role) {
switch (role) {
case "Admin":
createAdmin();
break;
case "Tutor":
createTutor();
break;
default:
createLearner();
}
}

void createAdmin() {
System.out.println("Admin Created");
}

void createTutor() {
System.out.println("Tutor Created");
}

void createLearner() {
System.out.println("Learner Created");
}
}

Jika kita melakukan hal tersebut sangat memungkinkan terciptanya bug baru di kemudian hari karena kita mungkin akan mengubah code yang sebelumnya apabila terdapat penambahan role dan sebagainya.

Sekarang kita akan coba mengimplementasikan OCP. Pertama-tama, kita buat interface sebagai bentuk abstraksi dari Role, yang memiliki satu buah method bernama create().

interface Role {
void create();
}

Setelah itu, kita bisa mengimplementasi interface Role ke dalam 3 class, yaitu Learner, Tutor, dan Admin.

class Learner implements Role {

@Override
void create() {
System.out.println("Learner Created");
}
}
class Tutor implements Role {

@Override
void create() {
System.out.println("Tutor Created");
}
}
class Admin implements Role {

@Override
void create() {
System.out.println("Admin Created");
}
}

Setelah itu, kita bisa tambahkan atribut role method create di dalam class User.

class User {
Role role;

User(Role role) {
this.role = role;
role.create();
}
}

Hal ini mempermudah pembuatan unit test maupun pengembangan software kedepannya karena ketika ingin menambah / menghapus role, tidak perlu mengubah kode pada class User, melainkan cukup menambahkan atau mengurangi class yang mengimplementasi Role.

3. Liskov Substitution Principle (LSP)

LSP adalah prinsip yang mengatakan bahwa objek dari inherit class harus dapat digunakan sebagai pengganti objek dari kelas induk tanpa mengubah kebenaran dari program tersebut. Dengan menerapkan LSP, kita dapat memastikan bahwa setiap objek memiliki behaviour yang konsisten.

4. Interface Segregation Principle (ISP)

ISP adalah prinsip yang mengatakan bahwa setiap klien harus hanya bergantung pada fungsionalitas yang dibutuhkan dan tidak harus bergantung pada fungsionalitas yang tidak dibutuhkan. Dengan menerapkan ISP, kita dapat memastikan bahwa klien hanya bergantung pada fungsionalitas yang dibutuhkan dan menghindari ketergantungan yang tidak perlu.

5. Dependency Inversion Principle (DIP)

DIP adalah prinsip yang mengatakan bahwa kelas harus bergantung pada abstraksi bukan pada implementasi. Dengan menerapkan DIP, kita dapat memastikan bahwa kelas tidak terlalu bergantung pada implementasi dan dapat lebih mudah untuk diuji dan dimodifikasi.

Dalam kesimpulannya, SOLID Principle adalah salah satu dari sekian banyak best practice dalam programming yang penting untuk diterapkan. Memahami dan mengikuti prinsip-prinsip SOLID Principle dapat membantu programmer membuat kode program yang lebih baik dan lebih mudah dipelihara.

Nah, itulah penjelasan singkat dari saya mengenai SOLID Principle dalam programming beserta contoh dan penjelasannya. Terima kasih sudah membaca dan semoga bermanfaat!

Referensi:

Jurnal:

  • Madasu, V. K., Venna, T. V. S. N., & Eltaeib, T. (2015). SOLID Principles in Software Architecture and Introduction to RESM Concept in OOP. Journal of Multidisciplinary Engineering Science and Technology (JMEST), 2(2), 3159–0040.
  • Arora, G. K. (2017). SOLID Principles Succinctly.

Blog:

  1. https://www.digitalocean.com/community/conceptual-articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design
  2. https://www.freecodecamp.org/news/solid-principles-explained-in-plain-english/

--

--

Adietya Christian
Adietya Christian

Written by Adietya Christian

A Passionate Computer Science Student Interested in Mobile Application Development

No responses yet