Apakah saya boleh memiliki kode bau jika itu mengakui solusi yang lebih mudah untuk masalah lain? [Tutup]

31

Sekelompok teman dan saya telah mengerjakan sebuah proyek selama beberapa waktu terakhir, dan kami ingin menemukan cara OOP yang bagus untuk mewakili skenario khusus untuk produk kami. Pada dasarnya, kami sedang mengerjakan permainan peluru neraka bergaya Touhou , dan kami ingin membuat sistem di mana kami dapat dengan mudah mewakili setiap perilaku yang mungkin dari peluru yang dapat kami impikan.

Jadi itulah tepatnya yang kami lakukan; kami membuat arsitektur yang sangat elegan yang memungkinkan kami untuk memilah perilaku peluru menjadi komponen-komponen berbeda yang dapat dilampirkan pada contoh peluru sesuka hati, seperti sistem komponen Unity . Ini bekerja dengan baik, mudah diperluas, fleksibel dan mencakup semua pangkalan kami, tetapi ada sedikit masalah.

Aplikasi kami juga melibatkan sejumlah besar generasi prosedural, yaitu kami secara prosedural menghasilkan perilaku peluru. Mengapa ini menjadi masalah? Nah, solusi OOP kami untuk merepresentasikan perilaku peluru, meski elegan, sedikit rumit untuk dikerjakan tanpa manusia. Manusia cukup pintar untuk memikirkan solusi untuk masalah yang logis dan pintar. Algoritma generasi prosedural belum begitu pintar, dan kami merasa sulit untuk mengimplementasikan AI yang menggunakan arsitektur OOP kami untuk potensi penuhnya. Diakui, itu adalah cacat dari arsitektur adalah bahwa itu tidak intuitif dalam semua situasi.

Jadi untuk mengatasi masalah ini, kami pada dasarnya memasukkan semua perilaku yang ditawarkan oleh komponen yang berbeda ke dalam kelas bullet, sehingga segala yang kami bayangkan dapat ditawarkan langsung di setiap instance peluru sebagai lawan dari instance komponen terkait lainnya. Ini membuat algoritma generasi prosedural kami sedikit lebih mudah untuk dikerjakan, tetapi sekarang kelas peluru kami adalah objek dewa yang sangat besar . Ini adalah kelas terbesar dalam program sejauh ini dengan kode lebih dari lima kali lipat dari yang lainnya. Agak sulit untuk dirawat juga.

Apakah tidak masalah bahwa salah satu kelas kami berubah menjadi objek dewa, hanya untuk membuatnya lebih mudah untuk bekerja dengan masalah lain? Secara umum, apakah boleh menggunakan kode bau di kode Anda jika ia mengakui solusi yang lebih mudah untuk masalah yang berbeda?

pengguna3002473
sumber
1
Yah ... ini agak sulit dijawab. Menurut saya TIDAK. Apalagi jika Anda bekerja sama dengan orang lain. Jika Anda bekerja sendiri, Anda dapat melakukan apa pun yang Anda inginkan. Tetapi secara umum itu tergantung pada siapa Anda bekerja dengan.
Kentang Sarkastik
13
"Jika itu bodoh, dan itu berhasil; itu tidak bodoh." Yang sedang berkata, Anda harus membuat pertimbangan bahwa bahkan jika itu bekerja persis seperti yang Anda inginkan, apakah Anda tidak membuat coding masa depan pada kelas dewa dekat tidak mungkin karena bagaimana Anda memutuskan untuk memperbaikinya.
Flater
8
Lebih baik mencium dan tahu Anda bau, maka untuk mencium hanya orang lain perhatikan. :)
Reactgular
1
Kedengarannya seperti Anda memerlukan kelas adaptor yang menyediakan antarmuka non-OO ke kode prosedural Anda, sehingga Anda dapat menjaga sisa kode Anda bersih (er).
nikie
1
Sepertinya Anda membangun sistem yang hebat dan memutuskan untuk meledakkannya semua ke neraka sekarang tidak berfungsi seperti yang diharapkan pada satu fitur. Benarkah itu yang Anda inginkan? Banggalah dengan pekerjaan Anda!
Tiang

Jawaban:

74

Ketika membangun program dunia nyata, sering ada pertukaran antara tetap pragmatis di satu sisi, dan tetap 100% bersih di sisi lain. Jika tetap bersih melarang Anda mengirimkan produk tepat waktu, maka Anda lebih baik dengan sedikit selotip untuk mengeluarkan benda itu dari pintu.

Mengatakan bahwa, deskripsi Anda suara yang berbeda - kedengarannya Anda tidak akan menambahkan sedikit sedikit lakban, sepertinya Anda akan merusak seluruh arsitektur Anda karena Anda tidak terlihat panjang dan cukup keras untuk solusi yang lebih baik. Jadi, alih-alih mencari seseorang di sini di PSE yang memberkati Anda dalam hal ini, Anda mungkin lebih baik mengajukan pertanyaan berbeda di mana Anda menggambarkan beberapa detail masalah yang Anda miliki secara mendalam, dan mencari apakah ada yang menawarkan Anda ide yang menghindari dewa. -kelas pendekatan.

Mungkin kelas peluru dapat dirancang untuk menjadi fasad ke sekelompok kelas lain, sehingga kelas peluru menjadi lebih kecil. Mungkin pola strategi dapat membantu sehingga peluru dapat mendelegasikan perilaku yang berbeda ke objek strategi yang berbeda. Mungkin Anda hanya membutuhkan adaptor antara komponen peluru dan generator prosedural Anda. Tapi jujur, tanpa mengetahui lebih detail tentang sistem Anda, orang hanya bisa menebak-nebak.

Doc Brown
sumber
6
Hanya untuk menegaskan kembali jawaban ini, saya akan menulis sesuatu dengan dua rekomendasi yang sama. Mengenai paragraf terakhir, apa yang OP jelaskan nampak seperti bau kode yang mengindikasikan bahwa diperlukan tingkat tipuan lain. Entah itu kelas pabrik yang lebih baik, fasad, atau bahkan DSL yang penuh sesak yang dapat dihasilkan AI diserahkan kepada OP.
Daniel B
2
Saran bagus untuk Fasad / Strategi untuk membagi kode menjadi potongan-potongan kecil. Meskipun tanpa mengetahui lebih detail, sulit untuk mengetahui apa yang disarankan.
user949300
25

Pertanyaan menarik. Saya agak bias karena pengalaman saya sebelumnya, yang mendorong saya untuk menjawab dengan TIDAK.

Jawaban singkat: Kami tidak pernah berhenti belajar. Ketika Anda menabrak dinding seperti itu, itu adalah kesempatan untuk meningkatkan keterampilan arsitektur / desain Anda, bukan alasan untuk menambahkan bau kode.

Versi yang lebih panjang adalah bahwa saya telah sering ditanyakan pertanyaan serupa dalam proyek saya di tempat kerja sekarang, tetapi akhirnya, kami akhirnya membahas masalah ini secara lebih mendalam, kemudian penanya yang asli memberikan penghargaan untuk itu. Anda ingin memasukkan mentalitas seperti analisis akar penyebab dengan itu.

Saya menemukan 5 Mengapa sangat membantu. Penjelasan Anda di sini berbunyi seperti yang pertama mengapa:

  • "Kami memiliki kelas dewa ini sekarang" Mengapa?
  • "Karena itu menyederhanakan algoritma pembuatan prosedural"

Apa sebenarnya yang disederhanakan? Dan mengapa begitu? Terus mengikuti garis itu dan apa yang biasanya terjadi adalah Anda mulai mengenali masalah yang jauh lebih mendasar, tetapi pada saat yang sama, mereka juga memberi Anda solusi yang lebih mendasar.

Singkatnya, setelah memikirkan lebih dalam tentang masalah yang dihadapi dan khususnya penyebabnya, menurut pengalaman saya, pertanyaan awal ternyata batal dan sama sekali tidak menarik bagi semua peserta. Jika Anda memiliki keraguan, tantang mereka dan apakah mereka akan hilang, atau Anda akan tahu apa yang harus Anda lakukan. Pikiran Anda, itu pertanda baik menurut pendapat saya untuk memiliki keraguan tentang kode / desain ini. Orang lain menyebutnya firasat, tetapi untuk menantang masalah ini, Anda harus terlebih dahulu mengenalinya. Karena Anda membuat langkah pertama itu, selamat! Sekarang pergilah ke lubang kelinci ...

jujur
sumber
9

Memiliki kelas dewa seperti ini tidak pernah diinginkan, karena itu tidak hanya berarti bahwa peluru Anda sekarang menjadi objek monolitik, tetapi juga berlaku untuk algoritma generasi prosedural Anda.

Langkah pertama adalah menganalisis, mengapa sebenarnya AI Anda benar-benar memiliki banyak masalah dalam berurusan dengan kompleksitas pola Anda?

Apakah Anda, secara kebetulan, mencoba mengubah AI Anda menjadi objek kelas dewa, sepenuhnya menyadari tentang semantik dari setiap properti yang mungkin ada? Jika Anda melakukannya, di situlah masalahnya berasal.

Solusinya kemudian tidak akan mengintegrasikan semua strategi ke dalam kelas peluru itu sendiri, tetapi bukannya membongkar petunjuk untuk AI dari inti AI ke implementasi strategi itu sendiri.

Itu akan memberi Anda fleksibilitas yang semula Anda inginkan, termasuk opsi untuk memperluas sistem dengan strategi baru seperti yang Anda inginkan tanpa takut mengalami efek samping dengan perilaku lama.

Alih-alih, sekarang Anda memiliki semua masalah yang terkait dengan objek dewa: Tidak hanya kelas dewa Anda sendiri yang sulit dipahami, sulit untuk men-debug monolit, tetapi hal yang sama juga berlaku untuk semua komponen lain yang mengakses kelas dewa semacam itu. Karena kurangnya abstraksi, AI Anda sekarang terikat untuk berubah menjadi kekejaman dengan kompleksitas yang sama karena harus menyadari semua properti individual yang berlebihan sekarang.

Bahkan sekarang, Anda sudah mengalami masalah dengan pemeliharaan. Masalah-masalah ini semakin buruk, terutama begitu Anda kehilangan anggota tim yang masih memiliki model kognitif tentang bagaimana kelas itu seharusnya bekerja.

Sejauh ini setiap proyek yang saya temui yang menggunakan kelas dewa atau fungsi dewa entah itu sepenuhnya ditulis ulang dari awal atau dihentikan, tidak ada pengecualian.

Ext3h
sumber
Satu hal yang sering hilang dalam diskusi tentang seberapa besar atau kompleks kelas seharusnya adalah perbedaan antara "berapa banyak kode yang memiliki referensi tipe X dapat lakukan dengan itu" versus "banyak logika harus ada dalam file kelas untuk X ". Jika klien kemungkinan memiliki koleksi objek yang mendukung berbagai kemampuan (mis. "Fnorble"), dan sering kali ingin meminta semua anggota koleksi untuk mis "fnorble jika memungkinkan, yang lain tidak melakukan apa-apa", kemudian memiliki antarmuka yang menggabungkan banyak metode seperti itu mungkin jauh lebih bermanfaat daripada mencoba untuk membagi antarmuka.
supercat
Dengan antarmuka seperti itu, dimungkinkan untuk memiliki kode yang mengenkapsulasi objek dengan kombinasi kemampuan apa pun, tanpa harus menangani kombinasi berbeda secara terpisah. Memisahkan antarmuka akan membuatnya perlu untuk menulis banyak kelas proxy yang berbeda, karena proksi untuk tipe yang mendukung metode X tidak dapat digunakan untuk membungkus objek yang tidak bisa X, dan proksi yang bisa membungkus objek yang tidak bisa X tidak akan t dapat mengekspos metode X bahkan jika itu membungkus objek yang dapat mendukungnya.
supercat
8

Semua kode buruk sejak awal waktu memiliki cerita di balik evolusinya yang membuatnya terlihat masuk akal langkah demi langkah. Tidak terkecuali Anda. Coders belajar dengan coding. Ada beberapa aspek dari masalah Anda yang tidak dapat Anda bayangkan sebelumnya. Ada keputusan yang Anda buat yang sepenuhnya masuk akal secara bertahap, tetapi mengarahkan arsitektur Anda ke arah yang salah secara keseluruhan. Anda perlu mengidentifikasi dan menguji kembali keputusan-keputusan itu.

Tanyakan di sekitar kantor Anda apakah ada yang tahu cara memperbaikinya. Sebagian besar tempat saya pernah bekerja, sekitar 10-20% dari programmer memiliki keahlian nyata untuk hal semacam itu, dan baru saja menunggu kesempatan. Cari tahu siapa orang-orang itu. Seringkali, karyawan baru Anda yang secara historis tidak berinvestasi dalam arsitektur saat ini yang paling mudah melihat alternatif. Pasangkan mereka dengan salah satu veteran Anda dan Anda mungkin kagum dengan apa yang mereka hasilkan bersama.

Karl Bielefeldt
sumber
2

Dalam beberapa kasus ini pasti dapat diterima. Namun, saya merasa sulit untuk percaya bahwa tidak ada solusi yang baik menggunakan generasi prosedural dan arsitektur perilaku berbasis komponen Anda yang terpasang / bagus. Jika semua perilaku di mana hanya ditarik ke dalam kelas peluru tidak ada perbedaan fungsional antara objek dewa, dan versi arsitektur yang rapi. Apa yang membuat algoritma generasi prosedural Anda sulit digunakan?

Saya pikir pertanyaan baru (mungkin di sini, atau di gamedev.stackexchange.com?), Di mana Anda menguraikan masalah apa yang Anda miliki dengan arsitektur Anda dalam kombinasi dengan proc. gen., akan sangat menarik. Beri tahu kami di sini jika Anda juga membuat pertanyaan baru!

Roy T.
sumber
3
Bisakah Anda memberikan contoh untuk situasi di mana memiliki kelas dewa akan diterima dan diinginkan sementara kelas ini bukan hanya kompilasi otomatis sumber individu?
Ext3h
Dengan dapat diterima saya mengacu pada "Apakah saya boleh memiliki kode bau jika itu mengakui solusi yang lebih mudah untuk masalah lain?" Kelas dewa umumnya mudah dipecahkan dengan menggunakan komposisi. Tapi ya ada bau kode tertentu yang pasti tidak selalu bernilai 100% menyingkirkan. Pada akhirnya beberapa pragmatisme diperlukan untuk menyelesaikan pekerjaan :). (Ini tidak berarti saya pikir Anda harus membuang praktik terbaik atas kemauan. Saya percaya bahwa sebagian besar rumah perangkat lunak akan lebih baik dalam mengikuti praktik terbaik dengan lebih ketat).
Roy T.
0

Untuk inspirasi, Anda mungkin ingin melihat pemrograman fungsional, atau lebih tepatnya, tipe yang dirancang khusus. Gagasannya adalah bahwa hal-hal tidak berfungsi tidak mungkin untuk diwakili dalam sistem tipe yang Anda miliki. Misalnya, Anda memiliki senjata yang memiliki komponen "tembak peluru" dan "tahan peluru". Jika mereka adalah dua komponen yang terpisah, ada konfigurasi yang tidak masuk akal - Anda dapat memiliki pistol yang menembakkan peluru tetapi tidak memiliki apa pun dalam penyimpanannya, atau pistol yang menyimpan peluru tetapi tidak menembakkannya.

Pada tingkat kerumitan ini, Anda berpikir "benar, manusia akan mengetahui ini tidak berguna, dan menghindari kombinasi yang tidak mungkin". Cara yang lebih baik mungkin dengan membuatnya mustahil untuk melakukan ini. Misalnya, komponen untuk "peluru tembak" mungkin diperlukan referensi ke komponen "tahan peluru" (atau pegang saja sebagai bagian dari dirinya sendiri, walaupun itu memiliki masalah sendiri).

Meskipun contoh Anda mungkin jauh lebih rumit, kuncinya masih membatasi kombinasi yang mungkin, menambah kendala. Di satu sisi, jika terlalu rumit untuk generasi prosedural untuk mendapatkan yang benar, itu mungkin terlalu rumit. Pikirkan semua cara Anda membatasi diri ketika merancang senjata - apakah Anda mengatakan pada diri sendiri "benar, senjata ini sudah memiliki penyembur api, tidak ada gunanya menambahkan peluncur granat"? Itu sesuatu yang bisa Anda masukkan dalam heuristik Anda. Anda mungkin ingin menggunakan mekanisme probabilitas yang sedikit lebih rumit daripada hanya memberi peluang tetap untuk memiliki masing-masing komponen - Anda mungkin memiliki komponen yang cenderung saling mengecualikan, atau komponen yang cenderung bekerja dengan baik bersama.

Dan terakhir, pertimbangkan apakah itu sebenarnya masalah yang cukup besar. Apakah itu merusak kesenangan permainan? Apakah senjata hasil yang tidak berguna atau dikuasai? Berapa banyak? Apakah satu dari 10 tidak masuk akal? Gim seperti Borderlands (dengan efek senjata yang dihasilkan secara prosedural) sering mengabaikan kombinasi efek yang tidak masuk akal - apa gunanya memiliki senapan dengan cakupan 16x? Namun itu sering terjadi di Borderlands. Itu hanya dimainkan untuk tertawa, daripada dianggap sebagai kegagalan mekanisme generasi :)

Luaan
sumber