ISP (Interface Segregation Principle) — prinsip SOLID keempat yang menyatakan: klien tidak boleh bergantung pada metode yang tidak mereka gunakan. Prinsip ini dirumuskan oleh Robert Martin dalam konteks perancangan antarmuka untuk sistem berorientasi objek. Seperti yang dijelaskan dalam buku Clean Architecture (2017), prinsip pemisahan antarmuka mengharuskan pembuatan antarmuka yang terspesialisasi secara sempit daripada satu antarmuka universal, yang mengurangi ketergantungan dan menyederhanakan perubahan.
Poin Utama
ISP (Interface Segregation Principle) — prinsip pemisahan antarmuka yang melarang pembuatan antarmuka “gemuk” dengan metode yang tidak digunakan oleh semua klien. Daripada satu antarmuka dengan sepuluh metode, dirancang beberapa antarmuka kecil, masing-masing untuk kelompok kliennya sendiri.
Prinsip ini diperkenalkan oleh Robert Martin sebagai solusi untuk masalah “pencemaran antarmuka”, ketika sebuah kelas dipaksa mengimplementasikan metode yang tidak dibutuhkannya hanya karena metode tersebut dideklarasikan dalam antarmuka umum. Dalam bahasa dengan pengetikan statis, hal ini menghasilkan implementasi kosong atau pelemparan pengecualian — tanda langsung pelanggaran ISP.
ISP dan SRP saling melengkapi: SRP tentang tanggung jawab kelas, ISP tentang kontrak antarmuka. SRP mengatakan “satu kelas — satu alasan untuk berubah”, ISP mengatakan “satu antarmuka — satu skenario klien”. Bersama-sama mereka membentuk arsitektur modular di mana setiap elemen sistem memiliki batas yang jelas.
Fat Interface — antarmuka yang berisi lebih banyak metode daripada yang dibutuhkan klien tertentu. Misalnya, antarmuka Worker dengan metode work, eat, sleep. Robot pekerja seharusnya tidak mengimplementasikan eat dan sleep, tetapi dipaksa. Solusi — pemisahan menjadi Workable, Eatable, Sleepable. Setiap klien mendapatkan persis apa yang dibutuhkannya.
Dalam pengembangan mobile, antarmuka gemuk muncul dalam protokol delegate dan DataSource. Satu protokol dapat berisi metode untuk dua skenario berbeda (pengeditan + penampilan), meskipun layar tertentu hanya menggunakan salah satunya.
Implementasi ISP dimulai dengan analisis klien dari setiap antarmuka. Jika dua klien menggunakan rangkaian metode yang berbeda dari antarmuka yang sama — antarmuka harus dipecah. Setiap antarmuka baru mengelompokkan metode yang dipanggil bersama dalam satu skenario.
Mekanisme pemisahan: antarmuka asli dipecah menjadi beberapa antarmuka sempit, masing-masing mewarisi bagian umum (jika ada). Klien beralih ke ketergantungan pada antarmuka sempit yang diperlukan daripada antarmuka umum. Kelas yang mengimplementasikan antarmuka asli sekarang hanya mengimplementasikan antarmuka sempit yang benar-benar mereka butuhkan.
Penjelasan penting: tingkat pemisahan ditentukan oleh jumlah klien dan skenario mereka. ISP tidak mengharuskan pemisahan maksimal (mikro-antarmuka dengan satu metode). Ini akan menyebabkan kompleksitas yang berlebihan. Tujuannya adalah menghilangkan ketergantungan klien pada metode yang tidak perlu, bukan meminimalkan ukuran setiap antarmuka.
Tanda-tanda utama pelanggaran ISP meliputi: kelas yang mengimplementasikan antarmuka dengan metode kosong (implementasi fiktif), pelemparan pengecualian UnsupportedOperationException dalam implementasi, sejumlah besar parameter atau tipe kembalian yang tidak digunakan oleh sebagian klien, dan perubahan antarmuka yang sering yang hanya memengaruhi sebagian klien.
Dalam pengembangan Android, contoh tipikal pelanggaran ISP adalah antarmuka OnItemClickListener yang mencakup metode untuk klik, klik panjang, dan geser. Jika layar tertentu hanya menggunakan klik — metode lainnya tetap kosong. Solusi — pemisahan menjadi OnItemClickListener, OnItemLongClickListener, OnItemSwipeListener.
Dalam pengembangan iOS, pelanggaran ISP muncul dalam delegate UIKit: satu protokol berisi metode untuk berbagai keadaan komponen. UITableViewDelegate mencakup metode untuk penampilan, pemilihan, pengeditan, dan tindakan geser. Seringkali pengembang mengimplementasikan seluruh protokol dengan sepuluh metode kosong. Pemisahan menjadi beberapa protokol berdasarkan kelompok tanggung jawab menyelesaikan masalah.
Masalahnya tidak hanya pada estetika kode. Ketika antarmuka berubah (metode baru ditambahkan), semua kelas pengimplementasi harus diperbarui — bahkan yang tidak membutuhkan metode baru. Dalam pengembangan mobile dengan puluhan layar, ini menyebabkan perubahan berantai. ISP mengisolasi setiap klien dari perubahan yang tidak berkaitan dengannya.
Pelanggaran ISP implisit terjadi melalui parameter konfigurasi. Jika sebuah metode menerima objek dengan sejumlah besar bidang, sementara klien hanya menggunakan 2-3 di antaranya — ini adalah sinyal untuk pemisahan. Alternatif: beberapa metode khusus dengan serangkaian parameter minimal.
Dalam pengembangan Android, ISP dilanggar saat menggunakan satu SharedPreferencesManager untuk membaca dan menulis semua pengaturan aplikasi. Fragment yang hanya perlu membaca tema mendapatkan ketergantungan pada manajer global dengan puluhan metode untuk berbagai tipe data. Pemisahan menjadi ThemePreferenceProvider, AuthPreferenceProvider, FeatureFlagProvider — penerapan ISP di tingkat layanan konfigurasi. Setiap penyedia berisi tepat metode yang dibutuhkan kliennya.
Mari kita lihat contoh Android dengan antarmuka untuk bekerja dengan data. Pelanggaran ISP — satu antarmuka untuk semua operasi CRUD, meskipun tidak semua klien membutuhkan semua operasi.
// Pelanggaran ISP: antarmuka gemuk
interface UserRepository {
fun getAll(): List<User>
fun getById(id: Int): User
fun save(user: User)
fun delete(id: Int)
}
// Setelah penerapan ISP: antarmuka sempit
interface UserReader {
fun getAll(): List<User>
fun getById(id: Int): User
}
interface UserWriter {
fun save(user: User)
fun delete(id: Int)
}
// ReadOnlyViewModel tidak bergantung pada metode penulisan
class ReadOnlyViewModel(
private val reader: UserReader
)
Contoh iOS dengan pemisahan protokol untuk bekerja dengan media:
// Pelanggaran ISP: satu protokol untuk semua kerja media
protocol MediaService {
func play(url: URL)
func pause()
func stop()
func upload(data: Data) async -> URL
func download(url: URL) async -> Data
}
// Setelah ISP: pemisahan menjadi protokol berdasarkan tanggung jawab
protocol MediaPlayer {
func play(url: URL)
func pause()
func stop()
}
protocol MediaTransfer {
func upload(data: Data) async -> URL
func download(url: URL) async -> Data
}
// PlayerViewModel tidak bergantung pada metode pemuatan
class PlayerViewModel {
private let player: MediaPlayer
}
Kesimpulan praktis: ISP melindungi klien dari perubahan di bagian antarmuka yang tidak terkait dengan mereka. Pemisahan UserRepository menjadi UserReader dan UserWriter berarti perubahan di save tidak memengaruhi ReadOnlyViewModel dan sebaliknya. Setiap klien terisolasi dari fungsionalitas yang tidak digunakannya dan tidak memerlukan perubahan saat bagian lain dari sistem ditingkatkan.
ISP dan SRP — pasangan alami. SRP menentukan bahwa sebuah kelas harus memiliki satu alasan untuk berubah. ISP menerapkan logika yang sama pada antarmuka: sebuah antarmuka harus melayani satu skenario klien. Sebuah kelas dapat mengimplementasikan beberapa antarmuka sempit (masing-masing sesuai dengan satu tanggung jawab), yang lebih bersih daripada satu antarmuka gemuk dengan beberapa tanggung jawab.
ISP dan OCP juga terkait: antarmuka sempit lebih mudah diperluas. Penambahan metode baru ke antarmuka sempit hanya memengaruhi kliennya. Penambahan metode ke antarmuka gemuk memengaruhi semua klien — berpotensi melanggar OCP, jika klien dipaksa mengubah implementasi mereka.
ISP dan DIP bekerja bersama: DIP mengharuskan ketergantungan pada abstraksi. ISP membuat abstraksi ini sempit dan terfokus. Ketergantungan pada antarmuka lebar tetaplah ketergantungan pada abstraksi, tetapi abstraksi yang “buruk” dari sudut pandang ISP. Empat prinsip (SRP, OCP, ISP, DIP) membentuk “piramida modularitas”: SRP dan ISP menentukan batas, OCP dan DIP — cara perluasan dan pengikatan.
Arsitektur komponen dalam proyek mobile (modul, fitur, lapisan) mendapatkan manfaat dari ISP di tingkat API publik. Setiap modul mengekspor antarmuka sempit untuk konsumennya, bukan satu fasad umum. Ini memungkinkan perubahan implementasi internal modul tanpa memengaruhi konsumen yang hanya menggunakan sebagian dari fungsionalitasnya.
Dalam proyek Android dengan Clean Architecture, ISP diterapkan pada UseCase: setiap UseCase adalah antarmuka terpisah dengan satu metode invoke atau execute. Klien (ViewModel) hanya bergantung pada UseCase yang dibutuhkannya, bukan seluruh repositori. Ini membuat ketergantungan menjadi transparan dan dapat diuji.
Pertanyaan yang Sering Diajukan
Ya, pemisahan berlebihan mungkin terjadi. ISP tidak mengharuskan satu antarmuka per metode. Kriteria: adakah klien yang hanya membutuhkan sebagian dari metode antarmuka? Jika semua klien menggunakan semua metode — antarmuka tidak perlu dipecah. Tingkat pemisahan optimal ditentukan oleh skenario penggunaan nyata.
ISP di tingkat parameter berarti: fungsi tidak boleh menerima objek dengan sejumlah besar bidang jika hanya menggunakan sebagian darinya. Sebagai gantinya, hanya data yang diperlukan yang boleh diteruskan atau antarmuka khusus digunakan (misalnya, antarmuka Renderable daripada User lengkap).
LSP tentang pewarisan yang benar dan kompatibilitas perilaku subtipe. ISP tentang perancangan antarmuka: klien tidak boleh bergantung pada metode yang tidak mereka gunakan. LSP menjawab pertanyaan “dapatkah subkelas digunakan sebagai pengganti kelas dasar?”, ISP — “apakah klien membutuhkan seluruh antarmuka?”.
Antarmuka sempit menyederhanakan pembuatan objek mock: pengujian membuat mock dengan satu atau dua metode, bukan dengan sepuluh. Semakin sedikit metode dalam antarmuka, semakin mudah untuk menyimulasikan perilakunya. Ini mengurangi beban kognitif pengembang pengujian dan mengurangi kemungkinan kesalahan dalam logika mock.
Jika antarmuka stabil dan semua klien menggunakan semua metode — pemisahan berlebihan. Contoh tipikal: protokol UIKit yang dirancang oleh Apple. Memisahkannya berisiko karena UIKit mengharapkan implementasi delegate yang lengkap. Dalam kasus seperti itu, pelanggaran ISP dibenarkan oleh stabilitas API.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga