Jika Anda memiliki kelas yang mewarisi dari dua kelas yang berbeda, bukankah ini berarti bahwa subkelas Anda secara otomatis melakukan (setidaknya) 2 hal, satu dari setiap superclass?
Saya percaya tidak ada perbedaan jika Anda memiliki beberapa antarmuka warisan.
Sunting: Agar jelas, saya percaya bahwa jika subkelas banyak kelas melanggar SRP, maka mengimplementasikan beberapa (non-penanda atau antarmuka dasar (misalnya Sebanding)) antarmuka juga melanggar SRP.
Jawaban:
Dalam arti yang sangat sempit, jawabannya adalah "Ya": dengan asumsi bahwa kelas dasar atau antarmuka Anda dirancang untuk satu tujuan, mewarisi keduanya menciptakan kelas dengan banyak tanggung jawab. Namun, apakah itu "hal buruk" tergantung pada sifat dari kelas atau antarmuka yang Anda warisi.
Anda dapat mempartisi kelas dan antarmuka Anda menjadi dua kelompok besar - yang membahas kompleksitas esensial sistem Anda, dan yang membahas kompleksitas yang tidak disengaja. Jika mewarisi dari lebih dari satu kelas "kompleksitas esensial", itu buruk; jika Anda mewarisi dari satu kelas "esensial" dan satu atau lebih "tidak disengaja", tidak apa-apa.
Misalnya, dalam sistem penagihan, Anda dapat memiliki kelas untuk mewakili faktur dan siklus penagihan (mereka mengatasi kompleksitas esensial) dan kelas untuk objek yang bertahan lama (mereka membahas kompleksitas yang tidak disengaja). Jika Anda mewarisi seperti ini
itu buruk: Anda
BillingCycleInvoice
memiliki tanggung jawab yang beragam karena berkaitan dengan kompleksitas esensial dari sistem.Di sisi lain, jika Anda mewarisi seperti ini
kelas Anda OK: secara teknis, ini melayani dua masalah sekaligus, tetapi karena hanya satu di antaranya yang penting, Anda dapat menghapus warisan yang tidak disengaja sebagai "biaya berbisnis".
sumber
SRP adalah pedoman untuk menghindari kelas dewa, yang buruk, tetapi juga bisa dianggap terlalu harfiah dan proyek memulai balon dengan banyak kelas yang tidak dapat benar-benar melakukan apa-apa tanpa sedikit pun digabungkan. Multiple inheritance / multiple interfaces dapat menjadi pertanda kelas menjadi terlalu besar, tetapi itu juga bisa menjadi pertanda bahwa fokus Anda terlalu terperinci untuk tugas yang dihadapi dan solusi Anda terlalu direkayasa, atau bisa juga dengan sempurna kasus penggunaan yang valid untuk pewarisan berganda dan kekhawatiran Anda tidak berdasar.
Desain perangkat lunak adalah seni dan ilmu pengetahuan, yang merupakan tindakan penyeimbang dari banyak kepentingan yang bersaing. Kita memiliki aturan untuk membantu menghindari hal-hal yang kita tahu jauh di satu arah yang menyebabkan masalah, tetapi aturan itu bisa dengan mudah membawa kita ke tempat yang sama buruk atau lebih buruk daripada apa yang kita coba hindari di tempat pertama.
sumber
Agak. Mari kita fokus pada prinsip utama untuk SRP:
Warisan berganda tidak memaksakan ini, tetapi cenderung mengarah ke sana. Jika kelas menimpa atau mengimplementasikan kelas dasarnya, itu cenderung menjadi lebih banyak alasan untuk mengubahnya. Dengan cara ini, interface multiple inheritance cenderung lebih merepotkan daripada class inheritance. Jika dua kelas diwarisi tetapi tidak diganti, maka alasan untuk mengubah ada di kelas dasar bukan kelas baru.
Tempat-tempat di mana pewarisan berganda tidak melanggar SRP adalah ketika semua kecuali satu dari tipe dasar bukanlah sesuatu yang diterapkan oleh kelas, tetapi bertindak sebagai sifat yang dimiliki oleh kelas tersebut. Pertimbangkan
IDisposable
dalam C #. Hal-hal yang sekali pakai tidak memiliki dua tanggung jawab, antarmuka hanya bertindak sebagai pandangan ke kelas yang memiliki sifat tersebut tetapi memiliki tanggung jawab yang jelas berbeda.sumber
Tidak menurut saya. Bagi saya, satu tanggung jawab adalah "memodelkan pengguna aplikasi saya". Saya mungkin perlu mengirimkan data itu melalui layanan web, dan menyimpannya dalam basis data relasional. Saya bisa menyediakan fungsionalitas itu dengan mewarisi beberapa kelas campuran.
Itu tidak berarti kelas memiliki tiga tanggung jawab. Ini berarti bahwa bagian dari tanggung jawab untuk memodelkan pengguna memerlukan serialisasi dan kegigihan yang mendukung.
sumber
Tidak semuanya. Di Jawa, Anda dapat memiliki antarmuka yang mewakili semacam objek domain - Foo, misalnya. Mungkin perlu dibandingkan dengan objek Foo lainnya, dan itu mengimplementasikan Comparable (dengan logika perbandingan dieksternalisasi dalam kelas Comparator); mungkin objek ini juga perlu Serializable, sehingga dapat diangkut melalui jaringan; dan mungkin harus Cloneable. Dengan demikian kelas mengimplementasikan tiga antarmuka tetapi tidak memiliki logika di dalamnya untuk mendukung mereka di luar yang didukung oleh Foo.
Yang mengatakan, itu konyol untuk mengambil SRP secara ekstrem. Jika kelas mendefinisikan lebih dari satu metode, apakah itu melanggar SRP? Semua Objek Java memiliki metode toString () dan metode equals (Obyek), yang berarti SETIAP objek di Jawa bertanggung jawab atas persamaan dan representasi diri. Itu adalah hal yang buruk?
sumber
Saya kira itu tergantung pada bagaimana Anda mendefinisikan tanggung jawab. Dalam contoh iostream klasik itu tidak melanggar SRP. IOstream bertanggung jawab untuk mengelola satu aliran dua arah.
Setelah Anda kehabisan tanggung jawab primitif, Anda beralih ke tanggung jawab tingkat tinggi yang lebih umum, setelah semua bagaimana Anda mendefinisikan tanggung jawab titik masuk utama Anda? Tanggung jawabnya harus 'menjadi titik masuk utama' bukan 'semua yang dilakukan aplikasi saya' jika tidak, tidak mungkin untuk tidak melanggar SRP dan menghasilkan aplikasi.
sumber