XNA'da Game1 statik olması kötü bir fikir mi?


10

Game1Sınıfımı statik olarak almak gerçekten kötü bir fikir mi? Sınıfımda şu anda olduğu gibi şu anki fayans setimle ilgili her şeyi işleyen ve tüm hayvanlarımı (şaşırtıcı bir şekilde) işleyen Game1bir sınıf var .TileHandlerAnimalHandler

Şimdi ben AnimalHandlerve ben bir kiremit yürünebilir olup olmadığını kontrol etmek istiyorsanız TileHandlero zaman bu sorunlara neden olur ya da ben AnimalHandlerdeğil tercih ederim içine yürünebilir fayans bir listesini geçmek zorunda.

Daha kolay olan Game1statik hale gelip sonra AnimalHandlersadece gitmek olacaktır Game1._tileHandler.WalkableTile(position).

Şimdi bununla ilgili yanlış bir şey göremiyorum veya herhangi bir soruna neden olacak bir şey göremedim ama sadece statik sınıfları kullanmaya başladım, bu yüzden daha bilgili olan herkes bunun kötü bir fikir olmasının devasa bir nedenini görüyor mu?

Yanıtlar:


9

Şimdi bununla ilgili yanlış bir şey göremiyorum veya herhangi bir soruna neden olacak bir şey göremedim ama sadece statik sınıfları kullanmaya başladım, bu yüzden daha bilgili olan herkes bunun kötü bir fikir olmasının devasa bir nedenini görüyor mu?

Yeni bir çekiçiniz olduğunda, her sorun bir çiviye benziyor.

Genel olarak, uygun şekilde kullanılırlarsa (örnek başına duruma sahip olmayan veya duruma bağlı olmayan şeyler için) statik sınıflar ve / veya yöntemlerle ilgili yanlış bir şey yoktur . Bununla birlikte, sizin durumunuzda , örnek başına bağımlılığı gizlemek için onları yanlış kullanıyorsunuz , bunu bağımlılığı ortadan kaldırmakla karıştırıyorsunuz. Ayrıca, Game1sınıfın uygulama ayrıntılarını da açığa çıkarıyorsunuz , ki bu da genellikle kötüdür.

Sorununuzun temel noktası:

... eğer AnimalHandlerbir yerdeyim ve bir kiremitin yürünebilir olup olmadığını kontrol etmek istiyorsanız, TileHandlerbu sorunlara neden oluyor ya da içine girmemeyi AnimalHandlertercih edeceğim bir yürünebilir kiremit listesini geçirmem gerekiyor.

Bu karolara AnimalHandlerihtiyaç duyma olasılığını görmezden gelmek, kendisi için kötü bir tasarım olabilir (seçtiğiniz isimlerle bu sınıfların detaylarını söylemek zor) ... AnimalHandleryürünebilir karoların bir listesine ihtiyaç duyuyorsa , o zaman yürünebilir fayans. Bağımlılıkları daha azdan daha açık hale getirmek genellikle daha iyidir , çünkü kodu daha fazla kendi kendine belgelendirir. Listeyi doğrudan adresine ileterek, AnimalHandlerböyle bir listeye ihtiyaç duyduğunu açıkça söylersiniz. Bunun yerine, her şeyi statik ve herkese açık hale getirirseniz, kodun başka bir yerinde tutulan statik listeye erişebilirsiniz, tek yapmanız gereken bağımlılığı gerçekten çözmeden veya kaldırmadan gizlemektir .

Ölçeklendirmesi gerekmeyen küçük bir oyun için bu bir problem olmayacaktır, ancak sizi kötü bir alışkanlığın yoluna götürebilir, bu yüzden yapmamayı düşünebilirsiniz. En azından üzerinde çalıştığınız bir sonraki proje için bunu aklınızda bulundurun.


Amin! Cevabımda gerçekten bahsetmediğim harika bir noktaya değindin.
Nate

+1 bağımlılıkları gizleme ve küresel devleti tanıtmak gerçekten sorun
ashes999

4

TileHandler'ı statik bir bağlamda çağırmanın nedeni mümkün olan en iyi tasarım değildir, aksi takdirde ayrılabilecek tasarımınızın bileşenlerini birleştirmesidir.

Gelecekte birden fazla TileHandler'a sahip olmayı seçerseniz, bu değişikliği gerçekleştirmek için çok fazla iş yapmanız gerekir.

TileHandler'ı kaldırmayı seçerseniz, bu değişikliği gerçekleştirmek için çok fazla iş yapmanız gerekir.

Gelecekte fayansları geçerli TileHandler'ınızdan farklı bir şekilde işleyen farklı bir seviye / bölge oluşturduğunuzu varsayalım. Daha sonra, kullanmak için döşeme işleme yöntemini belirtmenin bir yoluna sahip olmanız veya farklı bir işleyici çağırmanız gerekir.

TileHandler, onu kullanan nesnelere parametre olarak iletildiyse, bir dahaki sefere farklı bir geçiş yapabilir veya daha sonra kullanan nesnelere farklı bir döşeme işleyicisi ayarlayabilirsiniz.

Şahsen, XNA oyunlarımdaki birçok şeye statik bir bağlamdan erişiyorum ve hiçbir zaman birden fazlasına sahip olamayacağımı varsayıyorum.

Oyun motoru kodunuzu bir sonraki oyununuzda yeniden kullanmak istiyorsanız, büyük olasılıkla şu anda statik olarak yazdığınız şeylerin çoğunu yeniden yazmanız gerekecektir.

Kısacası:

Statik bağlam kullanılmaması lehine:

Nesneleri olabildiğince parametre olarak geçirmek, oyun öğelerini ayırır ve mevcut veya gelecekteki projeler için bunları kolayca değiştirmenize / yeniden kullanmanıza olanak tanır. Ayrıca büyük miktarda kodun karmaşıklığını biraz daha kolay yönetmenizi sağlar (büyük bir oyunda oyun sınıfınızda yüzlerce statik yöneticiye sahip olmayı düşünün).

Statik bağlam lehine:

Statik bir bağlamdan nesnelere bildirimde bulunmak ve erişmek, yüzlerce statik yönetici gerektirmeyen küçük oyunlar yazmayı kolaylaştırır. Statik olarak erişilen bir veya daha fazla fazladan parametreye ihtiyaç duymadan birçok yöntemi ve yapıcıyı basitleştirir.


2

Bunun basit bir oyun için süper kötü bir fikir olduğunu düşünmüyorum, ancak http://www.nuclex.org/articles/4-architecture/6-game-components-and-game-services adresine de göz atabilirsiniz . iletişim oyun bileşenlerinin nasıl oluşturulacağı hakkında daha iyi bir fikir


Sadece basit bir oyun olmasaydı herhangi bir problem düşünebilir misiniz?
Harold

Kod okunabilirliği, test edilebilirliği ve iyi mimari uygulamaları bundan kaçınmayı önerir.
smnbss

2

TileHandler ve AnimalHandler gibi şeyler bir oyun ekranına bir üst seviye koyardım. Başlık ekranınızın TileHandler'a erişmesi gerekiyor mu ve oyun ilk yüklendiğinde başlatılıyor mu? Muhtemelen değil.

Check out XNA Devlet Yönetimi örneği . Orada çok fazla kod var, ancak temelde oyun sadece bir oyun durumu (veya ekran) yığını başlatır. Her ekran diğerlerinden oldukça bağımsızdır ve Oyunun basitleştirilmiş bir versiyonu olarak çalışır. PlayScreen'inizin statik üyeleri olabilir, böylece PlayScreen bileşenleri tarafından erişilebilir olurlar.

Temel Oyun'da birkaç statik kullanıyorum, ancak InputHelper, Log veya Config okuyucuları gibi çok düşük seviyeli şeyler. Tüm motorlarda oldukça standarttırlar, böylece temel motor hızlı ve kolay bir şekilde taşınabilir. Ekranlar gerçek oyun mantığının gerçekleştiği yerdir. Uzun cevap kısa - hayır, bunun teoride kötü bir fikir olduğunu düşünmüyorum, sadece statik yaptığınız şeylere dikkat edin. Devam edip statik bir şey yaptıktan sonra, fikrinizi değiştirirseniz muazzam bir iş.


0

Burada ortaya atılan noktaların hepsi iyi. Deneyimlerime göre (kuşkusuz iş uygulamalarına oyunlardan daha ağırlıklı), statik sınıflar ve üyeler için harika kullanımlar var ve bunları birçok kez kullandım. Gereksinimler ve karmaşıklık arttıkça, bu statik sınıfları geri dönüştürdüğümü ve bunları örnek sınıflarına dönüştürdüğümü ve etrafta dolaşmaya başladığımı fark ettim.

Belirtmek istediğim nokta, statik bir sınıf kullanmak, bu oyunu çıkarmanıza yardımcı oluyorsa , devam edin, ancak yine de doğru şeyleri yapın: bir arabirimi veya temel sınıfı uygulayın, böylece kopyalayıp dönüştürmek daha kolay daha sonra bir örnek sınıfına.

Bir ons önleme, bir kiloluk tedaviye değer, bu nedenle statik sınıfınızın sizi zorla bağlamadığından emin olun, bu da değiştirmeyi zorlaştırır. Bir arabirimi uygulayan statik bir sınıf kullanarak bir yöntemi yeniden düzenlemek oldukça kolaydır, böylece yeni bir arabirim parametresini kabul eder ve statik sınıf başvurusu yerine bu arabirimi kullanır.


0

Evet, genellikle her zaman kötü bir fikirdir.

Değişen veriler içeren nesneleri (yani salt okunur sabitler ve arama tabloları dışında herhangi bir şey) statik sınıflara dönüştürmek, iyi tasarımın dalış yaptığı yerdir.

  1. Modülerliği öldüren ve kodun yeniden kullanılmasını engelleyen gelişigüzel bağımlılıkları teşvik eder. Oyununuz için bir editör yazmak istediğinizi varsayalım - birdenbire ağlayan ve Game1paylaşımlı bir kütüphaneye kolayca geçemeyeceğiniz birçok dersiniz olacaktı .

  2. Kodunuz test edilemez hale gelir. Birim testi, bağımlılıkları alay ederek veya simüle ederek (mümkün olduğunca asgari düzeyde tutulmalıdır) bireysel sınıfları diğerlerinden izole ederek çalışır. Herhangi bir statik sınıf bir yükümlülüktür, çünkü herhangi bir zamanda erişilebilir, birden fazla test üzerinden durumu taşıyabilir veya testlerin başarılı olabilmesi için başlatılması gerekir.

  3. Bağımlılıkları gizler. Servis sağlayıcı anti-pattern (XNA, Game.Services tarafından da kullanılır) gibi, sınıflarınız dışarıda görmediğiniz bağımlılıkları seçebilir.

Bu yaklaşım, özellikle statik sınıfları yük tren çağrılarıyla ( Game.Instance.ActorManager.Enemies.FindInRange(10)tren benzeri araba benzeri zincir sembolleri nedeniyle adlandırılan şeyler ) birleştirirse, bileşenlerin aniden sadece bir Gamesınıfa değil, aynı Instancezamanda bir nesneyi döndüren bir özelliğe ActorManagersahip bir EnemiesözellikFindInRange() yöntemi.

Değişken statik sınıflar yazmak için kabul edeceğim tek mazeret hala öğreniyor olacak ve kötü seçimleri tespit etmek için sürekli olarak iyi tasarım ve eğitimli bir göz uygulama yeteneğine sahip değil.

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.