Если классы «ResourceManager» считаются плохими, каковы альтернативы?


19

Я слышу противоречивые мнения, такие как:

  • «Классы выделенного менеджера почти никогда не являются правильным инженерным инструментом»
  • «Классы Dedicated Manager (в настоящее время) - лучший способ выжить в большом проекте с тысячами ресурсов»

Давайте возьмем классический класс ResourceManager, который имеет следующие функциональные возможности:

  • Загружает ресурсы (текстуры, аудио, 3D-модели и т. Д.)
  • Обеспечивает загрузку ресурсов только один раз, сохраняя кеш
  • Ссылка подсчитывает активы, чтобы определить, могут ли они быть освобождены
  • Скрывает, откуда взяты фактические активы (например, это может быть один файл на актив, или все активы в одном файле пакета, или активы могут быть даже загружены по сети)
  • Можно перезагрузить ресурсы без перезапуска программы, что крайне полезно для художников, работающих над игрой.

Давайте также уберем аргумент «синглетоны - это плохо» , притворившись, что эти объекты ResourceManager не являются синглетонами, а вместо этого передаются через внедрение зависимостей .

Затем есть аргумент «использовать фабрику» или «назвать фабрику». Моя проблема с этим заключается в том, что да, это фабрика, но это также кеш и перегрузчик (из-за отсутствия лучшего слова). Называть это фабрикой не описывает это должным образом, и если я сделаю ее правильной фабрикой, то где же будет реализовано кэширование и перезагрузка?

Я согласен с тем, что классы «Менеджер» часто являются признаком плохой архитектуры, но в данном конкретном случае, как она может быть реструктурирована и при этом сохранить все функциональные возможности ? Это ситуация, когда класс «Менеджер» действительно уместен?


3
Может быть, назвать это складом вместо завода? : P
замедленная

Ответы:


9

Я думаю, что проблема не в том, что это плохой дизайн. Проблема в том, что имя «Диспетчер» не имеет значения, например «Обновление», «Процесс» и «Актер». Это не помогает кому-то, пытающемуся понять эту систему, и это создает путаницу, если у вас когда-либо есть другие классы, которые выполняют некоторую операцию с активами.

Тем не менее, назвать вещи так, чтобы они эффективно отражали их цель, действительно очень сложно . Большинство систем слишком сложны, чтобы их можно было назвать по имени. Лучшее, что вы можете сделать, - это попытаться определить, какая конкретная идея делает этот класс связным, а какие другие классы должны явно отличаться, и выбрать уникальное слово, которое подходит.

ИМХО, самая важная особенность хорошего имени в том, что оно уникально в том контексте, что люди увидят его (основа кода), и его легко запомнить. Тест должен состоять в том, чтобы вы могли поговорить со своими товарищами по команде, которые знакомы с кодом, без необходимости уточнения того, на что вы ссылаетесь. Это также поможет, если вам когда-нибудь понадобится написать справочную документацию.

Наконец, учтите, что если вы не можете описать эту связную идею, она может быть не очень связной. Например, вы можете разделить подсчет кэширования и ссылок в AssetCache и сохранить загрузку в AssetLoader. Но это действительно зависит от того, насколько сложен и запутан код.

Но если ваш AssetManager достаточно сплоченный, и ничто другое в вашей игре не является AssetManagery, тогда это может быть вполне подходящее имя.


Разделение AssetLoader / AssetCache - неплохая идея.
Том Даллинг

4

"Я делаю это в одном месте, или я делаю это много?"

Логика загрузки обычно централизована для одной точки доступа, потому что она, как правило, запускается только в ключевых точках приложения, где мы пытаемся убрать ее как можно скорее. Это обычно происходит при запуске приложения, на уровне игры или когда мировая позиция игрока требует загрузки нового чанка, чтобы сохранить взаимодействие без проблем. Учитывая, что это делается как пакетный процесс (будь то один массивный блок или несколько меньших по размеру, на самом деле не имеет значения), имеет смысл иметь один метод или набор методов для вызова, чтобы запустить этот процесс.

На большинстве платформ загрузка выполняется асинхронно, поэтому у вас практически нет другого выбора, кроме как разделить потоки кода для загрузки и разделить другую логику приложения, что является еще одной причиной абстрагирования функций управления ресурсами в их собственный класс.

Наконец, несколько моментов для размышления:

Загрузка ресурсов выполняется не очень часто по сравнению, например, с. игровая логика, так стоит ли усложнять ваши отдельные игровые объекты, чтобы сделать это? Игровые объекты, как правило, максимально освещены и предназначены только для того, что необходимо во время симуляции.

Должен ли объект нести ответственность за свое собственное создание и уничтожение? Это может вызвать серьезные головные боли во время управления сущностью. Если вы ожидаете, что объект выполнит свой собственный процесс создания (включая получение зависимостей от ресурсов), то он также будет нести ответственность за его уничтожение. Это может вызвать висячие / нулевые указатели, так что на самом деле им нужно управлять извне. Посмотрите этот ответ, описывающий эту проблему более подробно.


PS Помимо обычных аргументов типа «Синглтоны - это ужасно» (которые ужасно догматичны), вы когда-нибудь видели хороший аргумент против ResourceManager? «Классы выделенного менеджера почти никогда не являются подходящим инженерным инструментом» - это совершенно не аргумент для этого конкретного случая .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.