Це погана ідея мати статичний Game1 в XNA?


10

Чи справді погана ідея мати свій Game1клас статичним? Наразі в моєму Game1класі у мене є клас, TileHandlerякий називається, що обробляє все, що стосується мого поточного набору плиток, і AnimalHandlerякий обробляє всіх моїх тварин (на диво).

Тепер, якщо я перебуваю AnimalHandlerі хочу перевірити, чи плитка може проходити з TileHandlerтих пір, це спричиняє проблеми, або мені доведеться передати список горілочних плиток AnimalHandler, що я б краще не робив.

Що було б простіше було б стати Game1статичним, а потім AnimalHandlerпросто йти Game1._tileHandler.WalkableTile(position).

Тепер я не можу побачити щось негайно з цим чи з чим-небудь, що спричинило б проблеми, але я тільки почав використовувати статичні класи, тому хто-небудь більш обізнаний бачить якусь гігантську причину, чому це погана ідея?

Відповіді:


9

Тепер я не можу побачити щось негайно з цим чи з чим-небудь, що спричинило б проблеми, але я тільки почав використовувати статичні класи, тому хто-небудь більш обізнаний бачить якусь гігантську причину, чому це погана ідея?

Коли у вас новий блискучий молоток, кожна проблема виглядає як цвях.

Взагалі немає нічого поганого в статичних класах та / або методах, якщо їх правильно використовувати (для речей, які не мають або не залежать від стану екземпляра). Однак у вашому випадку ви зловживаєте ними, щоб приховати залежність від конкретної інстанції, плутаючи це з видаленням залежності. Виявляється також, що ви виставляєте деталі реалізації Game1класу, що також взагалі погано.

Ось суть вашої проблеми:

... якщо я заїжджаю AnimalHandlerі хочу перевірити, чи плитка може проходити з TileHandlerтих пір, це спричиняє проблеми або мені доведеться передати список горілочних плиток AnimalHandler, що я б краще не робив.

Ігнорування можливості того, що AnimalHandlerпотреба в цих плитках сама по собі може бути поганим дизайном (з назвами, які ви вибрали, важко сказати деталі цих класів) на даний момент ... якщо AnimalHandlerпотрібен список прогулянкових плиток, то їй потрібен список горяча плитка. Зазвичай краще зробити залежності більш явними, ніж менш , оскільки це робить код більш самодокументованим. Передаючи цей список безпосередньо AnimalHandler, ви явно викликаєте той факт, що йому потрібен такий список. Якщо ви замість цього зробите все статичним і загальнодоступним, щоб ви могли просто отримати доступ до статичного списку, який міститься в іншому місці коду, все, що ви робите, - це приховати залежність, фактично не вирішуючи і не знімаючи її.

Для невеликої гри, яка не потребує масштабуванні, сама по собі ця проблема не буде проблемою, але вона може призвести вас по шляху шкідливої ​​звички, тому ви, можливо, захочете не вважати цього. Принаймні майте це на увазі для наступного проекту, над яким ви працюєте.


Амінь! Ви торкаєтесь чудового моменту, про який я насправді не говорив у своїй відповіді.
Нейт

+1 ховати залежності та запроваджувати глобальний стан - це справді проблема
ashes999

4

Причина того, що виклик TileHandler в статичному контексті не є найкращим можливим дизайном, полягає в тому, що він з'єднує компоненти вашого дизайну, які в іншому випадку можуть бути роз'єднані.

Якщо ви вирішите мати більше одного TileHandler у майбутньому, вам доведеться зробити багато роботи, щоб прийняти цю зміну.

Якщо ви вирішите видалити TileHandler, вам доведеться зробити багато роботи, щоб пристосувати цю зміну.

Припустимо, ви будуєте інший рівень / зону в майбутньому, яка обробляє плитки не так, як ваш поточний TileHandler. Тоді вам або потрібно мати спосіб вказати метод керування плитками для використання, або вам потрібно зателефонувати до іншого обробника.

Якщо TileHandler був переданий як параметр для об'єктів, які його використовують, то ви можете просто передати наступний раз інший або встановити інший обробник плитки для об'єктів, які його використовують пізніше.

Особисто я отримую доступ до багатьох речей у своїх іграх XNA зі статичного контексту і вважаю, що ніколи не буду мати більше ніж одну з них.

Якщо ви хочете мати змогу повторно використовувати свій ігровий код у наступній грі, вам, ймовірно, доведеться переписати велику частину речей, які ви зараз написали як статичні.

Коротко:

На користь не використовувати статичний контекст:

Передача об'єктів як параметрів максимально роз'єднує ігрові елементи, і дозволяє легше змінювати / використовувати їх для поточних чи майбутніх проектів. Це також дозволяє трохи легше керувати складністю великої кількості коду (подумайте про те, щоб мати сотні статичних менеджерів у вашому ігровому класі, у великій грі).

На користь статичного контексту:

Оголошення та доступ до об'єктів із статичного контексту полегшує написання невеликих ігор, для яких не потрібні сотні статичних менеджерів. Спрощує багато методів і конструкторів, не вимагаючи одного або декількох додаткових параметрів, які замість них отримують статичний доступ.


2

Я не думаю, що це дуже погана ідея для простої гри, але ви також можете подивитися на http://www.nuclex.org/articles/4-architecture/6-game-components-and-game-services для краща ідея про те, як будувати взаємодіючі компоненти гри


Чи можете ви придумати якісь проблеми, якби це була не проста гра?
Гарольд

Читання кодом, перевіряемость та хороша архітектурна практика пропонують цього уникати.
smnbss

2

Такі речі, як TileHandler та AnimalHandler, я поставив би рівень вище на екрані гри. Чи потрібен ваш титульний екран доступу до TileHandler і чи ініціалізується він при першому завантаженні гри? Напевно, ні.

Ознайомтеся зі зразком управління державою XNA . У ньому багато коду, але в основному основна гра просто ініціалізує стек ігрових станів (або екранів). Кожен екран досить незалежний від інших і працює як спрощена версія самої гри. Ваш PlayScreen може мати статичні елементи, тому вони доступні компонентам PlayScreen.

У базовій грі я використовую кілька статик, але вони дуже низького рівня, такі як читачі InputHelper, Log або Config. Вони досить стандартні у всіх іграх, тому базовий двигун можна швидко та легко переносити. Екрани - це місце, де відбувається фактична логіка гри. Так довга відповідь коротка - ні, я не думаю, що це теоретично погана ідея, просто будьте уважні, що ви робите статичними. Коли ви продовжуєте робити щось статичне, це велика робота, якщо ви передумаєте.


0

Підняті тут бали - це все добре. На моєму досвіді (який з адміністративної вагою більше відноситься до бізнес-додатків, ніж до ігор), для статичних класів та учасників є велике використання, і я використовував їх багато разів. Я виявив, що в міру зростання вимог і складності я закінчую переробку цих статичних класів і перетворення їх у класи екземплярів і починаю передавати їх.

Я хотів би зауважити, що якщо використання статичного класу допоможе вам вийти з цієї гри, перейдіть до цього, але все-таки робіть правильні речі: реалізуйте інтерфейс або базовий клас, щоб легше було вирвати його та конвертувати пізніше це клас екземпляра.

Унція профілактики коштує півлітра вилікувати, тому переконайтесь, що ваш статичний клас не прив’язує вас до себе, що ускладнює зміни. Досить легко переробити метод за допомогою статичного класу, який реалізує інтерфейс, тому він приймає новий параметр інтерфейсу і використовує цей інтерфейс замість статичного посилання на клас.


0

Так, це взагалі завжди погана ідея.

Перетворення об’єктів, що містять зміни даних (тобто нічого, крім констант лише для читання та таблиць пошуку), у статичні класи - це хороший дизайн.

  1. Це сприяє випадкових залежностей, які вбивають модульність і перешкоджають повторному використанню коду. Припустимо, що ви хотіли написати редактор для своєї гри - у вас раптом багато класів плакали за Game1те, що ви не можете легко перейти до спільної бібліотеки.

  2. Ваш код стає нестабільним. Підрозділ тестування працює, виділяючи окремі класи від решти, глузуючи або моделюючи їх залежності (які повинні бути мінімально можливими). Будь-який статичний клас є відповідальністю, оскільки до нього можна отримати доступ у будь-який час, перенести стан над декількома тестами або вимагати його ініціалізації, перш ніж тести зможуть досягти успіху.

  3. Він приховує залежності. Так само, як анти-шаблон постачальника послуг (також зайнятий XNA, Game.Services), ваші класи можуть вибирати залежності, яких ви не бачите зовні.

Цей підхід стає особливо отруйним, якщо поєднувати статичні класи з дзвінками вантажних поїздів (Thingsl ike Game.Instance.ActorManager.Enemies.FindInRange(10)- так називається через символи, пов’язані з поїздами, що нагадують поїзд), де компоненти несподівано вимагають не лише Gameкласу, але й такого, який має статичну Instanceвластивість, яка повертає щось із ActorManagerвластивість , яке має Enemiesвластивість , яке повертає об'єкт з FindInRange()методом.

Єдиним виправданням, яке я б прийняв для написання змінних статичних класів, було б те, що все ще навчається і не має можливості послідовно застосовувати хороший дизайн та навчене око для виявлення поганого вибору.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.