author-pic

Ferry S

An ISTJ, Type 5, Engineer, Gamer, and Thriller-Movies-Lover
Prinsip Interface Segregation
Monday Nov 9th, 2020 01:23 am4 mins read
Java, Programming Principle, Tips & Tutorial
Prinsip Interface Segregation
Source: Infurnia - Why waste segregation is good

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, 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.

Pelanggaran Interface Segregation Principle

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

Solusi

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 turunan dari UserAddressGateway ga harus override method yang berhubungan dengan perbankan, begitu juga sebaliknya. Semuanya sesuai pada porsinya masing-masing

Interface Segregation di Library Java

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, Set, SortedSet, 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.

Rule of thumb:

  • Jika yang dibutuhkan adalah kumpulan elemen tanpa duplikasi maka gunakan Set
  • Jika yang dibutuhkan adalah kumpulan elemen yang memperbolehkan duplikasi maka gunakan List.
  • Set pun terbagi lagi jadi SortedSet dan NavigableSet. Jika Set yang dibutuhkan adalah yang berurutan maka gunakan SortedSet
  • Jika Set yang dibutuhkan adalah yang berurutan dan dapat dinavigasikan maka gunakan NavigableSet.
  • Begitu juga jika behavior yang dibutuhkan tidak terlalu spesifik, seperti hanya melakukan penambahan dan perulangan elemen saja, maka gunakan Collection. Jadi objeknya interchangeable, bisa menggunakan turunan List atau Set.

Kesimpulan

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 gunakan hierarki paling tinggi, yaitu UserGateway. Gunakan interface yang spesifik untuk kasus yang spesifik dan gunakan interface yang paling abstrak untuk kasus yang tidak terlalu spesifik.

Prinsip SOLID lainnya: