Apa perbedaan antara Layanan Game XNA dan variabel global yang dimuliakan?

10

The Microsoft.Xna.Framework.Gamekelas memiliki Layanan properti yang memungkinkan programmer untuk menambahkan layanan ke permainan mereka dengan menyediakan jenis kelas dan sebuah instance dari kelas dengan metode Tambah.

Sekarang, alih-alih harus meneruskan sebuah AudioComponentke semua kelas dan metode yang memerlukannya, Anda hanya melewati Gamecontoh Anda dan mencari layanan. ( Pencari Layanan )

Sekarang, karena gim memiliki banyak layanan (GraphicsDevice, SceneGraph, AudioComponent, EffectsManager, dan lain-lain), sekarang Anda pada dasarnya akan menyerahkan Gim ke semuanya.

Jadi mengapa tidak membuat saja contoh ini Singleton? Ya, karena Singletons buruk karena mereka memiliki keadaan global, mencegah pengujian, dan membuat desain Anda jauh lebih rapuh. Penelusur layanan sama-sama dianggap sebagai anti-pola bagi banyak orang karena alih-alih hanya meneruskan ketergantungan pada suatu objek, Anda melewatkan pencari layanan (Game) yang memasangkan kelas tersebut dengan seluruh layanan.

Jadi mengapa Layanan direkomendasikan dalam XNA dan pengembangan game? Apakah itu karena permainan berbeda dari program reguler dan sangat terkait dengan komponen mereka dan harus melewati setiap komponen yang diperlukan untuk berfungsinya kelas akan sangat rumit? Apakah Layanan Game saat itu merupakan kejahatan yang diperlukan dalam desain game? Apakah ada alternatif yang tidak melibatkan daftar parameter panjang dan kopling?

John Pollick
sumber
3
"Pencari layanan dianggap sama-sama anti-pola bagi banyak orang" - [rujukan?]. Jelas menggunakan mereka di mana Anda tidak membutuhkannya adalah buruk - benar dari semua konstruksi perangkat lunak - tapi saya belum pernah mendengar pencari layanan yang disebut anti-pola. (Di sisi lain, saya juga mencoba untuk menghindari programmer yang menghabiskan sebagian besar waktu mereka membahas pola-pola minutiae terbaru.)
@ JoWreschnig walaupun saya setuju dengan Anda, saya melakukan beberapa penggalian dan menemukan ini: blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntitiPattern.aspx
Roy T.
2
Ya, tapi pria itu menjual buku tentang menggunakan DI; jelas dia tidak ingin Anda menggunakan sesuatu yang sederhana, maka Anda tidak akan membeli bukunya! (Dalam semua keseriusan, artikel DI / SL asli Fowler membahas topik yang tepat ini - martinfowler.com/articles/… - dan kata-kata kasar blog orang itu tidak menambah apa pun dalam diskusi.)
Saya berharap saya dapat menandai tautan yang baru saja Anda kirim dari Martin Fowler sebagai jawaban (walaupun itu bukan pertanyaan saya)
Roy T.

Jawaban:

6

Saya tidak berpikir semua orang setuju bahwa pencari layanan buruk. Service Locators menyediakan cara untuk memisahkan fungsi penting yang dibutuhkan setiap orang dari implementasi aktualnya. Penelusur layanan juga menyediakan cara untuk menukar layanan pada waktu berjalan. Juga saya tidak berpikir itu benar bahwa Anda perlu melewati pelacak layanan di mana-mana. Saya pikir Anda dapat mengaksesnya dari mana saja. Sementara kelas gim dengan global perlu dilewati sekitar seribu kali per frame (yang akan menyebabkan kinerja buruk).

Untuk membuat perbedaan antara pencari lokasi dan kelas dengan global sedikit lebih jelas, perhatikan contoh berikut:

Saya membuat game dan menggunakan objek kelas gameA yang memiliki variabel global: pemuat konten. Sekarang di game saya berikutnya, saya tidak ingin menggunakan kelas gameA tetapi membuat kelas gameB baru. Saya sekarang harus kembali menambahkan global gameA ke gameB yang merupakan pekerjaan ekstra. Juga menjadi sulit untuk mengkonfigurasi tipe pemuat konten yang saya inginkan. Katakanlah saya memiliki permainan yang berjalan di PC dan XBOX. Pada PC saya ingin pemuat konten yang juga dapat membuka dialog 'file terbuka'. Sementara di XBOX saya pasti tidak menginginkan ini. Dengan memiliki file konfigurasi, saya bahkan dapat melalui setengah permainan dengan mudah mengubah pemuat konten, bahkan dari tempat lain selain kelas gameA, tanpa hanya membuat global dalam gameA semuanya publik.

Sekarang pertimbangkan saya menggunakan pencari lokasi layanan. Saya selalu bisa terus menggunakannya. Dan bahkan layanan apa saja yang ada dapat berbeda setiap saat. Juga benar bahwa saya bahkan tidak akan peduli dengan implementasi mereka selama mereka memiliki antarmuka yang sama. (Meskipun saya bisa menggunakannya dalam gamA like class juga).

Pokoknya saya pikir Anda akan menemukan layanan game yang cukup berguna. Semua orang yang saya kenal menggunakannya. Untuk membantu Anda lebih banyak. Saya telah membuat kelas pembantu kecil di sekitar layanan game sehingga Anda dapat melakukan casting dengan sedikit lebih sedikit setiap saat: http://roy-t.nl/index.php/2010/08/25/xna-accessing-contentmanager -dan-alat grafis-di mana saja-kapan saja-the-gameservicecontainer / Saya menggunakannya cukup banyak.

Roy T.
sumber
Terima kasih balasannya. Di kelas yang membutuhkan layanan, apakah Anda biasanya hanya meminta kelas GameServices untuk layanan kapan pun diperlukan, atau apakah Anda membuat variabel anggota di kelas dan meminta layanan hanya di konstruktor? Saya kira apa yang saya tanyakan adalah seberapa lambat return (T)Instance.GetService(typeof(T));.
John Pollick
Juga, apa pendapat Anda tentang implementasi kelas GameServices ini? Saya menghapus singleton yang tidak perlu karena tidak memiliki fitur yang belum dimiliki abstraksi. Juga, saya menghapus Serviceakhiran redundan di akhir setiap metode.
John Pollick
Juga, saya pikir alasan bahwa AddServicemetode Layanan mengambil jenis adalah agar Anda dapat menentukan antarmuka layanan. Sebagai contoh Services.AddService(typeof(IGraphicsDeviceManager), graphics);,. Kemudian saat mengambil layanan Anda dapat menentukan antarmuka sebagai jenis dan melemparkannya ke subkelas yang Anda pilih.
John Pollick
@JohnPollick, untuk pertanyaan pertama. Saya mencoba untuk selalu memintanya (karena itu bisa saja berubah) tetapi jika saya benar-benar membutuhkan sesuatu setiap frame saya membuat variabel anggota. Saya tidak memiliki banyak statistik kinerja selain itu tidak pernah menjadi hambatan bagi saya. Yang kedua, ya kelihatannya baik-baik saja :). Dan untuk yang ketiga. Itu memang alasan untuk tipe argumen, namun Anda tidak boleh membuat kebiasaan downcasting mengambil nilai karena itu menghancurkan kemampuan Anda untuk menukar kelas sebagai layanan. Jika Anda tidak ingin IGraphicsDeviceManger tetapi MyGDM maka mungkin buat antarmuka baru.
Roy T.
1
Oh, aku tidak melihat kamu juga dicor. Tentu saja itu dapat menyimpulkan tipe jika Anda melakukan casting terlebih dahulu :).
Roy T.
5

Jadi mengapa tidak membuat saja contoh ini Singleton? Ya, karena Singletons buruk karena mereka memiliki keadaan global, mencegah pengujian, dan membuat desain Anda jauh lebih rapuh.

Lajang umumnya mengambil banyak sifat yang berguna dan mengemasnya bersama-sama dalam hibrida mengerikan yang memberi Anda beberapa hal yang tidak Anda inginkan bersama dengan bit mana pun yang Anda inginkan. (Apakah ini karakteristik 'ciptakan sesuai permintaan'? Cakupan global? Penegakan setidaknya satu contoh? Larangan banyak contoh?)

Penelusur layanan sama-sama dianggap sebagai anti-pola bagi banyak orang karena alih-alih hanya meneruskan ketergantungan pada suatu objek, Anda melewatkan pencari layanan (Game) yang memasangkan kelas tersebut dengan seluruh layanan.

Anda tidak dapat menghindari sambungan sepenuhnya. Hal-hal menggunakan hal-hal lain dan tanpa itu program Anda tidak melakukan apa-apa. Jadi satu-satunya pertanyaan sebenarnya adalah pada level apa abstraksi itu berada.

Sebagian besar teks tentang orientasi objek membuat perbedaan antara Komposisi dan Agregasi. Penting untuk mengetahui perbedaan konseptual antara sesuatu yang Anda miliki dan sesuatu yang Anda ketahui. Sayangnya sebagian besar bahasa modern tidak memiliki perbedaan yang jelas di sini, dan referensi ke suatu objek dapat berarti salah satu dari hal-hal ini. (Ironisnya, C ++ melakukan pekerjaan yang lebih baik, jika Anda menggunakan berbagai jenis penunjuk pintar.)

Salah satu cara di mana Anda dapat memperjelas komposisi dan agregasi dalam kode Anda adalah dengan menggunakan layanan untuk objek agregat. Layanan adalah salah satu cara untuk menyediakan akses ke barang-barang yang bukan milik Anda, tetapi dapat Anda gunakan.

Jadi mengapa Layanan direkomendasikan dalam XNA dan pengembangan game?

Saya tidak berpikir mereka direkomendasikan secara universal dalam pengembangan game.

Kylotan
sumber