Чи використовують роздрібні ігри «інверсія контролю» та «введення залежності»?


30

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


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

Ін'єкційна залежність звучить як система, що базується на компонентах, але чи маєте ви приклад того, як можна зробити інверсію управління?
ADB

Оскільки, здається, більшість цього потоку неправильно поінформована про те, що таке ІОК і що вона вирішує, а ОП насправді не просить, що в першу чергу я зазначу тут майбутніх відвідувачів: sebaslab.com/ioc-container-unity-part-1
Борис Калленс

Так, вони роблять. Насправді, Рідкісні говорили про те, як вони проводять свої випробування в Морі злодіїв - youtube.com/watch?v=KmaGxprTUfI&t=1s . На жаль, їм не було надто багато сказати про інверсію управління в Unreal Engine, проте я написав проект, який демонструє, як він працює: github.com/jimmyt1988/UE-Testing
Jimmyt1988

Відповіді:


45

Ви називаєте це «сумлінною розробкою програмного забезпечення», я називаю це «болісною пересистемою». Це не означає, що інверсія контролю є поганою - насправді основне її визначення є хорошим, - але розповсюдження цілих рамок і методів роботи, щоб досягти всього цього, є мало не божевільним, особливо в поєднанні з тим, як люди трапляються ідеально хороший та чистий інтерфейси для того, щоб можна було вводити взаємозамінні компоненти, які 99% часу ви ніколи не обміняєтесь. Це така річ, яка могла походити лише з корпоративного середовища Java, і я радий, що в ній немає стільки опори.

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

Отже, коротка відповідь: так, але не так, як ви думаєте. Іноді, коли вам потрібна взаємозамінна поведінка, ви переходите в об'єкт до конструктора, який диктує частину поведінки нового об’єкта. Ось про це.


5
+1 - Я погоджуюсь, що, здається, у спільноти Java значно надмірно складно, що здається дуже простою ідеєю.
Кріс Хоу

4
Ідея необов'язково полягає в тому, що вам потрібно буде замінювати різні реалізації у виробництві, але ви можете ввести спеціальні реалізації для полегшення автоматизованого тестування. У цьому відношенні DI / IoC, безумовно, може бути корисним в іграх, але ви хочете, щоб це було достатньо обсяг. Вам не потрібно більше ніж кілька разових дозволів обслуговування на високому рівні - ви не хочете вирішувати послуги для кожного маленького об'єкта в грі, і, звичайно, не для кожного кадру чи нічого подібного.
Майк Стробель

2
@Thomas Dufour: концепція тесту ніколи нічого не може довести. Це просто точка даних. Ви можете пройти тестовий пропуск 100000 разів, не доводячи, що він пройде на пробігу 100001. Доказ виходить з логічного аналізу предмета. Я б заперечував, що ці контейнери IoC та подібне полегшують тестування за рахунок посилення доказування коректності, і я вважаю, що це погано.
Килотан

13
@Kylotan концепція тесту ніколи нічого не намагається довести . Він намагається продемонструвати, що поведінка із заданими входами відповідає очікуваному. Чим більше поведінка виявляється правильною, тим більше переконання, що загальна функція правильна, але вона ніколи не є 100%. Заява, що мінімальний інтерфейс доводить що-небудь, є смішним.
Даш-Том-Банг

5
@ Алекс Шерер: Боюся, я ніколи не можу прийняти, що необхідність використовувати формалізовану систему контейнерів IoC і, як правило, створювати додаткові аргументи конструктора або фабричні класи для полегшення тестування, в будь-якому випадку, робить код кращим з врахуванням, і, звичайно, не що робить його більш густим у поєднанні. Насправді він досить сильно топтає капсулювання, ключовий аспект ООП. Замість того, щоб покладатися на TDD, щоб керувати їх дизайном і сподіватися, що вийде хороший результат, люди могли просто слідувати принципам SOLID в першу чергу.
Кілотан

17

Структура стратегії , склад , введення залежностей всі дуже тісно пов'язані.

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

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

Ось стаття Міка Веста, яка розповідає про те, як він ввів цей тип системи в серію ігор Тоні Хоук від Neversoft.

Розвивайте свою ієрархію

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


2
+1, Evolve Your Iierarchy - це чудове посилання, про яке я повністю забув. Слайди Скотта Біласа теж хороші - правильне посилання на них є ( scottbilas.com/files/2002/gdc_san_jose/game_objects_slides.pdf ). Є ще один набір пов’язаних слайдів, але я забув, де ...
орендуюсь

Також стаття в «Ігри дорогоцінні камені 5» (я думаю) Б'ярне Рене.
Кріс Хоу

13

Здається, існує велика плутанина щодо структури інверсії управління (IoC). Чимало людей прирівнюють його до Стратегічної моделі або Компонентної моделі, але ці порівняння насправді не фіксують те, про що йдеться у IoC. IoC - це справді про те, як виходить залежність. Дозвольте навести приклад:

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

У вищесказаному зрозуміло, що Sprite.Loadмає залежність від a FileReader. Коли ви хочете перевірити метод, вам потрібно наступне:

  1. Файлова система на місці
  2. Тестовий файл для завантаження з файлової системи
  3. Можливість ініціювати поширені помилки файлової системи

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

Мета IoC - відключити використання поведінки від її побудови. Зверніть увагу, чим це відрізняється від структури Стратегії. Завдяки шаблону стратегії мета полягає в тому, щоб закріпити повторно використаний шматок поведінки, щоб ви могли легко поширити її в майбутньому; він не має нічого сказати про те, як будуються стратегії.

Якби ми переписали Sprite.Loadметод вище, ми, швидше за все, закінчимося:

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

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

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

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


2
Олексій: ніхто не заперечує проти передачі вже створених об’єктів, щоб задіяти спеціальні функціональні можливості там, де це потрібно. Всі роблять це, як у вашому прикладі. Проблема полягає в тому, де люди використовують цілі рамки, які існують виключно для обробки цього матеріалу, і релігійно кодують кожен аспект функціональності, щоб залежати від цієї функціональності. Вони спочатку додати IReader в якості параметра конструкції Sprite, а потім в кінцевому підсумку необхідності спеціальних об'єктів SpriteWithFileReaderFactory , щоб полегшити це, і т.д. Це ставлення дійсно відбуваються з Java і такі речі , як контейнери Spring IoC і т.д.
Kylotan

2
Але ми не говоримо про контейнери IoC - принаймні, я цього не бачу в оригінальній публікації. Ми просто говоримо про сам візерунок. Ви аргументуєте, як я найкраще можу сказати, «Оскільки деякі засоби в дикій природі погані, ми не повинні використовувати основні поняття». Це вражає мене, як викидати дитину водою з ванни. Досягнення правильного балансу між простотою, виконанням речей та ремонтопридатністю / доказовістю є важкою проблемою, яка, ймовірно, найкраще розглядається на проектній основі.
Алекс Шерер

Я підозрюю, що багато людей проти IoC, тому що це означає:
phtrivier

4

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


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

4

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

З іншого боку, інверсія управління - корисна ідея, яка існує довгий час, і дуже корисна, якщо зробити все правильно. (Не спосіб Java / Dependency Injection.) Насправді, ви, ймовірно, робите це весь час, якщо ви працюєте на здоровій мові програмування. Коли я вперше прочитав всю цю "МОК" річ, про яку всі гуділи, я був абсолютно невдоволений. Інверсія управління - це не що інше, як передача покажчика функції (або вказівника методу) на рутину чи об'єкт, щоб допомогти налаштувати його поведінку.

Це ідея, яка існувала з 1950-х років. Це в стандартній бібліотеці C (QSort приходить на розум) , і це всюди в Delphi і .NET (обробники подій / делегатів). Це дозволяє старому коду викликати новий код без необхідності перекомпілювати старий код, і він весь час використовується в ігрових двигунах.


2
Я був також «так це те , що люди схвильовані?» коли я читав про DI, але факт полягає в тому, що більшість ігрових програмістів могли стояти, щоб дізнатися про це та про те, як це стосуватиметься роботи, яку ми виконуємо.
dash-tom-bang

2

Не в моєму досвіді. Що шкода, оскільки ігровий код повинен бути дуже пристосованим, і ці підходи, безумовно, допоможуть.

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


1

Я не професійний розробник ігор, і лише один раз спробував впровадити IoC в C ++, тому це просто спекуляція.

Однак я підозрюю, що розробники ігор будуть з підозрою ставитися до IoC, оскільки це означає:

1 / проектування безлічі інтерфейсів і безлічі малих класів

2 / мають майже кожен функціональний виклик, який був нещодавно зв'язаний

Зараз це може бути збіг, але обидва, як правило, трохи складніші та / або проблемні для виступів на C ++ (який широко використовується в грі, чи не так?), Ніж на Java, де IoC набув широкого поширення (напевно тому що це було досить просто зробити, допоможіть людям спроектувати ієрархії безпечніших об'єктів, а тому, що деякі вважали, що це може перетворити додаток на Java в написання програми в XML, але це ще одна дискусія: P)

Мене цікавлять коментарі, якщо це взагалі не має сенсу;)

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