Saya mungkin akan menganggapnya sebagai bau kode atau bahkan anti-pola untuk memiliki kelas yang mengimplementasikan 23 antarmuka. Jika memang anti-pola, apa yang akan Anda sebut itu? Atau apakah itu hanya tidak mengikuti prinsip tanggung jawab tunggal?
object-oriented
anti-patterns
solid
Jonas Elfström
sumber
sumber
Jawaban:
Keluarga Kerajaan: Mereka tidak melakukan sesuatu yang sangat gila tetapi mereka memiliki satu miliar gelar dan entah bagaimana terkait dengan kebanyakan bangsawan lainnya.
sumber
somehow
Saya serahkan bahwa pola anti ini diberi nama Jack of All Trades, atau mungkin Too Many Hats.
sumber
Jika saya harus memberi nama, saya pikir saya akan menyebutnya Hydra :
Yang paling relevan adalah kenyataan bahwa ia tidak hanya memiliki banyak kepala, tetapi terus tumbuh semakin banyak dan tidak mungkin untuk dibunuh karena itu. Itulah pengalaman saya dengan desain semacam ini; pengembang hanya terus memasukkan lebih banyak antarmuka ke dalamnya sampai terlalu banyak untuk ditampung di layar, dan pada saat itu sudah menjadi sangat tertanam dalam desain program dan asumsi bahwa membaginya adalah prospek tanpa harapan (jika Anda mencoba, Anda sebenarnya seringkali berakhir membutuhkan lebih banyak antarmuka untuk menjembatani kesenjangan).
Satu tanda awal dari malapetaka yang akan datang karena "Hydra" adalah seringnya pengecoran dari satu antarmuka ke antarmuka lainnya, tanpa banyak pemeriksaan kewarasan, dan seringkali ke target yang tidak masuk akal, seperti pada:
Sudah jelas ketika diambil di luar konteks bahwa ada sesuatu yang mencurigakan tentang kode ini, tetapi kemungkinan hal ini terjadi seiring dengan semakin banyak "kepala" suatu objek tumbuh, karena pengembang secara intuitif tahu bahwa mereka selalu berurusan dengan makhluk yang sama.
Good luck pernah melakukan perawatan apapun pada objek yang mengimplementasikan interface 23. Kemungkinan Anda tidak menyebabkan kerusakan pada prosesnya sangat kecil.
sumber
The Allah Obyek datang ke pikiran; satu objek yang tahu bagaimana melakukan SEMUANYA. Ini berasal dari kepatuhan yang rendah terhadap persyaratan "kohesi" dari dua metodologi desain utama; jika Anda memiliki objek dengan 23 antarmuka, Anda memiliki objek yang tahu bagaimana menjadi 23 hal yang berbeda bagi penggunanya, dan 23 hal yang berbeda tersebut kemungkinan besar tidak sejalan dengan satu tugas atau bidang sistem.
Dalam SOLID, meskipun pencipta objek ini jelas telah mencoba mengikuti Prinsip Segregasi Antarmuka, mereka telah melanggar aturan sebelumnya; Prinsip Tanggung Jawab Tunggal. Ada alasannya "SOLID"; S selalu lebih dulu ketika memikirkan desain, dan semua aturan lainnya mengikuti.
Dalam GRASP, pencipta kelas semacam itu telah mengabaikan aturan "Kohesi Tinggi"; GRASP, tidak seperti SOLID, mengajarkan bahwa suatu objek tidak HARUS memiliki tanggung jawab tunggal, tetapi paling tidak ia harus memiliki dua atau tiga tanggung jawab yang sangat erat terkait.
sumber
23 adalah Hanya angka! Dalam skenario yang paling mungkin, cukup tinggi untuk mengkhawatirkan. Namun, jika kita bertanya, berapa jumlah metode / antarmuka tertinggi sebelum bisa mendapatkan tag untuk disebut sebagai "anti-pola"? Apakah 5 atau 10 atau 25? Anda menyadari bahwa angka benar-benar bukan jawaban karena jika 10 baik, 11 juga bisa menjadi - dan kemudian bilangan bulat setelah itu.
Pertanyaan sebenarnya adalah tentang kompleksitas. Dan kita harus menunjukkan bahwa kode panjang, jumlah metode atau ukuran besar kelas dengan ukuran apa pun sebenarnya BUKAN definisi kompleksitas. Ya, kode yang lebih besar dan lebih besar (lebih banyak metode) membuatnya sulit dibaca dan dipahami oleh pemula yang baru. Ini juga menangani fungsionalitas yang berpotensi beragam, sejumlah besar pengecualian, dan algoritma yang cukup berkembang untuk berbagai skenario. Ini tidak berarti kompleks - hanya sulit untuk dicerna.
Di sisi lain, kode ukuran yang relatif kecil yang bisa dibaca seseorang dalam beberapa jam masuk dan keluar masih bisa rumit. Inilah saatnya saya berpikir kodenya kompleks (tidak perlu).
Setiap bagian dari kebijaksanaan desain berorientasi objek dapat diletakkan di sini untuk mendefinisikan "kompleks" tetapi saya akan membatasi di sini untuk menunjukkan kapan "begitu banyak metode" merupakan indikasi kompleksitas.
Saling Mengetahui (alias kopling) Banyak kali ketika sesuatu ditulis sebagai kelas, kita semua berpikir itu adalah kode berorientasi objek yang "bagus". Tetapi asumsi tentang kelas lain pada dasarnya memecah enkapsulasi yang sangat dibutuhkan. Ketika Anda memiliki metode yang "membocorkan" detail mendalam tentang keadaan internal algoritma - dan aplikasi dibangun dengan asumsi utama tentang keadaan internal kelas melayani.
Terlalu banyak pengulangan (pembobolan) Ketika metode yang memiliki nama serupa tetapi melakukan pekerjaan yang bertentangan - atau bertentangan dengan nama dengan fungsi yang sama. Banyak kode yang berevolusi untuk mendukung antarmuka yang sedikit berbeda untuk aplikasi yang berbeda.
Terlalu banyak peran Ketika kelas terus menambahkan fungsi samping dan terus berkembang lebih seperti orang menyukainya, hanya untuk mengetahui bahwa kelas itu sekarang menjadi dua kelas. Yang mengejutkan semua ini dimulai dengan yang aslipersyaratan dan tidak ada kelas lain untuk melakukan ini. Pertimbangkan ini, ada Transaksi kelas, yang memberi tahu detail transaksi. Terlihat bagus sejauh ini, sekarang seseorang memerlukan konversi format pada "waktu transaksi" (antara UTC dan sejenisnya), kemudian, orang menambahkan aturan untuk memeriksa apakah ada hal-hal tertentu pada tanggal tertentu untuk memvalidasi transaksi yang tidak valid. - Saya tidak akan menulis keseluruhan cerita tetapi akhirnya, kelas transaksi membangun seluruh kalender dengan di dalamnya dan kemudian orang-orang mulai menggunakan bagian "hanya kalender"! Ini sangat kompleks (untuk membayangkan) mengapa saya akan instantiate "kelas transaksi" untuk memiliki fungsionalitas bahwa "kalender" akan memberi saya!
(Dalam) konsistensi API Ketika saya melakukan book_a_ticket () - Saya memesan tiket! Itu sangat sederhana terlepas dari berapa banyak pemeriksaan dan proses untuk mewujudkannya. Sekarang menjadi rumit ketika aliran waktu mulai mempengaruhi ini. Biasanya seseorang akan memungkinkan "mencari" dan kemungkinan status yang tersedia / tidak tersedia, kemudian untuk mengurangi back-n-sebagainya Anda mulai menyimpan beberapa pointer konteks di dalam tiket dan kemudian merujuknya untuk memesan tiket. Pencarian bukan satu-satunya fungsi - hal menjadi lebih buruk setelah banyak "fungsi samping" tersebut. Dalam proses arti book_a_ticket () menyiratkan book_that_ticket ()! dan itu bisa sangat rumit.
Mungkin ada banyak situasi seperti itu yang akan Anda lihat dalam kode yang sangat berkembang dan saya yakin bahwa banyak orang dapat menambahkan skenario, di mana "begitu banyak metode" tidak masuk akal atau tidak melakukan apa yang Anda pikirkan. Ini adalah anti-pola.
Pengalaman pribadi saya adalah bahwa ketika proyek yang dimulai dari bawah ke atas secara wajar , banyak hal yang seharusnya memiliki kelas asli sendiri - tetap terkubur atau lebih buruk masih tetap terbagi antara kelas yang berbeda dan peningkatan kopling. Paling sering apa yang seharusnya layak 10 kelas, tetapi hanya memiliki 4, kemungkinan banyak dari mereka memiliki multi-tujuan yang membingungkan dan sejumlah besar metode. Sebut saja TUHAN dan NAGA, inilah yang BURUK.
TAPI Anda menemukan kelas SANGAT BESAR yang konsisten dengan rapi, mereka memiliki 30 metode - dan masih sangat BERSIH. Mereka bisa baik.
sumber
Kelas harus memiliki jumlah antarmuka yang tepat; tidak lebih, tidak kurang.
Mengatakan "terlalu banyak" tidak akan mungkin tanpa melihat apakah semua antarmuka tersebut memiliki tujuan yang berguna di kelas itu. Mendeklarasikan bahwa objek mengimplementasikan antarmuka berarti Anda harus mengimplementasikan metode-metodenya jika Anda mengharapkan kelas untuk dikompilasi. (Saya kira kelas yang Anda lihat tidak.) Jika semua yang ada di antarmuka diimplementasikan dan implementasi tersebut melakukan sesuatu yang relatif terhadap jeroan kelas, akan sulit untuk mengatakan bahwa implementasi tidak boleh ada di sana. Satu-satunya kasus yang saya bisa pikirkan di mana antarmuka memenuhi kriteria itu tidak akan termasuk ada eksternal: ketika tidak ada yang menggunakannya.
Beberapa bahasa memungkinkan antarmuka untuk "subkelas" menggunakan mekanisme seperti
extends
kata kunci Java , dan siapa pun yang menulisnya mungkin tidak tahu itu. Mungkin juga bahwa ke-23 itu cukup jauh sehingga menggabungkan mereka tidak masuk akal.sumber
Kedengarannya seperti mengira mereka memiliki pasangan "pengambil" / "penyetel" untuk setiap properti, seperti biasa untuk "kacang" khas dan mempromosikan semua metode ini ke antarmuka. Jadi bagaimana kalau menyebutnya " kacang ". Atau "perut kembung" yang lebih Rabelaisian setelah pengaruh yang dikenal dari terlalu banyak kacang.
sumber
Jumlah antarmuka sering bertambah ketika objek generik digunakan di lingkungan yang berbeda. Dalam C # varian IComparable, IEqualityComparer dan IComparer memungkinkan pengurutan dalam pengaturan yang berbeda, sehingga Anda mungkin akhirnya mengimplementasikan semuanya, beberapa di antaranya mungkin lebih dari sekali karena Anda dapat mengimplementasikan versi generik yang diketik dengan kuat serta versi non-generik , selain itu Anda dapat menerapkan lebih dari satu obat generik.
Mari kita ambil contoh skenario, katakanlah sebuah toko web di mana Anda dapat membeli kredit yang dengannya Anda dapat membeli sesuatu yang lain (stok situs foto sering menggunakan skema ini). Anda mungkin memiliki kelas "Valuta" dan kelas "Kredit" yang mewarisi bentuk basis yang sama. Valuta memiliki beberapa kelebihan operator dan rutinitas perbandingan yang memungkinkan Anda melakukan perhitungan tanpa khawatir tentang properti "Mata Uang" (misalnya, menambahkan pound ke dolar). Kredit lebih mudah tetapi memiliki beberapa perilaku berbeda lainnya. Ingin dapat membandingkan ini satu sama lain, Anda bisa akhirnya mengimplementasikan IComparable serta IComparable dan varian lain dari antarmuka perbandingan pada keduanya (meskipun mereka menggunakan implementasi umum apakah itu di kelas dasar atau di tempat lain).
Ketika menerapkan serialisasi, ISerializable, IDeserializationCallback diimplementasikan. Kemudian menerapkan tumpukan undo-redo: IClonable ditambahkan. Fungsionalitas IsDirty: IObservable, INotifyPropertyChanged. Mengizinkan pengguna mengedit nilai menggunakan string: IConvertable ... Daftar ini bisa berlanjut dan terus ...
Dalam bahasa modern kita melihat tren berbeda yang membantu memisahkan aspek-aspek ini dan menempatkannya di kelas mereka sendiri, di luar kelas inti. Kelas atau aspek luar kemudian dikaitkan dengan kelas target dengan menggunakan anotasi (atribut). Seringkali dimungkinkan untuk membuat kelas aspek luar lebih atau kurang generik.
Penggunaan atribut (anotasi) tunduk pada refleksi. Satu kelemahan adalah kerugian kinerja (awal) kecil. Kelemahan (sering emosional) adalah bahwa prinsip-prinsip seperti enkapsulasi perlu santai.
Selalu ada solusi lain, tetapi untuk setiap solusi bagus ada tradeoff atau tangkapan. Misalnya, menggunakan solusi ORM mungkin menuntut semua properti dinyatakan virtual. Solusi serialisasi mungkin menuntut konstruktor default di kelas Anda. Jika Anda menggunakan injeksi dependensi Anda mungkin akhirnya mengimplementasikan 23 antarmuka pada satu kelas.
Di mata saya, 23 antarmuka tidak harus buruk menurut definisi. Mungkin ada skema dipikirkan dengan baik di belakangnya, atau beberapa prinsip penentuan seperti menghindari penggunaan refleksi atau keyakinan enkapsulasi ekstrim.
Setiap kali berganti pekerjaan, atau harus membangun arsitektur yang sudah ada. Saran saya adalah pertama-tama berkenalan sepenuhnya, jangan mencoba untuk memperbaiki semuanya terlalu cepat. Dengarkan pengembang asli (jika dia masih di sana) dan cobalah untuk mencari tahu pikiran dan ide di balik apa yang Anda lihat. Saat mengajukan pertanyaan, lakukan itu bukan demi memecahnya, tetapi untuk belajar ... Ya, setiap orang memiliki palu emas sendiri, tetapi semakin banyak palu yang dapat Anda kumpulkan semakin mudah Anda bergaul dengan rekan-rekan sesama.
sumber
"Terlalu banyak" adalah subyektif: gaya pemrograman? kinerja? kesesuaian dengan standar? preseden? sekadar rasa nyaman / percaya diri?
Selama kode Anda berperilaku benar dan tidak menghadirkan masalah pemeliharaan, 23 bahkan bisa menjadi norma baru. Suatu hari nanti saya bisa berkata, "Anda dapat melakukan pekerjaan yang sangat baik dengan 23 antarmuka, lihat: Jonas Elfström".
sumber
Saya akan mengatakan bahwa batasnya harus lebih kecil dari 23 - lebih seperti 5 atau 7,
namun, ini tidak termasuk sejumlah antarmuka yang diwariskan oleh antarmuka tersebut atau sejumlah antarmuka yang diterapkan oleh kelas dasar.
(Jadi sama sekali, N + sejumlah antarmuka yang diwariskan, di mana N <= 7.)
Jika kelas Anda mengimplementasikan terlalu banyak antarmuka, itu mungkin kelas dewa .
sumber