Apakah game ritel menggunakan "inversi kontrol" dan "injeksi ketergantungan"?

30

Banyak pengembang perangkat lunak yang lebih rajin yang saya tahu bergerak ke inversi kontrol dan injeksi ketergantungan untuk menangani referensi ke objek. Berasal dari perspektif Flash games, saya tidak tahu semua seluk beluk studio AAA, jadi: apakah ini digunakan di dunia game ritel?

Iain
sumber
Saya pikir dalam hal kinerja dunia itu yang terpenting, karena lebih banyak pengguna akan terkena kinerja rendah daripada programmer dengan kode buruk.
Bart van Heukelom
Injeksi ketergantungan terdengar seperti sistem berbasis komponen, tetapi apakah Anda memiliki contoh tentang bagaimana seseorang akan melakukan inversi kontrol?
ADB
Karena sebagian besar utas ini tampaknya salah informasi tentang apa itu IoC dan apa yang dipecahkannya dan OP tidak benar-benar bertanya bahwa pertama-tama saya akan menunjukkan di sini untuk pengunjung masa depan: sebaslab.com/ioc-container-unity-part-1
Boris Callens
Ya mereka melakukanya. Faktanya, Rare telah berbicara tentang bagaimana mereka mengimplementasikan pengujian mereka di Sea of ​​Thieves - youtube.com/watch?v=KmaGxprTUfI&t=1s . Sayangnya mereka tidak banyak bicara tentang Pembalikan Kontrol di Unreal Engine, namun, saya telah menulis sebuah proyek yang menunjukkan cara kerjanya: github.com/jimmyt1988/UE-Testing
Jimmyt1988

Jawaban:

45

Anda menyebutnya 'pengembangan perangkat lunak yang rajin', saya menyebutnya 'overengineering yang menyakitkan'. Itu bukan untuk mengatakan bahwa inversi kontrol buruk - pada kenyataannya, definisi dasar itu baik - tetapi proliferasi seluruh kerangka kerja dan metode kerja untuk mencapai semua ini sedikit gila, terutama dikombinasikan dengan cara orang menghancurkan antarmuka yang sangat baik dan bersih untuk dapat menyuntikkan komponen yang dapat dipertukarkan yang 99% dari waktu Anda tidak akan pernah bisa dipertukarkan. Ini semacam hal yang hanya bisa berasal dari lingkungan perusahaan Java dan saya senang itu tidak memiliki banyak pijakan di tempat lain.

Seringkali argumennya adalah bahwa meskipun Anda tidak menukar komponen, Anda ingin dapat mengujinya secara terpisah dengan benda tiruan dan sejenisnya. Namun, saya khawatir saya tidak akan pernah membeli argumen bahwa itu layak membengkak dan menyulitkan antarmuka agar lebih dapat mengujinya. Pengujian hanya membuktikan satu hal - bahwa tes Anda berfungsi. Antarmuka yang bersih dan minimal membuktikan bahwa kode Anda berfungsi.

Jadi, jawaban singkatnya: ya, tapi tidak dengan cara Anda berpikir. Terkadang, ketika Anda membutuhkan perilaku yang dapat dipertukarkan, Anda akan meneruskan sebuah objek ke konstruktor yang menentukan bagian dari perilaku objek baru. Itu saja.

Kylotan
sumber
5
+1 - Saya setuju bahwa komunitas Jawa tampaknya memiliki terlalu rumit apa yang tampaknya menjadi ide yang sangat sederhana.
Chris Howe
4
Idenya tidak harus bahwa Anda perlu menukar implementasi yang berbeda dalam produksi, tetapi Anda mungkin ingin menyuntikkan implementasi khusus untuk memfasilitasi pengujian otomatis. Dalam hal itu, DI / IoC tentu bisa berguna dalam game, tetapi Anda ingin menjaganya tetap masuk akal. Anda seharusnya tidak membutuhkan lebih dari beberapa resolusi layanan satu kali di level tinggi - Anda tidak ingin menyelesaikan layanan untuk setiap objek kecil dalam game, dan tentu saja tidak setiap frame atau semacamnya.
Mike Strobel
2
@ Thomas Dufour: konsep ujian tidak pernah bisa membuktikan apa pun. Itu hanya titik data. Anda dapat memiliki tes lulus 100000 kali tanpa membuktikan bahwa itu akan lulus saat dijalankan 100001. Bukti berasal dari analisis logis dari materi pelajaran. Saya berpendapat bahwa wadah IoC ini dan sejenisnya membuat pengujian lebih mudah dengan mengorbankan membuat pembuktian kebenaran menjadi lebih sulit, dan saya percaya itu adalah hal yang buruk.
Kylotan
13
@Kylotan konsep tes tidak pernah mencoba membuktikan apa pun. Ia mencoba menunjukkan bahwa perilaku dengan input yang diberikan seperti yang diharapkan. Semakin banyak perilaku terbukti benar, semakin besar keyakinan Anda bahwa fungsi keseluruhan benar tetapi tidak pernah 100%. Pernyataan bahwa antarmuka minimal membuktikan apa pun adalah menggelikan.
dash-tom-bang
5
@Alex Schearer: Saya khawatir saya tidak akan pernah menerima bahwa perlu menggunakan sistem wadah IoC yang diformalkan dan biasanya membuat argumen konstruktor tambahan atau kelas pabrik untuk memfasilitasi pengujian, dengan cara apa pun, membuat kode lebih diperhitungkan, dan tentu saja tidak membuatnya lebih longgar ditambah. Sebenarnya itu cukup banyak menginjak enkapsulasi, aspek kunci dari OOP. Alih-alih mengandalkan TDD untuk mendorong desain mereka dan berharap bahwa hasil yang baik muncul, orang hanya bisa mengikuti prinsip-prinsip SOLID di tempat pertama.
Kylotan
17

Pola Strategi , Komposisi , Injeksi Ketergantungan , semuanya sangat terkait erat.

Karena Pola Strategi adalah bentuk Injeksi Ketergantungan, jika Anda melihat mesin seperti Unity misalnya, mereka sepenuhnya didasarkan pada prinsip ini. Penggunaan Komponen (Pola Strategi) mereka sangat tertanam dalam seluruh mesin mereka.

Salah satu manfaat utama selain menggunakan kembali komponen adalah untuk menghindari hierarki kelas yang dalam yang ditakuti.

Berikut adalah artikel oleh Mick West yang berbicara tentang bagaimana ia memperkenalkan sistem jenis ini ke dalam seri permainan Tony Hawk oleh Neversoft.

Berevolusi Hirarki Anda

Hingga tahun-tahun belakangan ini, programmer game secara konsisten menggunakan hierarki kelas yang dalam untuk mewakili entitas game. Air pasang mulai bergeser dari penggunaan hierarki yang dalam ini ke berbagai metode yang menyusun objek entitas gim sebagai agregasi komponen ...

David Young
sumber
2
+1, Evolve Your Hierarchy adalah tautan bagus yang benar-benar saya lupakan. Slide Scott Bilas juga bagus - tautan yang benar untuk ini adalah ( scottbilas.com/files/2002/gdc_san_jose/game_objects_slides.pdf ). Ada satu set lagi slide terkait, tapi saya lupa di mana ...
leander
Juga artikel di Games Gems 5 (saya pikir) oleh Bjarne Rene.
Chris Howe
13

Tampaknya ada banyak kebingungan tentang pola Inversion of Control (IoC). Sejumlah orang telah menyamakannya dengan Pola Strategi atau Model Komponen, tetapi perbandingan ini tidak benar-benar menangkap tentang apa itu IoC. IOC benar-benar tentang bagaimana ketergantungan diperoleh. Biarkan saya memberi Anda sebuah contoh:

class Game {
    void Load() {
        this.Sprite.Load(); // loads resource for drawing later
    }
}

class Sprite {
    void Load() {
        FileReader reader = new FileReader("path/to/resource.gif");
        // load image from file
    }
}

Di atas jelas bahwa Sprite.Loadmemiliki ketergantungan pada a FileReader. Saat Anda ingin menguji metode ini, Anda memerlukan yang berikut ini:

  1. Sistem file di tempat
  2. File uji untuk memuat dari sistem file
  3. Kemampuan untuk memicu kesalahan sistem file yang umum

Dua yang pertama sudah jelas, tetapi jika Anda ingin memastikan bahwa penanganan kesalahan Anda berfungsi seperti yang diharapkan, Anda benar-benar membutuhkan # 3 juga. Dalam kedua kasus Anda berpotensi memperlambat tes Anda sedikit karena mereka sekarang harus pergi ke disk dan Anda cenderung membuat lingkungan pengujian Anda lebih rumit.

Tujuan dari IoC adalah untuk memisahkan penggunaan perilaku dari konstruksinya. Perhatikan bagaimana ini berbeda dari pola Strategi. Dengan pola Strategi, tujuannya adalah untuk merangkum sejumlah perilaku yang dapat digunakan kembali sehingga Anda dapat dengan mudah memperluasnya di masa depan; tidak ada yang bisa dikatakan tentang bagaimana strategi dibangun.

Jika kita menulis ulang Sprite.Loadmetode di atas, kita mungkin akan berakhir dengan:

class Sprite {
    void Load(IReader reader) {
        // load image through reader
    }
}

Sekarang, kami telah memisahkan konstruksi pembaca dari penggunaannya. Oleh karena itu, mungkin untuk menukar pembaca tes selama pengujian. Ini berarti bahwa lingkungan pengujian Anda tidak lagi membutuhkan sistem file, menguji file, dan dapat dengan mudah mensimulasikan peristiwa kesalahan.

Perhatikan bahwa saya melakukan dua hal dalam penulisan ulang. Saya membuat antarmuka IReaderyang merangkum beberapa perilaku - yaitu menerapkan pola Strategi. Selain itu, saya memindahkan tanggung jawab untuk menciptakan pembaca yang tepat ke kelas lain.

Mungkin kita tidak perlu nama pola baru untuk menggambarkan hal di atas. Itu menurut saya sebagai campuran dari Strategi dan pola Pabrik (untuk wadah IOC). Karena itu, saya tidak yakin dengan alasan apa orang keberatan dengan pola ini karena jelas bahwa itu memecahkan masalah nyata, dan, tentu saja, tidak jelas bagi saya apa hubungannya dengan Jawa.

Alex Schearer
sumber
2
Alex: tidak ada yang keberatan untuk lewat objek yang sudah dibuat untuk mendorong fungsionalitas khusus di mana diperlukan. Semua orang melakukannya, seperti dalam contoh Anda. Masalahnya adalah di mana orang menggunakan seluruh kerangka kerja yang ada murni untuk menangani hal-hal ini, dan secara religius mengkode setiap aspek fungsionalitas untuk bergantung pada fungsi ini. Mereka pertama-tama menambahkan IReader sebagai parameter untuk konstruksi Sprite, dan akhirnya membutuhkan objek SpriteWithFileReaderFactory khusus untuk memfasilitasi ini, dll. Sikap ini memang berasal dari Jawa dan hal-hal seperti wadah
IoC
2
Tapi kita tidak berbicara tentang wadah IOC - setidaknya saya tidak melihatnya di pos asli. Kami hanya berbicara tentang polanya sendiri. Argumen Anda, seperti yang bisa saya katakan, adalah "Karena beberapa alat di alam liar buruk, kita tidak boleh menggunakan konsep yang mendasarinya." Itu menurut saya seperti membuang bayi keluar dengan air mandi. Memukul keseimbangan yang tepat antara kesederhanaan, menyelesaikan sesuatu, dan rawatan / testabilitas adalah masalah sulit yang mungkin paling baik ditangani pada proyek berdasarkan proyek.
Alex Schearer
Saya curiga banyak orang menentang IoC karena itu berarti:
phtrivier
4

Saya akan mengatakan bahwa itu adalah salah satu alat di antara banyak, dan digunakan pada kesempatan. Seperti yang dikatakan tenpn, metode apa pun yang memperkenalkan vtables (dan umumnya tipuan tambahan apa pun) dapat memiliki penalti kinerja, tetapi ini adalah sesuatu yang hanya perlu kita khawatirkan untuk kode tingkat rendah. Untuk kode struktural tingkat tinggi yang sebenarnya bukan masalah, dan IoC dapat memiliki manfaat positif. Apa pun untuk mengurangi ketergantungan antar kelas dan membuat kode Anda lebih fleksibel.

Chris Howe
sumber
2
Lebih tepatnya saya khawatir tentang hukuman vtable untuk kode apa pun yang disebut berkali-kali bingkai. Ini mungkin level rendah atau tidak.
tenpn
4

Harus setuju dengan Kylotan yang satu ini. "Dependency injection" adalah solusi Java yang jelek untuk cacat konseptual Java yang jelek, dan satu-satunya alasan mengapa orang melihatnya dalam bahasa lain adalah karena Java menjadi bahasa pertama bagi banyak orang, padahal sebenarnya tidak.

Inversi kontrol, di sisi lain, adalah ide yang berguna yang sudah ada sejak lama, dan sangat membantu ketika dilakukan dengan benar. (Bukan cara Java / Dependency Injection.) Faktanya, Anda mungkin melakukannya sepanjang waktu jika Anda bekerja dalam bahasa pemrograman yang waras. Ketika saya pertama kali membaca tentang semua hal "IOC" yang didengungkan oleh semua orang, saya benar-benar underwhelmed. Inversion of Control tidak lebih dari melewatkan penunjuk fungsi (atau penunjuk metode) ke rutin atau objek untuk membantu menyesuaikan perilakunya.

Ini adalah ide yang sudah ada sejak 1950-an. Ada di pustaka standar C (qsort terlintas di benak) dan semuanya ada di Delphi dan .NET (event handler / delegates). Ini memungkinkan kode lama untuk memanggil kode baru tanpa perlu mengkompilasi ulang kode lama, dan digunakan sepanjang waktu di mesin permainan.

Mason Wheeler
sumber
2
Saya juga dari "jadi ini yang membuat orang bersemangat?" ketika saya membaca tentang DI, tetapi faktanya adalah sebagian besar programmer game dapat berdiri untuk mempelajarinya dan tentang bagaimana itu akan diterapkan pada pekerjaan yang kita lakukan.
dash-tom-bang
2

Tidak dalam pengalaman saya. Yang memalukan, karena kode gim harus sangat mudah beradaptasi, dan pendekatan ini pasti akan membantu.

Namun harus dikatakan bahwa kedua metode bisa, dalam C ++, memperkenalkan tabel virtual di mana tidak ada sebelumnya, membawa serta mereka hit kinerja yang sesuai.

tenpn
sumber
1

Saya bukan pengembang permainan profesional, dan hanya mencoba menerapkan IoC di C ++ sekali, jadi ini hanya berspekulasi.

Namun, saya menduga para pengembang game akan curiga tentang IoC karena itu berarti:

1 / mendesain banyak antarmuka dan banyak kelas kecil

2 / memiliki hampir semua panggilan fungsi sedang terikat

Sekarang, itu mungkin kebetulan, tetapi keduanya cenderung sedikit lebih rumit dan / atau bermasalah untuk kinerja di C ++ (yang banyak digunakan dalam game, bukan?) Daripada di Jawa, di mana IoC menjadi luas (Mungkin karena itu relatif mudah dilakukan, membantu orang mendesain hierarki objek yang lebih waras, dan karena beberapa percaya itu bisa mengubah penulisan aplikasi di Jawa menjadi menulis aplikasi dalam XML, tapi itu debat lain: P)

Saya tertarik pada komentar jika itu tidak masuk akal sama sekali;)

dokter hewan
sumber