Могу ли я использовать глобальную переменную в этом сценарии?

После прочтения некоторых SO-тем по этой теме: я пришел к выводу о причинах плохих глобальных переменных / синглетонов.

  1. Становится все труднее понять функции: глобальное состояние, по мере роста кода все больше и больше функций будут изменять это глобальное состояние.
  2. Это затрудняет юнит-тестирование.
  3. Это скрывает зависимости.
  4. Вам придется переписать код, если когда-нибудь окажется, что ваша глобальная переменная на самом деле не является единичным объектом / переменной.

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

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

Что если я на 100% уверен, что в моем приложении будет только одна карта высот? Кроме того, поскольку это небольшой сольный проект, я верю, что смогу понять, что каждая функция делает с глобальным состоянием? И я не вижу, как использование глобальной переменной в этом случае вредит модульному тестированию. Если я хочу использовать макет карты высот, я не могу просто сделать globalHeightmap = generateMockHeightmap(); перед вызовом функции, которую я хочу проверить?

1 ответ

Решение

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

Простое переопределение глобальной карты состояний для вашего модульного теста кажется хрупким. Что делать, если вам нужно восстановить старое состояние или изменить состояние в тесте? Затем вы получите кучу кода сохранения / установки / восстановления.

Что, если вы когда-нибудь захотите добавить модель потоков в свое приложение? Использование глобального состояния сделает этот переход намного более сложным.

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

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

Другие вопросы по тегам