SRP (Single Responsibility Principle) — prinsip pertama SOLID yang menentukan: setiap kelas atau modul harus memiliki tepat satu alasan untuk berubah. Prinsip ini dirumuskan oleh Robert Martin dalam buku Clean Architecture (2017) dan menjadi fondasi perancangan modular. Menurut buku ini, penerapan SRP secara langsung mengurangi keterikatan antar komponen dan menghilangkan perubahan berantai saat penyempurnaan fungsionalitas.
Poin Utama
SRP (Single Responsibility Principle) — prinsip tanggung jawab tunggal yang menyatakan: setiap kelas atau modul harus memiliki tepat satu alasan untuk berubah. Ini tidak berarti bahwa kelas harus melakukan tepat satu operasi. Yang dimaksud adalah sekelompok tindakan terkait yang disatukan oleh satu tanggung jawab terhadap satu aktor.
Robert Martin merumuskan ulang SRP dalam istilah aktor: kelas harus berubah hanya atas permintaan satu pihak yang berkepentingan atau satu kelompok orang. Jika dua aktor berbeda meminta perubahan pada kelas yang sama — tanggung jawab tidak dibagi dengan benar.
Misalnya, kelas Employee yang secara bersamaan menghitung gaji (permintaan akuntansi) dan membuat laporan (permintaan manajemen) melanggar SRP. Perubahan aturan perhitungan dapat mempengaruhi pembuatan laporan dan sebaliknya.
Modul harus memiliki satu dan hanya satu alasan untuk berubah. Alasan perubahan ditentukan oleh aktor — orang atau sistem yang menginisiasi kebutuhan. Jika kebutuhan dari aktor berbeda mengarah pada perubahan satu modul — modul melanggar SRP.
Konsep aktor menjadikan SRP alat praktis untuk analisis arsitektur, bukan rekomendasi abstrak. Saat merancang sistem, cukup bertanya: “Siapa yang akan meminta perubahan kode ini?” — jika jawabannya mencakup lebih dari satu pihak yang berkepentingan, tanggung jawab harus dibagi.
Tanggung jawab tunggal diwujudkan melalui pengelompokan metode yang berubah karena satu alasan. Kelas menjadi “titik kumpul” logika terkait, bukan “pisau Swiss” untuk segala keperluan. Ini menyederhanakan pemahaman kode: pengembang melihat kelas dan langsung memahami tujuannya.
Mekanisme kerja SRP didasarkan pada aturan satu sumbu perubahan. Jika fungsionalitas dapat berubah karena alasan independen — harus dipindahkan ke kelas terpisah. Hubungan antar kelas ini dibangun melalui komposisi atau delegasi.
Pelanggaran SRP muncul dalam “kelas dewa” (God Objects) yang berisi puluhan metode yang bekerja dengan data berbeda. Kelas seperti itu sulit diuji — pengujian satu metode memerlukan konfigurasi lingkungan untuk semua metode lainnya. Perubahan satu tanggung jawab dapat merusak yang lain, membuat kode menjadi rapuh.
Dalam praktiknya, SRP membantu pengembang menjawab pertanyaan “di mana kode ini?”. Jika setiap tanggung jawab dipisahkan ke dalam kelasnya sendiri, menemukan file yang diperlukan hanya membutuhkan waktu detik. Dalam proyek Android dengan arsitektur MVVM, ini berarti UserViewModel hanya bertanggung jawab atas status layar pengguna, dan UserRepository bertanggung jawab atas pengambilan data. Pengembang yang mencari logika cache pergi ke UserCacheRepository, bukan ke ViewModel. Organisasi kode seperti ini mempercepat orientasi anggota tim baru dan mengurangi jumlah kesalahan saat refactoring.
Pengembangan mobile menuntut modularitas kode yang tinggi. Android Fragment atau iOS ViewController sering menjadi “titik tarik” logika: penanganan klik, panggilan API, parsing respons, pembaruan UI — semuanya dalam satu kelas. SRP memerlukan pemisahan tanggung jawab ini.
Dalam arsitektur Android, SRP tertanam dalam rekomendasi Google untuk Jetpack: ViewModel bertanggung jawab atas status layar, Repository untuk data, UseCase untuk logika bisnis. Setiap komponen memiliki satu alasan untuk berubah. Dalam pengembangan iOS, pola MVVM dan Coordinator mengikuti logika yang sama.
Kepatuhan terhadap SRP dalam proyek mobile memberikan keuntungan terukur: pengurangan ukuran kelas sebesar 40-60%, pemendekan waktu code review, dan pengurangan jumlah bug regresi saat menambahkan fungsionalitas baru. Modul yang terisolasi lebih mudah dicakup dengan unit test dan digunakan kembali di layar lain.
Unit test untuk kelas yang mematuhi SRP membutuhkan lebih sedikit objek mock dan konfigurasi. Jika kelas memiliki satu tanggung jawab, dependensinya terbatas. Pengujian memeriksa satu perilaku, bukan kombinasi dari beberapa skenario yang tidak terkait.
Menurut laporan Google Testing Blog (2023), kelas dengan tanggung jawab tunggal menunjukkan cakupan pengujian 35% lebih tinggi dibandingkan dengan kelas agregator. Pengembang lebih bersedia menulis tes untuk modul kecil yang mudah dipahami.
Perhatikan kelas Android tipikal yang melanggar SRP — ia memuat data, memparsing respons, dan memperbarui UI. Setelah refactoring, setiap tanggung jawab dipisahkan ke dalam komponen tersendiri.
// Pelanggaran SRP: satu kelas melakukan semuanya
class BadUserProfileActivity {
fun loadUser(userId: Int) {
// Permintaan HTTP
// Parsing JSON
// Pembaruan UI
// Penyimpanan ke database
}
}
// Setelah penerapan SRP
class UserRepository {
fun getUser(userId: Int): User
}
class UserViewModel {
private val repo: UserRepository
fun loadUser(userId: Int) { }
}
class UserProfileFragment {
fun render(user: User) { }
}
Contoh serupa pada iOS Swift dengan pemisahan lapisan jaringan dan lapisan presentasi:
// Pelanggaran SRP: ViewController mengelola data dan UI
class BadProfileViewController: UIViewController {
func viewDidLoad() {
// Permintaan URLSession
// Decode JSON
// Pembaruan label
}
}
// Setelah penerapan SRP
protocol UserServiceProtocol {
func fetchUser(id: Int) async throws -> User
}
class ProfileViewModel {
private let service: UserServiceProtocol
func loadProfile(id: Int) { }
}
class ProfileViewController: UIViewController {
func display(user: User) { }
}
Refactoring SRP tidak memperumit arsitektur — ia mendistribusikan ulang tanggung jawab. Jumlah kode bahkan bisa berkurang dengan menghilangkan duplikasi. Setiap kelas baru memiliki tujuan yang jelas dan dapat dikembangkan secara independen.
Komposisi membantu mematuhi SRP di mana pewarisan menciptakan keterikatan yang tidak perlu. Alih-alih superclass dengan puluhan metode, subclass menerima sekumpulan objek khusus melalui konstruktor. Setiap objek bertanggung jawab atas fungsionalitasnya sendiri.
Dalam pengembangan Android, pola Decorator memungkinkan penambahan tanggung jawab tanpa mengubah kelas asli. Di iOS, rantai Middleware dalam lapisan jaringan membagi logging, caching, dan autentikasi ke dalam modul terpisah.
Pelanggaran paling umum — “God Class”: kelas yang mengelola database, mengirim notifikasi, menghasilkan laporan, dan memproses input pengguna. Kelas seperti itu menjadi hambatan proyek: setiap perubahan memerlukan pengujian regresi lengkap.
Dalam pengembangan mobile, pelanggaran SRP disebabkan oleh pencampuran logika bisnis dan logika UI di Activity, Fragment, atau ViewController. Ketika metode onClickListener secara bersamaan memvalidasi data, memanggil API, dan memperbarui visibilitas tombol — ini adalah pelanggaran langsung terhadap prinsip tanggung jawab tunggal.
Konsekuensi pelanggaran SRP meliputi: kesulitan pengembangan paralel (konflik dalam satu file), unit testing yang sulit, biaya perubahan yang tinggi, dan penurunan keterbacaan kode. Proyek dengan pelanggaran SRP sistematis membutuhkan 2-3 kali lebih banyak waktu untuk menambahkan fungsionalitas baru.
Pelanggaran SRP dapat ditentukan dari tanda tidak langsung: kelas berisi lebih dari 200 baris, mengimpor modul dari lapisan aplikasi yang berbeda (UI + network + database), memiliki lebih dari 5 metode publik dengan topik berbeda. Metrik kohesi — indikator statistik: kohesi rendah metode di dalam kelas menunjukkan pelanggaran SRP.
Untuk mendeteksi pelanggaran SRP, berguna menggunakan alat analisis statis: untuk Android — Detekt dengan aturan TooManyFunctions, untuk iOS — SwiftLint dengan aturan file_length. Alat-alat ini menyoroti kelas yang melebihi batas ukuran dan kompleksitas.
Refactoring kelas yang melanggar SRP dilakukan melalui Extract Class atau Extract Delegate: sekelompok metode terkait dipindahkan ke kelas terpisah, dan kelas asli mendelegasikan panggilan ke mereka. Penerapan bertahap refactoring semacam itu mengubah “God Class” menjadi sekumpulan modul dengan keterikatan longgar, masing-masing dengan satu tanggung jawab. Pendekatan seperti ini memungkinkan peningkatan arsitektur tanpa menghentikan pengembangan — refactoring dilakukan secara iteratif, satu modul pada satu waktu.
Pertanyaan yang Sering Diajukan
Tidak. SRP bukan tentang jumlah metode, melainkan tentang jumlah alasan untuk berubah. Sebuah kelas dapat memiliki sepuluh metode jika semuanya melayani satu tanggung jawab terhadap satu aktor. Satu metode — adalah ekstrem lain yang menyebabkan fragmentasi kode yang berlebihan.
Ini adalah prinsip yang sama. Single Responsibility Principle diterjemahkan baik sebagai “tanggung jawab tunggal” maupun “kewajiban tunggal”. Istilah “tanggung jawab” lebih tepat mencerminkan esensi: ini tentang tanggung jawab terhadap aktor, bukan tentang fungsi teknis.
Repository — hasil langsung dari penerapan SRP ke lapisan data. Alih-alih menyebarkan logika akses data ke ViewModel atau UseCase, Repository mengambil satu tanggung jawab: menyediakan data dengan abstraksi sumber. Ini adalah implementasi klasik SRP dalam arsitektur mobile.
Ya, SRP tidak melarang dependensi. Kelas dengan satu tanggung jawab dapat mendelegasikan sebagian pekerjaan ke kelas lain melalui komposisi. Penting bahwa tugas yang didelegasikan ini adalah bagian dari tanggung jawab yang sama, bukan alasan independen untuk berubah.
Ajukan pertanyaan: “Aktor mana yang mungkin meminta perubahan pada kelas ini?” Jika jawabannya mencakup lebih dari satu aktor — SRP dilanggar. Tambahan: coba deskripsikan tujuan kelas dalam satu kalimat tanpa kata sambung “dan”. Jika tidak berhasil — kelas melakukan terlalu banyak hal.
Kesimpulan
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