Jika kelas "ResourceManager" dianggap buruk, apa alternatifnya?

19

Saya mendengar pendapat yang bertentangan seperti:

  • "Kelas Manajer Khusus hampir tidak pernah menjadi alat teknik yang tepat"
  • "Kelas Manajer Khusus (saat ini) adalah cara terbaik untuk bertahan dari proyek besar dengan ribuan sumber daya"

Mari kita ambil kelas ResourceManager klasik yang memiliki fungsi berikut:

  • Memuat aset (tekstur, audio, model 3D, dll)
  • Memastikan aset hanya dimuat satu kali dengan menyimpan cache
  • Referensi menghitung aset untuk menentukan apakah mereka dapat dialokasikan kembali
  • Menyembunyikan dari mana aset sebenarnya berasal (mis., Dapat berupa satu file per aset, atau semua aset dalam satu paket file, atau aset bahkan dapat dimuat melalui jaringan)
  • Dapat memuat ulang aset tanpa memulai ulang program, yang sangat berguna bagi para seniman yang mengerjakan permainan.

Mari kita juga mengambil argumen "lajang yang buruk" dari meja dengan berpura-pura bahwa objek-objek ResourceManager ini bukan lajang, dan sebaliknya diteruskan melalui injeksi ketergantungan .

Lalu ada argumen "gunakan pabrik" atau "sebut saja pabrik". Masalah saya dengan ini adalah, ya, itu adalah pabrik, tetapi juga merupakan cache dan reloader (karena tidak ada kata yang lebih baik). Menyebutnya sebuah pabrik tidak menggambarkannya dengan benar, dan jika saya menjadikannya pabrik yang tepat, lalu di mana caching dan reload diimplementasikan?

Saya setuju bahwa kelas "Manajer" sering merupakan gejala dari arsitektur yang buruk, tetapi dalam kasus khusus ini bagaimana bisa direstrukturisasi dan masih mempertahankan semua fungsinya ? Apakah ini situasi di mana kelas "Manajer" sebenarnya sesuai?

Tom Dalling
sumber
3
Mungkin menyebutnya gudang, bukan pabrik? : P
deceleratedcaviar

Jawaban:

9

Saya pikir masalahnya bukan bahwa ini adalah desain yang buruk. Masalahnya adalah bahwa nama "Manajer" tidak mencolok, seperti "Pembaruan" dan "Proses" dan "Aktor". Tidak membantu seseorang yang mencoba memahami sistem ini, dan ini menciptakan kebingungan jika Anda pernah memiliki kelas lain yang melakukan beberapa operasi pada aset.

Namun, memberi nama dengan cara yang secara efisien menyampaikan tujuan mereka adalah sangat, sangat sulit . Sebagian besar sistem terlalu rumit untuk diperjelas dengan namanya. Yang terbaik yang dapat Anda lakukan adalah mencoba mempersempit ide spesifik apa yang membuat kelas ini kohesif, dan apa yang kelas lain perlu jelas berbeda, dan pilih kata unik yang cocok.

IMHO, fitur paling penting dari nama baik adalah unik dalam konteks yang orang akan melihatnya (basis kode), dan mudah diingat. Tesnya adalah Anda dapat melakukan percakapan dengan teman satu tim Anda yang terbiasa dengan kode tanpa harus mengklarifikasi apa yang Anda maksud. Ini juga akan membantu jika Anda perlu menulis dokumentasi referensi.

Akhirnya, pertimbangkan bahwa jika Anda tidak dapat menggambarkan gagasan kohesif itu, itu mungkin tidak terlalu kohesif. Misalnya, Anda dapat memisahkan penghitungan caching dan referensi dalam AssetCache, dan menyimpan pemuatan di AssetLoader. Tapi itu benar-benar tergantung seberapa rumit dan terjalinnya kode tersebut.

Tetapi jika AssetManager Anda cukup kohesif, dan tidak ada yang lain dalam game Anda adalah AssetManagery, maka itu mungkin nama yang sangat bagus.

Evan Rogers
sumber
Pemisahan AssetLoader / AssetCache bukan ide yang buruk.
Tom Dalling
4

"Apakah aku melakukan ini di satu tempat, atau aku banyak melakukannya?"

Logika pemuatan biasanya terpusat pada satu titik akses karena cenderung dijalankan hanya pada titik-titik kunci dalam aplikasi, di mana kami mencoba mengeluarkannya sesegera mungkin. Ini biasanya terjadi di startup aplikasi, permulaan level game, atau ketika posisi pemain dunia menuntut pemuatan chunk baru untuk menjaga pengalaman tetap mulus. Mengingat ini dilakukan sebagai proses batch (baik dalam satu potongan besar atau banyak yang lebih kecil tidak terlalu penting), masuk akal untuk memiliki satu metode atau serangkaian metode untuk memanggil, untuk memulai proses ini.

Pada sebagian besar platform, memuat tidak sinkron, sehingga Anda sebenarnya tidak punya banyak pilihan selain memisahkan aliran kode untuk memuat dan logika aplikasi lainnya, alasan lain untuk abstraksi fungsi manajemen sumber daya ke dalam kelas mereka sendiri.

Terakhir, beberapa poin untuk dipikirkan:

Pemuatan sumber daya tidak berjalan sangat sering dibandingkan dengan misalnya. logika game, jadi apakah layak menambahkan kompleksitas pada objek game individual Anda untuk melakukan ini? Objek permainan biasanya dibuat seringan mungkin dan dimaksudkan hanya untuk apa yang dibutuhkan selama simulasi.

Haruskah suatu objek bertanggung jawab atas ciptaan dan kehancurannya sendiri? Ini dapat menyebabkan sakit kepala besar selama manajemen entitas. Jika Anda mengharapkan suatu objek untuk melakukan proses penciptaannya sendiri (termasuk mendapatkan dependensi sumber daya) maka ia juga akan memiliki tanggung jawab untuk menghancurkan dirinya sendiri. Ini dapat menyebabkan penguntit / null pointer, jadi itu benar-benar harus dikelola dari luar. Lihat jawaban ini menguraikan masalah itu secara lebih rinci.


PS Selain dari argumen tipe "Singletons yang mengerikan" (yang sangat dogmatis), apakah Anda pernah melihat argumen yang bagus melawan ResourceManagers? "Kelas Manajer Khusus hampir tidak pernah menjadi alat teknik yang tepat" tidak ada argumen sama sekali untuk kasus khusus ini .

Insinyur
sumber