Prinsip tanggung jawab tunggal didefinisikan di wikipedia sebagai
Prinsip tanggung jawab tunggal adalah prinsip pemrograman komputer yang menyatakan bahwa setiap modul, kelas, atau fungsi harus memiliki tanggung jawab atas satu bagian dari fungsi yang disediakan oleh perangkat lunak, dan bahwa tanggung jawab harus sepenuhnya dienkapsulasi oleh kelas.
Jika suatu kelas hanya memiliki satu tanggung jawab, bagaimana ia dapat memiliki lebih dari 1 metode? Tidakkah setiap metode memiliki tanggung jawab yang berbeda, yang kemudian berarti bahwa kelas akan memiliki lebih dari 1 tanggung jawab.
Setiap contoh yang saya lihat menunjukkan prinsip tanggung jawab tunggal menggunakan kelas contoh yang hanya memiliki satu metode. Mungkin membantu untuk melihat contoh atau memiliki penjelasan tentang kelas dengan beberapa metode yang masih dapat dianggap memiliki satu tanggung jawab.
sumber
Jawaban:
Tanggung jawab tunggal mungkin bukan sesuatu yang dapat dipenuhi fungsi tunggal.
Kelas ini dapat melanggar prinsip tanggung jawab tunggal. Bukan karena memiliki dua fungsi, tetapi jika kode untuk
getX()
dangetY()
harus memenuhi pemangku kepentingan yang berbeda yang mungkin menuntut perubahan. Jika Wakil Presiden Tn. X mengirim sekitar memo bahwa semua angka akan dinyatakan sebagai angka titik mengambang dan Direktur Akuntansi Ny. Y menegaskan bahwa semua angka yang ditinjau oleh departemennya akan tetap bilangan bulat terlepas dari apa yang dipikirkan dengan baik oleh Tn maka kelas ini sebaiknya memiliki satu ide tentang siapa yang bertanggung jawab karena semuanya akan membingungkan.Jika SRP telah diikuti, akan menjadi jelas jika kelas Lokasi berkontribusi untuk hal-hal yang diungkapkan oleh X dan kelompoknya. Perjelas apa yang menjadi tanggung jawab kelas dan Anda tahu arahan apa yang mempengaruhi kelas ini. Jika keduanya berdampak pada kelas ini maka itu dirancang dengan buruk untuk meminimalkan dampak perubahan. "Kelas seharusnya hanya memiliki satu alasan untuk berubah" tidak berarti seluruh kelas hanya dapat melakukan satu hal kecil. Itu berarti saya seharusnya tidak dapat melihat kelas dan mengatakan bahwa Tuan X dan Ny. Y memiliki ketertarikan pada kelas ini.
Selain hal-hal seperti itu. Tidak, banyak metode baik-baik saja. Berikan saja nama yang menjelaskan metode apa yang termasuk dalam kelas dan apa yang tidak.
SRP Paman Bob lebih tentang Hukum Conway daripada Hukum Curly . Paman Bob menganjurkan menerapkan Hukum Curly (melakukan satu hal) untuk fungsi bukan kelas. SRP memperingatkan terhadap pencampuran alasan untuk berubah bersama. Hukum Conway mengatakan sistem akan mengikuti bagaimana arus informasi organisasi. Itu mengarah pada mengikuti SRP karena Anda tidak peduli dengan apa yang tidak pernah Anda dengar.
Orang-orang terus menginginkan SRP menjadi alasan untuk membatasi ruang lingkup. Ada lebih banyak alasan untuk membatasi ruang lingkup daripada SRP. Saya selanjutnya membatasi ruang lingkup dengan menegaskan bahwa kelas adalah abstraksi yang dapat mengambil nama yang memastikan bahwa melihat ke dalam tidak akan mengejutkan Anda .
Anda bisa menerapkan Hukum Curly ke kelas. Anda di luar apa yang Paman Bob bicarakan tetapi Anda bisa melakukannya. Di mana Anda salah adalah ketika Anda mulai berpikir itu berarti satu fungsi. Itu seperti berpikir keluarga seharusnya hanya memiliki satu anak. Memiliki lebih dari satu anak tidak menghentikannya menjadi keluarga.
Jika Anda menerapkan hukum Curly ke kelas, semua yang ada di kelas harus tentang satu ide pemersatu. Gagasan itu bisa luas. Idenya mungkin kegigihan. Jika beberapa fungsi utilitas logging ada di sana, maka mereka jelas tidak pada tempatnya. Tidak masalah jika Mr X adalah satu-satunya yang peduli dengan kode ini.
Prinsip klasik untuk diterapkan di sini disebut Pemisahan Kekhawatiran . Jika Anda memisahkan semua kekhawatiran Anda, dapat dikatakan bahwa yang tersisa di satu tempat adalah satu perhatian. Itulah yang kami sebut ide ini sebelum film 1991 City Slickers memperkenalkan kami pada karakter Curly.
Ini baik Hanya saja apa yang Paman Bob sebut sebagai tanggung jawab bukan masalah. Tanggung jawab kepadanya bukanlah sesuatu yang Anda fokuskan. Itu adalah sesuatu yang bisa memaksa Anda untuk berubah. Anda dapat fokus pada satu masalah dan masih membuat kode yang bertanggung jawab kepada berbagai kelompok orang dengan agenda berbeda.
Mungkin Anda tidak peduli tentang itu. Baik. Berpikir bahwa memegang untuk "melakukan satu hal" akan menyelesaikan semua kesengsaraan desain Anda menunjukkan kurangnya imajinasi tentang apa yang "satu hal" dapat akhirnya menjadi. Alasan lain untuk membatasi ruang lingkup adalah organisasi. Anda dapat membuat banyak "satu hal" di dalam yang lain "satu hal" sampai Anda memiliki laci sampah penuh dengan segalanya. Saya sudah membicarakan hal itu sebelumnya
Tentu saja alasan klasik OOP untuk membatasi ruang lingkup adalah karena kelas memiliki bidang pribadi di dalamnya dan alih-alih menggunakan getter untuk membagikan data tersebut, kami menempatkan setiap metode yang membutuhkan data tersebut di kelas tempat mereka dapat menggunakan data secara pribadi. Banyak yang menemukan ini terlalu ketat untuk digunakan sebagai batasan ruang lingkup karena tidak setiap metode yang dimiliki bersama menggunakan bidang yang sama persis. Saya ingin memastikan bahwa ide apa pun yang menyatukan data menjadi ide yang sama yang menyatukan metode.
Cara fungsional untuk melihat ini adalah
a.f(x)
dana.g(x)
hanya f a (x) dan g a (x). Bukan dua fungsi tetapi rangkaian pasangan fungsi yang berbeda-beda. Thea
bahkan tidak harus memiliki data di dalamnya. Itu bisa saja bagaimana Anda tahu manaf
dang
implementasi yang akan Anda gunakan. Fungsi yang berubah bersama menjadi satu. Itu polimorfisme lama yang bagus.SRP hanyalah salah satu dari banyak alasan untuk membatasi ruang lingkup. Itu bagus. Tapi bukan satu-satunya.
sumber
Kuncinya di sini adalah ruang lingkup , atau, jika Anda suka, rincian . Bagian dari fungsionalitas yang diwakili oleh kelas dapat lebih jauh dipisahkan menjadi bagian-bagian fungsionalitas, masing-masing bagian menjadi metode.
Ini sebuah contoh. Bayangkan Anda perlu membuat CSV dari suatu urutan. Jika Anda ingin mematuhi RFC 4180, akan butuh beberapa waktu untuk mengimplementasikan algoritme dan menangani semua kasing tepi.
Melakukannya dalam metode tunggal akan menghasilkan kode yang tidak akan mudah dibaca, dan terutama, metode ini akan melakukan beberapa hal sekaligus. Karena itu, Anda akan membaginya menjadi beberapa metode; misalnya, salah satu dari mereka mungkin bertanggung jawab untuk menghasilkan header, yaitu baris pertama CSV, sementara metode lain akan mengonversi nilai tipe apa pun menjadi representasi string yang cocok untuk format CSV, sementara yang lain akan menentukan apakah nilai harus dimasukkan ke dalam tanda kutip ganda.
Metode-metode itu memiliki tanggung jawab mereka sendiri. Metode yang memeriksa apakah ada kebutuhan untuk menambahkan tanda kutip ganda atau tidak memiliki sendiri, dan metode yang menghasilkan header memiliki satu. Ini adalah SRP yang diterapkan pada metode .
Sekarang, semua metode tersebut memiliki satu tujuan yang sama, yaitu, mengambil urutan, dan menghasilkan CSV. Ini adalah tanggung jawab tunggal kelas .
Pablo H berkomentar:
Memang. Contoh CSV yang saya berikan idealnya memiliki satu metode publik dan semua metode lainnya bersifat pribadi. Contoh yang lebih baik adalah dari antrian, diimplementasikan oleh
Queue
kelas. Kelas ini pada dasarnya berisi dua metode:push
(juga disebutenqueue
), danpop
(juga disebutdequeue
).Tanggung jawabnya
Queue.push
adalah menambahkan objek ke ekor antrian.Tanggung jawabnya
Queue.pop
adalah untuk menghapus objek dari kepala antrian, dan menangani kasus di mana antrian kosong.Tanggung jawab
Queue
kelas adalah menyediakan logika antrian.sumber
Fungsi adalah fungsi.
Tanggung jawab adalah tanggung jawab.
Seorang mekanik memiliki tanggung jawab untuk memperbaiki mobil, yang akan melibatkan diagnostik, beberapa tugas perawatan sederhana, beberapa pekerjaan perbaikan aktual, beberapa pendelegasian tugas kepada orang lain, dll.
Kelas kontainer (daftar, array, kamus, peta, dll) memiliki tanggung jawab untuk menyimpan objek, yang melibatkan menyimpannya, memungkinkan penyisipan, menyediakan akses, semacam pemesanan, dll.
Tanggung jawab tunggal tidak berarti hanya ada sedikit kode / fungsionalitas, itu berarti fungsi apa pun yang ada "milik bersama" di bawah tanggung jawab yang sama.
sumber
Tanggung jawab tunggal tidak selalu berarti hanya melakukan satu hal.
Ambil contoh kelas layanan Pengguna:
Kelas ini memiliki banyak metode tetapi tanggung jawabnya jelas. Ini memberikan akses ke catatan pengguna di penyimpanan data. Satu-satunya dependensi adalah model Pengguna dan penyimpanan data. Ini secara longgar digabungkan dan sangat kohesif, yang sebenarnya adalah apa yang SRP coba untuk membuat Anda berpikir.
SRP tidak harus bingung dengan "Prinsip pemisahan antarmuka" (lihat SOLID ). Prinsip Segregasi Antarmuka (ISP) mengatakan bahwa antarmuka yang lebih kecil dan ringan lebih disukai daripada antarmuka yang lebih umum. Go menggunakan banyak ISP di seluruh perpustakaan standarnya:
SRP dan ISP tentu terkait, tetapi yang satu tidak menyiratkan yang lain. ISP ada di level antarmuka dan SRP ada di level kelas. Jika suatu kelas mengimplementasikan beberapa antarmuka sederhana, itu mungkin tidak lagi hanya memiliki satu tanggung jawab.
Terima kasih kepada Luaan karena menunjukkan perbedaan antara ISP dan SRP.
sumber
UserService
danUser
akan UpperCamelCase, tetapi metodeCreate
,Exists
danUpdate
saya akan membuat lowerCamelCase.Ada seorang koki di sebuah restoran. Satu-satunya tanggung jawabnya adalah memasak. Namun dia bisa memasak steak, kentang, brokoli, dan ratusan hal lainnya. Apakah Anda akan menyewa satu koki per hidangan di menu Anda? Atau satu koki untuk setiap komponen setiap hidangan? Atau seorang koki yang dapat memenuhi tanggung jawabnya sendiri: Untuk memasak?
Jika Anda meminta koki itu untuk melakukan penggajian juga, saat itulah Anda melanggar SRP.
sumber
Contoh tandingan: menyimpan status yang dapat diubah.
Misalkan Anda memiliki kelas paling sederhana yang pernah ada, yang tugasnya hanya menyimpan
int
.Jika Anda dibatasi hanya 1 metode, Anda bisa memiliki
setState()
, atau agetState()
, kecuali jika Anda memecahkan enkapsulasi dan membuati
publik.Jadi jelas, tanggung jawab tunggal ini mengharuskan memiliki setidaknya 2 metode di kelas ini. QED.
sumber
Anda salah mengartikan prinsip tanggung jawab tunggal.
Tanggung jawab tunggal tidak sama dengan metode tunggal. Mereka memiliki arti yang berbeda. Dalam pengembangan perangkat lunak kita berbicara tentang kohesi . Fungsi (metode) yang memiliki kohesi tinggi "milik" bersama dan dapat dihitung sebagai melakukan tanggung jawab tunggal.
Terserah pengembang untuk merancang sistem sehingga prinsip tanggung jawab tunggal terpenuhi. Orang dapat melihat ini sebagai teknik abstraksi dan karena itu kadang-kadang masalah pendapat. Menerapkan prinsip tanggung jawab tunggal membuat kode terutama lebih mudah untuk diuji dan lebih mudah untuk memahami arsitektur dan desainnya.
sumber
Seringkali bermanfaat (dalam bahasa apa pun, tetapi terutama dalam bahasa OO) untuk melihat berbagai hal dan mengaturnya dari sudut pandang data alih-alih fungsinya.
Dengan demikian, pertimbangkan tanggung jawab kelas untuk menjaga integritas dan memberikan bantuan untuk menggunakan data yang dimilikinya. Jelas ini lebih mudah dilakukan jika semua kode berada dalam satu kelas, daripada tersebar di beberapa kelas. Menambahkan dua poin lebih dapat dilakukan dengan andal, dan kode lebih mudah dipelihara, dengan
Point add(Point p)
metode diPoint
kelas daripada memilikinya di tempat lain.Dan khususnya, kelas tidak boleh mengekspos apa pun yang dapat menghasilkan data yang tidak konsisten atau salah. Misalnya, jika a
Point
harus terletak di dalam bidang (0,0) hingga (127.127), konstruktor dan metode apa pun yang memodifikasi atau menghasilkan yang baruPoint
memiliki tanggung jawab memeriksa nilai yang diberikan dan menolak perubahan apa pun yang akan melanggar ini kebutuhan. (Seringkali sesuatu seperti aPoint
akan berubah, dan memastikan bahwa tidak ada cara untuk memodifikasiPoint
setelah itu dibangun maka juga akan menjadi tanggung jawab kelas)Perhatikan bahwa layering di sini sangat bisa diterima. Anda mungkin memiliki
Point
kelas untuk berurusan dengan poin individu danPolygon
kelas untuk berurusan dengan satu setPoint
s; ini masih memiliki tanggung jawab terpisah karenaPolygon
mendelegasikan semua tanggung jawab untuk berurusan dengan apa pun yang semata-mata berkaitan denganPoint
(seperti memastikan suatu poin memiliki nilaix
dany
nilai) kePoint
kelas.sumber