Perakende oyunlar “kontrolün tersine çevrilmesi” ve “bağımlılık enjeksiyonu” kullanıyor mu?


30

Bildiğim daha çalışkan yazılım geliştiricilerin birçoğu, nesnelere referansları işlemek için kontrol ve bağımlılık enjeksiyonunun ters çevrilmesine geçiyor . Flash oyunlar açısından bakıldığında, AAA stüdyolarının tüm içeriğini ve çıkışlarını bilmiyorum, yani: bunlar perakende oyun dünyasında kullanılıyor mu?


Bence bu dünyadaki performans her şeyden önemli, çünkü daha fazla kullanıcı programcılardan daha düşük performansla kötü kodlardan etkilenecek.
Bart van Heukelom

Bağımlılık enjeksiyonu, bileşen tabanlı bir sistem gibi gözükmektedir, ancak kontrolün nasıl ters çevrileceğine dair bir örnek verir misiniz?
ADB

Bu konunun çoğu IoC'nin ne olduğu ve ne çözdüğü hakkında yanlış anlaşılıyor gibi görünüyor ve OP gerçekten ilk sırada gelecekteki ziyaretçiler için buraya işaret edeceğim
Boris Callen,

Evet onlar yapar. Aslında, Nadir Testlerini Hırsızlar Denizi'nde nasıl uyguladıkları hakkında bir konuşma yaptı - youtube.com/watch?v=KmaGxprTUfI&t=1s . Ne yazık ki, Unreal Engine'deki Inversion of Control hakkında bir şey söyleyemeyecek kadar çok şeyleri yoktu, ancak bunun nasıl çalıştığını gösteren bir proje yazdım: github.com/jimmyt1988/UE-Testing
Jimmyt1988

Yanıtlar:


45

Sen buna 'çalışkan yazılım geliştirme' diyorsun, ben 'acı verici mühendislik' olarak adlandırıyorum. Bu, kontrolün tersine çevrilmesinin kötü olduğu anlamına gelmez - aslında, bunun temel tanımı iyidir - ancak tüm çerçevelerin çoğalması ve tüm bunları elde etmek için çalışma yöntemlerinin deliliğin az olması, özellikle insanların yolsuzlukları ile birleştiği zaman zaman% 99'unun asla değişmeyeceğiniz değiştirilebilir bileşenlerin enjekte edilebilmesi için tamamen iyi ve temiz arayüzler. Bu, yalnızca Java kurumsal ortamından kaynaklanabilecek bir şeydir ve başka bir yerde çok fazla yer olmadığı için memnunum.

Genelde argüman, bileşenleri değiştirmeseniz bile, onları sahte nesneler ve benzerleriyle yalıtılmış bir şekilde test edebilmek istediğinizdir. Ancak, korkarım ki daha iyi bir test yapabilmek için bir arayüzü zorlamaya ve tartışmaya değer olduğu tartışmasını asla almayacağım. Test yapmak yalnızca bir şeyi kanıtlar - testlerin işe yaradığını. Diğer taraftan temiz ve minimal arayüzler, kodunuzun çalıştığını kanıtlamak için uzun bir yol kat ediyor.

Yani, kısa cevap: evet, ama düşündüğün şekilde değil. Bazen, birbiriyle değiştirilebilir davranışa ihtiyaç duyduğunuzda, bir nesneyi yeni nesnenin davranışının bir bölümünü belirleyen bir kurucuya iletirsiniz. Bu konuda.


5
+1 - Java topluluğunun çok basit bir fikir gibi görünen aşırı derecede karmaşık olduğu görülüyor.
Chris Howe,

4
Üretimde farklı uygulamaları değiştirmeniz gerekmediği, ancak otomatik testi kolaylaştırmak için özel uygulamalar enjekte etmeniz gerekebileceği fikri gerekli değildir. Bu bakımdan, DI / IoC oyunlarda kesinlikle faydalı olabilir, ancak bunu makul ölçüde kapsamda tutmak istiyorsunuz. Birkaç seferde birden fazla hizmet çözünürlüğüne yüksek seviyede ihtiyaç duymamanız gerekir - oyundaki her küçük nesne için hizmetleri çözmek istemezsiniz ve kesinlikle her kareye veya benzer bir şeye değil.
Mike Strobel

2
@Thomas Dufour: Test kavramı hiçbir şeyi ispatlayamaz. Bu sadece bir veri noktası. 100001 kez geçeceğini kanıtlamadan 100000 kez deneme geçişi yapabilirsiniz. Kanıt, konunun mantıksal analizinden gelir. Bu IoC konteynerlerinin ve benzerlerinin doğruluğu kanıtlamayı zorlaştırmak pahasına testi kolaylaştırdığını ve bunun kötü bir şey olduğuna inanıyorum.
Kylotan

13
@Kylotan bir test kavramı hiçbir şeyi kanıtlamaya çalışmaz . Verilen girdilerle olan davranışın beklendiği gibi olduğunu göstermeye çalışır. Ne kadar fazla davranışın doğru olduğu gösteriliyorsa, genel işlevin doğru olduğuna dair inancınız o kadar artar, ancak hiçbir zaman% 100'dür. Minimal bir arayüzün her şeyi kanıtladığı iddiası saçmadır.
çizgi-tom-bang

5
@Alex Schearer: Korkarım ki, formalize edilmiş bir IoC konteyner sistemi kullanmaya ihtiyaç duymanın ve genellikle testi kolaylaştırmak için ek yapıcı argümanlar veya fabrika sınıfları oluşturmanın hiçbir şekilde kodu daha iyi faktörlü ve kesinlikle yapmadığını kabul edemem. daha gevşek birleştiğinde. Aslında, hemen hemen OOP'un kilit bir yönü olan enkapsülasyonu çiğniyor. Tasarımlarını sürdürebilmek ve iyi bir sonuç ortaya çıkacağını ümit etmek için TDD'ye güvenmek yerine, insanlar yalnızca SOLID ilkelerini takip edebilirler.
Kylotan

17

Strateji Deseni , Kompozisyon , Bağımlılık Enjeksiyonu , hepsi çok yakından ilişkilidir.

Strateji Deseni bir Bağımlılık Enjeksiyonu biçimi olduğundan, örneğin Unity gibi motorlara bakarsanız, tamamen bu prensibe dayanırlar. Bileşenleri (Strateji Deseni) kullanımları, tüm motorlarına derinlemesine gömülüdür.

Bileşenlerin yeniden kullanılmasının yanı sıra, temel faydaylardan biri de, korkunç, derin sınıf hiyerarşilerinden kaçınmaktır.

İşte bu tür bir sistemi Neversoft'un Tony Hawk oyun serisine nasıl soktuğunu anlatan Mick West'in bir makalesi .

Hiyerarşinizi Geliştirin

Oldukça son yıllara kadar oyun programcıları sürekli olarak oyun varlıklarını temsil etmek için derin bir sınıf hiyerarşisi kullandılar. Gelgit, bu derin hiyerarşilerin kullanımından, bir oyun nesnesi bileşenlerinin toplanması olarak oluşturan çeşitli yöntemlere kaymaya başlıyor ...


2
+1, Hiyerarşinizi Geliştirin, tamamen unutmuş olduğum harika bir bağlantı. Scott Bilas slaytları da iyi - bunlar için doğru bağlantı ( scottbilas.com/files/2002/gdc_san_jose/game_objects_slides.pdf ). Bir ilgili slayttan başka bir set daha var, ama nerede olduğunu unuttum ...
Yalın

Ayrıca Bjarne Rene'nin Games Gems 5 (bence) adlı makalesinde de yer almaktadır.
Chris Howe,

13

Kontrolün Tersine Çevirilmesi (IoC) modeli hakkında çok fazla kafa karışıklığı var gibi görünüyor. Bazı insanlar, Strateji Örüntüsü veya Bileşen Model ile eşitledi, ancak bu karşılaştırma IoC'nin ne olduğunu gerçekten anlamadı. IoC gerçekten bir bağımlılığın nasıl elde edildiği ile ilgilidir. Sana bir örnek vereyim:

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
    }
}

Yukarıda Sprite.Load, a'ya bağımlı olduğu açıktır FileReader. Yöntemi test etmek istediğinizde aşağıdakilere ihtiyacınız vardır:

  1. Yerinde bir dosya sistemi
  2. Dosya sisteminden yüklenecek bir test dosyası
  3. Genel dosya sistemi hatalarını tetikleyebilme

İlk ikisi açıktır, ancak hata işlemenin beklendiği gibi çalıştığından emin olmak istiyorsanız, gerçekten de 3 numaraya ihtiyacınız var. Her iki durumda da, şimdi diske gitmeleri gerektiği için testlerinizi oldukça yavaşlattınız ve muhtemelen test ortamınızı daha karmaşık hale getirdiniz.

IoC'nin amacı, davranış kullanımını yapısından ayırmaktır. Bunun Strateji modelinden ne kadar farklı olduğuna dikkat edin. Strateji kalıbı ile amaç, tekrar kullanılabilir bir davranış yığınını kapsama almaktır; böylece gelecekte kolayca genişletebilirsiniz; stratejilerin nasıl inşa edildiği hakkında söyleyecek hiçbir şeyi yok.

Sprite.LoadYukarıdaki yöntemi tekrar yazacak olsaydık, sonuçta ortaya çıkar:

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

Şimdi, okuyucunun yapısını kullanımından ayırdık. Bu nedenle, test sırasında bir test okuyucusunda değişim yapmak mümkündür. Bu, test ortamınızın artık bir dosya sistemine ihtiyaç duymayacağı, dosyaları test edemeyeceği ve hata olaylarını kolayca simüle edebileceği anlamına gelir.

Yeniden yazmamda iki şey yaptığımı unutmayın. IReaderBazı davranışları içine alan bir arayüz yarattım - yani Strateji desenini uyguladı. Ayrıca, doğru okuyucuyu yaratma sorumluluğunu başka bir sınıfa taşıdım.

Belki yukarıdakileri tanımlamak için yeni bir kalıp ismine ihtiyacımız yoktur. Bana Strateji ve Fabrika modellerinin bir karışımı olarak saldırıyor (IoC konteynerleri için). Söyleniyor, gerçek bir problemi çözdüğü açıkça belli olduğundan, insanların bu kalıba neyin dayandığı konusunda emin değilim ve kesinlikle bunun Java ile ne yapması gerektiği açık değil.


2
Alex: Hiç kimse, gerektiğinde özel işlevsellik sağlamak için önceden oluşturulmuş nesneleri iletmeye itiraz etmiyor. Herkes yapar, tıpkı sizin örneğinizde olduğu gibi. Sorun, insanların sadece bu şeyleri işlemek için var olan tüm çerçeveleri kullandığı ve bu işlevselliğe bağlı olarak işlevselliğin her yönünü dini olarak kodlamasıdır. Önce Sprite inşaat parametre olarak iReader ekleyin ve sonra bu kolaylaştırmak için özel SpriteWithFileReaderFactory nesneleri ihtiyacı kadar sona vb Bu tutum vb Java ve Bahar IoC kapları gibi şeyler, kaynaklı gelmez
Kylotan

2
Ancak IoC konteynerleri hakkında konuşmuyoruz - en azından orijinal yazıyı göremiyorum. Sadece modelin kendisinden bahsediyoruz. Argüman, en iyi söyleyebileceğim gibi, "Vahşi doğada bazı araçlar kötü olduğu için, temel kavramları kullanmamalıyız." Bu beni bebeği banyo suyuyla atmak gibi vurur. Basitlik, işlerin yapılması ve sürdürülebilirlik / test edilebilirlik arasında doğru dengeye oturmak, proje bazında bir projede en iyi şekilde ele alınması zor bir problemdir.
Alex Schearer

Pek çok insanın
IoC'ye

4

Bunun birçoğu arasında bir araç olduğunu ve arada sırada kullanıldığını söyleyebilirim. Tenpn'nin söylediği gibi vtables (ve genel olarak herhangi bir ekstra yönlendirme) tanıtan herhangi bir yöntem performans cezasına sahip olabilir, ancak bu sadece düşük seviye kod için endişelenmemiz gereken bir şey. Gerçekten sorun olmayan üst düzey yapısal kod için ve IoC'nin olumlu faydaları olabilir. Sınıflar arasındaki bağımlılığı azaltan ve kodunuzu daha esnek hale getiren herhangi bir şey.


2
Kesin olmak gerekirse, birçok kez kare olarak adlandırılan herhangi bir kod için uygulanabilir cezalar hakkında endişeleniyorum. Bu düşük seviyeli olabilir veya olmayabilir.
tenpn

4

Bu konuda Kylotan ile aynı fikirdeyim. "Bağımlılık enjeksiyonu" çirkin bir Java kavramsal kusuruna karşı çirkin bir Java çözümüdür ve birinin başka dillerde de olsa bakmasının tek nedeni, Java'nın pek çok insan için ilk dil olması gerektiğidir.

Diğer taraftan, kontrolün tersine çevrilmesi uzun zamandır etrafta olan ve doğru yapıldığında çok yardımcı olan yararlı bir fikirdir. (Java / Bağımlılık Enjeksiyonu yöntemi değil.) Aslında, aklı başında bir programlama dilinde çalışıyorsanız, muhtemelen her zaman yaparsınız. Bu "IOC" olayını ilk kez okuduğumda, herkesin uğultu duyduğu bir şey vardı. Denetimin Tersine çevrilmesi, davranışını kişiselleştirmeye yardımcı olmak için işlev işaretçisini (veya yöntem işaretçisini) bir rutine veya nesneye geçirmekten başka bir şey değildir.

Bu, 1950'lerden bu yana olan bir fikir. C standart kütüphanesinde (qsort akla geliyor) ve Delphi ve .NET'teki her yerde (olay işleyicileri / delegeler) var. Eski kodu yeniden derlemeye gerek kalmadan eski kodun yeni şekilde çağrılmasını sağlar ve oyun motorlarında her zaman kullanılır.


2
Ben de oldu ait "böylece bu insanlar hakkında heyecanlandırdıklarını nedir?" DI hakkında okuduğumda, gerçek şu ki, çoğu oyun programcısı bunun ve bizim yaptığımız işe nasıl uygulanacağı hakkında bilgi edinmeye dayanıyor.
dash-tom-bang

2

Benim tecrübeme göre değil. Oyun kodunun uyarlanabilir olması gerektiğinden utanç verici ve bu yaklaşımlar kesinlikle yardımcı olacaktır.

Ancak, her iki yöntemin de, C ++ 'ta daha önce hiç olmadığı sanal tabloları getirip, bunlara uygun bir performans getireceği söylenebilir.


1

Mesleki bir oyun devi değilim ve sadece bir kez C ++ 'da IoC'yi uygulamayı denedim, bu sadece spekülasyon.

Ancak, oyun geliştiricilerin IoC hakkında şüpheli olacağından şüpheleniyorum çünkü:

1 / çok sayıda arabirim ve çok sayıda küçük sınıf tasarlama

2 / hemen hemen her fonksiyon çağrısına sahip olmak

Şimdi, bu bir tesadüf olabilir, ancak her ikisi de C ++ 'da (oyunda yaygın olarak kullanılan, öyle değil mi?) Performansları için biraz daha karmaşık olma eğilimindedir, IoC'nin yaygınlaştığı Java'da (muhtemelen? Yapması nispeten kolay olduğu için, insanlara daha iyi nesne hiyerarşileri tasarlamalarında yardım etti ve bazıları Java'da bir uygulama yazmanın XML'de bir uygulama yazmaya dönüştüğüne inanıyorlardı, ama bu başka bir tartışma: P)

Bu hiçbir anlam ifade etmiyorsa yorumlarla ilgileniyorum;)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.