Prinsip Tanggung Jawab Tunggal didasarkan pada prinsip kohesi yang tinggi. Perbedaan antara keduanya adalah bahwa kelas yang sangat kohesif memiliki serangkaian tanggung jawab yang sangat terkait, sedangkan kelas yang mengikuti SRP hanya memiliki satu tanggung jawab.
Tetapi bagaimana kita menentukan apakah kelas tertentu memiliki serangkaian tanggung jawab dan dengan demikian hanya sangat kohesif, atau apakah hanya memiliki satu tanggung jawab dan dengan demikian mematuhi SRP? Dengan kata lain, bukankah itu lebih atau kurang subyektif, karena beberapa mungkin menganggap kelas sangat granular (dan karena itu akan percaya kelas mematuhi SRP), sementara yang lain mungkin menganggapnya tidak cukup granular?
design-patterns
single-responsibility
cohesion
pengguna1483278
sumber
sumber
Jawaban:
Mengapa ya itu sangat subyektif, dan itu adalah subjek dari banyak programmer, debat berwajah merah masuk ke.
Sebenarnya tidak ada satu jawaban pun, dan jawabannya mungkin berubah ketika perangkat lunak Anda menjadi lebih kompleks. Apa yang dulunya tugas tunggal yang didefinisikan dengan baik pada akhirnya dapat menjadi beberapa tugas yang tidak didefinisikan dengan baik. Itu selalu menggosok juga. Bagaimana Anda memilih cara yang tepat untuk membagi program menjadi tugas?
Tentang satu-satunya saran yang bisa saya berikan adalah ini: gunakan penilaian terbaik Anda (dan rekan kerja Anda). Dan ingat bahwa kesalahan dapat (biasanya) diperbaiki jika Anda menangkapnya segera.
sumber
Bob Martin (Paman Bob), yang berasal dari prinsip-prinsip PADAT di mana SRP adalah yang pertama, mengatakan tentang ini (saya parafrase, tidak dapat mengingat kata-kata yang sebenarnya):
Jika memiliki lebih dari satu alasan, itu tidak mematuhi SRP.
sumber
Saya bisa memberi Anda beberapa aturan praktis.
sumber
Prinsip Tanggung Jawab Tunggal mengatakan bahwa setiap modul perangkat lunak hanya memiliki satu alasan untuk berubah. Pada sebuah artikel baru-baru ini Paman Bob menjelaskan "alasan untuk berubah",
Lebih lanjut ia menjelaskan konsep dengan contoh DI SINI .
sumber
Untuk menjawab ini, mundur selangkah dan pertimbangkan niat prinsip tanggung jawab tunggal. Mengapa prinsip desain yang direkomendasikan di tempat pertama?
Tujuan dari prinsip ini adalah untuk "mengelompokkan" basis kode, sehingga kode yang berkaitan dengan "tanggung jawab" tunggal diisolasi dalam satu unit tunggal. Ini membuatnya lebih mudah untuk menemukan dan memahami kode, dan yang lebih penting, itu berarti bahwa perubahan pada "tanggung jawab" hanya akan berdampak pada satu unit kode saja.
Apa yang Anda benar-benar tidak pernah inginkan dalam suatu sistem adalah ketika satu peluang kecil menyebabkan beberapa bagian kode yang tampaknya tidak terkait gagal atau mengubah perilaku. SRP membantu mengisolasi bug dan perubahan.
Jadi, apa itu "tanggung jawab"? Itu adalah sesuatu yang bisa berubah secara independen dari perubahan lain. Katakanlah Anda memiliki program yang dapat menyimpan beberapa pengaturan ke file konfigurasi XML, dan dapat membacanya kembali dari file tersebut. Apakah ini satu tanggung jawab, atau "memuat" dan "menyelamatkan" dua tanggung jawab yang berbeda? Segala jenis perubahan pada format file atau struktur akan membutuhkan perubahan baik memuat dan menyimpan logika. Karena itu merupakan tanggung jawab tunggal yang harus diwakili oleh satu kelas. Sekarang pertimbangkan sebuah aplikasi yang dapat mengekspor beberapa data dalam format CVS, Excel dan XML. Dalam hal ini, mudah untuk membayangkan bahwa satu format dapat berubah tanpa memengaruhi lainnya. Jika Anda memutuskan untuk mengubah pembatas dalam format CVS, itu seharusnya tidak mempengaruhi output Excel.
sumber
OO mengatakan bahwa kelas adalah pengelompokan fungsionalitas data. Definisi ini menyisakan banyak ruang untuk interpretasi subyektif.
Kita tahu bahwa kelas harus didefinisikan dengan jelas dan mudah. Tetapi, untuk mendefinisikan kelas seperti itu, kita harus memiliki gagasan yang jelas tentang bagaimana kelas cocok dengan keseluruhan desain. Tanpa persyaratan jenis air terjun yang, secara paradoks, dianggap sebagai anti-pola ... ini sulit dicapai.
Kita dapat mengimplementasikan desain kelas dengan arsitektur yang berfungsi dalam banyak kasus, seperti MVC. Dalam aplikasi MVC, kami hanya berasumsi memiliki data, antarmuka pengguna, dan persyaratan untuk keduanya untuk berkomunikasi.
Dengan arsitektur dasar, lebih mudah untuk mengidentifikasi kasus di mana aturan tanggung jawab tunggal dilanggar. EG Melewati instance dari Kontrol Pengguna ke Modal.
sumber
Demi diskusi, saya akan memunculkan kelas dari JUCE bernama AudioSampleBuffer . Sekarang kelas ini ada untuk menyimpan potongan (atau mungkin potongan yang agak panjang) dari audio. Ia tahu jumlah saluran, jumlah sampel (per saluran), tampaknya berkomitmen untuk float IEEE 32-bit daripada memiliki representasi numerik variabel atau wordsize (tapi itu tidak masalah dengan saya). Ada fungsi anggota yang memungkinkan Anda untuk mendapatkan numChannels atau numSamples dan pointer ke saluran tertentu. Anda dapat membuat AudioSampleBuffer lebih lama atau lebih pendek. Saya menganggap yang pertama nol-bantalan buffer sementara yang kedua memotong.
Ada beberapa anggota pribadi dari kelas ini yang digunakan untuk mengalokasikan ruang di tumpukan khusus yang digunakan JUCE.
Tetapi inilah yang tidak ada pada AudioSampleBuffer (dan saya telah melakukan beberapa diskusi dengan Jules tentang hal itu): seorang anggota menelepon
SampleRate
. Bagaimana bisa melewatkan itu?Tanggung jawab tunggal yang harus dipenuhi oleh AudioSampleBuffer adalah merepresentasikan audio fisik yang didengar oleh sampel. Saat Anda memasukkan AudioSampleBuffer dari sesuatu yang membaca file suara atau dari aliran, ada parameter tambahan yang harus Anda dapatkan dan meneruskannya bersama AudioSampleBuffer ke metode pemrosesan (katakan itu filter) yang perlu mengetahui laju sampel atau, akhirnya, ke metode yang memutar buffer keluar untuk didengar (atau streaming ke tempat lain). Terserah.
Tapi yang harus Anda lakukan adalah terus meneruskan SampleRate ini, yang melekat pada kehidupan audio tertentu di AudioSampleBuffer, berkeliling ke mana-mana. Saya telah melihat kode di mana 44100.0f konstan dilewatkan ke suatu fungsi, karena programmer tampaknya tidak tahu harus berbuat apa lagi.
Ini adalah contoh kegagalan memenuhi tanggung jawab tunggal.
sumber
Cara konkret dapat dilakukan, berdasarkan pada apa yang Anda katakan - bahwa kohesi yang tinggi memikul tanggung jawab tunggal yang dapat Anda ukur kohesi. Kelas kohesif maksimal memiliki semua bidang yang digunakan dalam semua metode. Sementara kelas kohesif maksimal tidak selalu mungkin atau diinginkan untuk memiliki yang terbaik untuk mencapai ini. Memiliki tujuan desain kelas ini, cukup mudah untuk menyimpulkan bahwa kelas Anda tidak dapat memiliki banyak metode atau bidang (ada yang mengatakan paling banyak 7).
Cara lain adalah dari dasar-dasar murni OOP - model setelah benda nyata. Jauh lebih mudah untuk melihat tanggung jawab objek nyata. Namun, jika objek nyata terlalu kompleks, pilah menjadi beberapa objek yang saling bersaing, masing-masing memiliki tanggung jawab sendiri.
sumber