author-pic

Ferry S

An ISTJ, Type 5, Engineer, Gamer, and Thriller-Movies-Lover
SOLID: Prinsip Interface Segregation
Mon. Nov 9th, 2020 01:23 AM3 mins read
SOLID: Prinsip Interface Segregation
Source: HuggingFace@TonyAssi - segregation of different kind of toilets

Interface Segregation adalah memecah sebuah abstrak yang terlalu besar menjadi beberapa abstrak yang lebih spesifik. Terkadang pada sebuah code yang dibutuhkan hanya beberapa method saja dari interface tersebut, sisanya tidak dibutuhkan dan beberapa diantaranya memiliki kohesi yang rendah, tidak saling terkait. Selain itu, sebuah abstraksi terlalu abstrak jika semuanya dikontrol oleh satu kelas yang sama. Karena scope-nya terlalu luas, suatu saat design seperti ini bisa melanggar Liskov Substitution Principle seandainya nanti ada sebuah turunan yang secara definisi masih satu turunan dengan parent-nya tapi mempunyai satu atau beberapa behavior yang tidak dimiliki. Pemisahan abstraksi ini dapat membuat abstrak jadi lebih mudah di-refactor, dimengerti dan diubah. Pada Java sendiri, Interface Segregation seperti ini dapat dilihat pada penggunaan interface Collection, List, Deque, dan Set. Seringkali contoh di google membuat bingung karena sering mencampuradukkan antara Interface Segregation dan Liskov Substitution Principle. Padahal kasusnya berbeda. Kali ini gw akan bikin contoh biar ga salah kaprah lagi.

Contoh kasusnya pada gateway yang bertugas menangani semua masalah tentang user terdapat beberapa method pada satu interface:

Interface UserGateway

public interface UserGateway{
	void signIn();
	void signOut();
	String getUserName();
	List<String> getBankList();
	boolean addBank(String bankName);
	boolean removeBank(String bankName);
	List<String> getAddressList();
	boolean addAddress(String address);
	boolean removeAddress(String address);
	String getMainAddress();
}

Interface tersebut digunakan pada sebuah code yang mengeksekusi aktivitas user seperti berikut:

Class UserProcessor

public class UserProcessor{
	public void addUserBank(UserGateway userGateway){
		userGateway.signIn();
		userGateway.addBank("BCA");
		userGateway.signOut();
	}

	public void addUserAddress(UserGateway userGateway){
		userGateway.signIn();
		userGateway.addAddress("Lubuk Sikarah");
		userGateway.signOut();
	}

	public void printUserName(UserGateway userGateway){
		userGateway.signIn();
		System.out.println("userName = " + userGateway.getUserName());
		userGateway.signOut();
	}
}

Pada class processor di atas, interface UserGateway terlalu gendut. Dari beberapa method hanya sedikit saja yang digunakan berdasarkan code tertentu. Pada method addUserBank() hanya menggunakan signIn(), addBank() dan signOut(). Pada method addUserAddress() hanya menggunakan signIn(), addAddress() dan signOut(). Dan pada method printUserName() hanya menggunakan signIn(), getUserName() dan signOut(). Antara method addAddress(), removeAddress(), getMainAddress(), serta getAddressList() memiliki kohesi yang rendah dan tidak saling terkait dengan method addBank(), removeBank() dan getBankList(). Artinya kedua kelompok method tersebut dapat dibagi lagi agar jadi lebih spesifik. Pelanggaran Interface Segregation Principle ini secara tidak langsung juga melannggar Single Responsibility Principle

Untuk itu interface UserGateway perlu dipecah menjadi beberapa sub-interface seperti berikut:

Interface UserGateway

public interface UserGateway{
	void signIn();
	void signOut();
	String getUserName();
}

Interface UserBankGateway

public interface UserBankGateway extends UserGateway{
	List<String> getBankList();
	boolean addBank(String bankName);
	boolean removeBank(String bankName);
}

Interface UserAddressGateway

public interface UserAddressGateway extends UserGateway{
	List<String> getAddressList();
	boolean addAddress(String address);
	boolean removeAddress(String address);
	String getMainAddress();
}

Sekarang code pada class UserProcessor hanya menerima parameter sesuai interface terkait. Jadinya seperti ini:

Class UserProcessor

public class UserProcessor{
	public void addUserBank(UserBankGateway userGateway){
		userGateway.signIn();
		userGateway.addBank("BCA");
		userGateway.signOut();
	}

	public void addUserAddress(UserAddressGateway userGateway){
		userGateway.signIn();
		userGateway.addAddress("Lubuk Sikarah");
		userGateway.signOut();
	}

	public void printUserName(UserGateway userGateway){
		userGateway.signIn();
		System.out.println("userName = " + userGateway.getUserName());
		userGateway.signOut();
	}
}

Dengan begitu nantinya implementasi dari UserAddressGateway ga harus override method yang berhubungan dengan perbankan, begitu juga bagi implementasi dari UserBankGateway yang ga harus override semua method yang berhubungan dengan alamat. Semuanya sesuai pada porsinya masing-masing

Hal yang sama berlaku pada Collection. Hierarchy interface Collection pada Java adalah salah satu contoh penggunaan Interface Segregation yang benar. Collection tersebut dipecah menjadi List, Queue, Deque, Set, dan NavigableSet. Seringkali developer hanya menggunakan List tanpa tau tujuan pasti mau diapakan elemen tersebut. Penggunaan List yang overuse kadang bermasalah saat objek yang diinginkan adalah objek dengan elemen yang unik dalam bentuk Set sehingga objeknya tidak interchangeable. Penjelasan lengkap mengenai Collection di Java juga udah gw bahas pada tulisan terpisah.

Dengan Interface Segregation, interface-nya jadi lebih spesifik tergantung dari kebutuhan yang diinginkan tanpa code yang tidak diperlukan. Jika yang dibutuhkan adalah gateway user yang berhubungan dengan perbankan gunakan UserBankGateway, jika yang dibutuhkan adalah gateway user yang berhubungan dengan alamat, maka gunakan UserAddressGateway. Kalau hanya butuh terkait identitas usernya saja secara umum maka gunakan hierarki paling tinggi, yaitu UserGateway. Gunakan interface yang spesifik untuk kasus yang spesifik dan gunakan interface yang paling general untuk kasus yang tidak terlalu spesifik.

Prinsip SOLID lainnya: