Tetapi bukankah metode draw () sangat tergantung pada apa antarmuka pengguna itu?
Dari pandangan pragmatis, beberapa kode di sistem Anda perlu tahu cara menggambar sesuatu seperti Rectangle
jika itu persyaratan pengguna-akhir. Dan itu akan memanas pada titik tertentu untuk melakukan hal-hal yang sangat rendah seperti rasterisasi piksel atau menampilkan sesuatu di konsol.
Pertanyaan saya dari sudut pandang penggandaan adalah siapa / apa yang harus bergantung pada jenis informasi ini, dan sampai pada tingkat detail apa (seberapa abstrak, misalnya)?
Mengabstraksi Gambar / Kemampuan Rendering
Karena jika kode gambar tingkat tinggi hanya bergantung pada sesuatu yang sangat abstrak, abstraksi itu mungkin dapat bekerja (melalui substitusi implementasi konkret) pada semua platform yang Anda targetkan. Sebagai contoh yang dibuat-buat, beberapa IDrawer
antarmuka yang sangat abstrak mungkin dapat diimplementasikan di kedua konsol dan API GUI untuk melakukan hal-hal seperti bentuk plot (implementasi konsol mungkin memperlakukan konsol seperti beberapa "gambar" 80xN dengan seni ASCII). Tentu saja itu adalah contoh yang dibuat karena biasanya bukan itu yang ingin Anda lakukan adalah memperlakukan keluaran konsol seperti penyangga gambar / bingkai; biasanya sebagian besar pengguna akhir membutuhkan panggilan untuk lebih banyak interaksi berbasis teks di konsol.
Pertimbangan lain adalah seberapa mudahkah mendesain abstraksi yang stabil? Karena mungkin mudah jika semua yang Anda targetkan adalah API GUI modern untuk mengabstraksi kemampuan menggambar bentuk dasar seperti merencanakan garis, persegi panjang, jalur, teks, hal-hal semacam ini (hanya rasterisasi 2D sederhana dari kumpulan primitif terbatas) , dengan satu antarmuka abstrak yang dapat dengan mudah diimplementasikan untuk mereka semua melalui berbagai subtipe dengan sedikit biaya. Jika Anda dapat mendesain abstraksi seperti itu secara efektif dan mengimplementasikannya pada semua platform target, maka saya akan mengatakan itu adalah kejahatan yang jauh lebih kecil, jika bahkan kejahatan sama sekali, untuk bentuk atau kontrol GUI atau apa pun untuk mengetahui cara menggambar dirinya sendiri menggunakan abstraksi.
Tetapi katakan Anda mencoba untuk mengabstraksikan detail berdarah yang bervariasi antara Playstation Portable, iPhone, XBox One, dan PC gaming yang tangguh sementara kebutuhan Anda adalah memanfaatkan teknik rendering / peneduhan 3D real-time paling mutakhir pada masing-masing . Dalam hal ini mencoba untuk membuat satu antarmuka abstrak untuk mengabstraksi rincian render ketika kemampuan perangkat keras dan API yang bervariasi sangat liar hampir pasti akan menghasilkan waktu yang sangat besar dalam mendesain dan mendesain ulang, kemungkinan besar perubahan desain berulang dengan tak terduga. penemuan, dan juga solusi denominator umum terendah yang gagal mengeksploitasi keunikan dan kekuatan penuh dari perangkat keras yang mendasarinya.
Membuat Aliran Ketergantungan Menuju Desain Yang Stabil, "Mudah"
Di bidang saya, saya berada dalam skenario terakhir itu. Kami menargetkan banyak perangkat keras yang berbeda dengan kemampuan dan API yang mendasari sangat berbeda, dan untuk mencoba menghasilkan satu abstraksi rendering / menggambar untuk memerintah mereka semua adalah tanpa batas (kita mungkin menjadi terkenal di dunia hanya melakukan itu secara efektif karena itu akan menjadi permainan) changer di industri). Jadi, hal terakhir yang saya inginkan dalam kasus saya adalah seperti analog Shape
atau Model
atau Particle Emitter
yang tahu cara menggambar itu sendiri, bahkan jika itu menyatakan bahwa menggambar dengan cara tingkat tertinggi dan paling abstrak mungkin ...
... karena abstraksi-abstraksi itu terlalu sulit untuk dirancang dengan benar, dan ketika sebuah desain sulit untuk mendapatkan yang benar, dan semuanya tergantung padanya, itu adalah resep untuk perubahan desain pusat yang paling mahal yang mengacak-acak dan menghancurkan semuanya tergantung padanya. Jadi hal terakhir yang Anda inginkan adalah ketergantungan pada sistem Anda mengalir ke desain abstrak yang terlalu sulit untuk diperbaiki (terlalu sulit untuk distabilkan tanpa perubahan yang mengganggu).
Tergantung Sulit pada Mudah, Tidak Mudah Tergantung pada Sulit
Jadi yang kami lakukan adalah membuat ketergantungan mengalir ke hal-hal yang mudah dirancang. Jauh lebih mudah untuk mendesain "Model" abstrak yang hanya berfokus pada penyimpanan hal-hal seperti poligon dan material dan mendapatkan desain yang benar daripada mendesain "Renderer" abstrak yang dapat secara efektif diimplementasikan (melalui subtipe beton yang dapat diganti-ganti) untuk melayani gambar meminta secara seragam untuk perangkat keras yang berbeda seperti PSP dari PC.
Jadi kami membalikkan ketergantungan dari hal-hal yang sulit untuk dirancang. Alih-alih membuat model abstrak tahu cara menggambar diri mereka sendiri ke desain renderer abstrak yang mereka semua andalkan (dan merusak implementasinya jika desain itu berubah), kami malah memiliki renderer abstrak yang tahu cara menggambar setiap objek abstrak di adegan kami ( model, penghasil partikel, dll), dan dengan demikian kita dapat menerapkan subtipe renderer OpenGL untuk PC seperti RendererGl
, yang lain untuk PSP seperti RendererPsp
, yang lain untuk ponsel, dll. Dalam hal ini dependensi mengalir ke desain yang stabil, mudah untuk mendapatkan yang benar, dari renderer ke berbagai jenis entitas (model, partikel, tekstur, dll) dalam adegan kami, bukan sebaliknya.
- Saya menggunakan "stabilitas / ketidakstabilan" dalam arti yang sedikit berbeda dari metrik kopling aferen / eferen Paman Bob yang mengukur lebih banyak kesulitan perubahan sejauh yang saya bisa mengerti. Saya berbicara lebih banyak tentang "probabilitas membutuhkan perubahan", meskipun metrik stabilitasnya berguna di sana. Ketika "probabilitas perubahan" sebanding dengan "kemudahan perubahan" (mis: hal-hal yang paling mungkin memerlukan perubahan memiliki ketidakstabilan dan kopling aferen tertinggi dari metrik Paman Bob), maka segala kemungkinan perubahan itu murah dan tidak mengganggu untuk dilakukan. , hanya membutuhkan penggantian implementasi tanpa menyentuh desain pusat.
Jika Anda menemukan diri Anda mencoba untuk mengabstraksi sesuatu di tingkat pusat basis kode Anda dan itu terlalu sulit untuk dirancang, alih-alih dengan keras kepala memukul dinding dan terus-menerus membuat perubahan yang mengganggu setiap bulan / tahun yang membutuhkan memperbarui 8.000 file sumber karena itu melanggar semua yang tergantung padanya, saran nomor satu saya adalah mempertimbangkan membalikkan dependensi. Lihat apakah Anda dapat menulis kode sedemikian rupa sehingga hal yang sangat sulit untuk dirancang tergantung pada segala sesuatu yang lebih mudah untuk dirancang, tidak memiliki hal-hal yang lebih mudah untuk dirancang tergantung pada hal yang sangat sulit untuk dirancang. Perhatikan bahwa saya berbicara tentang desain (khususnya desain antarmuka) dan bukan implementasi: kadang-kadang hal-hal mudah dirancang dan sulit diimplementasikan, dan terkadang hal-hal sulit untuk dirancang tetapi mudah diimplementasikan. Ketergantungan mengalir ke arah desain, jadi fokusnya seharusnya hanya pada seberapa sulit sesuatu untuk merancang di sini untuk menentukan arah di mana dependensi mengalir.
Prinsip Tanggung Jawab Tunggal
Bagi saya SRP tidak begitu menarik di sini biasanya (meskipun tergantung pada konteksnya). Maksud saya ada tindakan menyeimbangkan tali ketat dalam mendesain hal-hal yang jelas dalam tujuan dan dapat dipelihara tetapi Shape
objek Anda mungkin harus memaparkan informasi yang lebih rinci jika mereka tidak tahu cara menggambar diri mereka sendiri, misalnya, dan mungkin tidak ada banyak hal yang bermakna untuk lakukan dengan bentuk dalam konteks penggunaan tertentu daripada membangunnya dan menggambarnya. Ada pertukaran dengan hampir semua hal, dan itu tidak terkait dengan SRP yang dapat membuat hal-hal sadar bagaimana menggambar diri mereka mampu menjadi mimpi buruk pemeliharaan dalam pengalaman saya dalam konteks tertentu.
Ini lebih terkait dengan kopling dan arah aliran dependensi dalam sistem Anda. Jika Anda mencoba untuk mem-port antarmuka rendering abstrak yang semuanya bergantung (karena mereka menggunakannya untuk menggambar sendiri) ke API / perangkat keras target baru dan menyadari bahwa Anda harus mengubah desainnya untuk membuatnya bekerja secara efektif di sana, maka itu adalah perubahan yang sangat mahal untuk dilakukan yang membutuhkan penggantian implementasi segala sesuatu di sistem Anda yang tahu cara menggambar sendiri. Dan itulah masalah perawatan paling praktis yang saya temui dengan hal-hal yang disadari tentang cara menggambar diri mereka sendiri jika itu berarti muatan perahu yang mengalir ke arah abstraksi yang terlalu sulit untuk dirancang dengan benar di muka.
Kebanggaan Pengembang
Saya menyebutkan satu poin ini karena, dalam pengalaman saya, ini sering merupakan hambatan terbesar untuk mengalirkan arah ketergantungan kepada hal-hal yang lebih mudah untuk dirancang. Sangat mudah bagi pengembang untuk menjadi sedikit ambisius di sini dan berkata, "Saya akan merancang abstraksi rendering lintas platform untuk mengatur semuanya, saya akan menyelesaikan apa yang menghabiskan waktu berbulan-bulan bagi pengembang lain dalam porting, dan saya akan mendapatkan itu benar dan itu akan bekerja seperti sulap pada setiap platform yang kami dukung dan gunakan teknik rendering canggih pada setiap platform; Saya sudah membayangkannya di kepala saya. "Dalam hal ini mereka menolak solusi praktis yaitu untuk menghindari melakukan itu dan hanya membalik arah dependensi dan menerjemahkan apa yang mungkin sangat mahal dan berulang perubahan desain pusat untuk perubahan hanya murah dan lokal untuk implementasi. Perlu ada semacam naluri "bendera putih" di pengembang untuk menyerah ketika ada sesuatu yang terlalu sulit untuk dirancang ke tingkat abstrak dan mempertimbangkan kembali seluruh strategi mereka, kalau tidak mereka akan menghadapi banyak kesedihan dan rasa sakit. Saya akan menyarankan untuk mentransfer ambisi dan semangat juang seperti itu ke implementasi canggih dari hal yang lebih mudah untuk dirancang daripada mengambil ambisi menaklukkan dunia ke tingkat desain antarmuka.