Я читал много блогов и постов в stack exchange о том, что глобальное состояние (обычно) является плохой практикой. Сейчас я стараюсь по возможности избегать этого в своем коде, но я столкнулся со случаем, когда я не знаю, как избежать глобального состояния:
Предположим, у меня есть задача, которая обрабатывает события. Если я хочу подсчитать количество событий, которые она обрабатывает, и хочу, чтобы этот счетчик был доступен для отображения через какой-нибудь отладочный канал, как я могу реализовать этот счетчик без использования глобального состояния?
(В моем конкретном случае используются задачи vxWorks).
Существуют различные аспекты, по которым глобальное состояние может быть проблематичным.
Если вас беспокоит связанность, тестируемость и потоки данных, вы можете переместить глобальное состояние в аргумент. Итак, вместо:
State s;
void some_function(void) { ... }
int main() {
some_function();
}
Ты можешь иметь:
void some_function(State* s) { ... }
int main() {
State s;
some_function(&s);
}
Если вас беспокоят проблемы параллелизма, возникающие при использовании общего состояния (а не только глобального состояния), то использование атомарных значений для счетчика может быть уместным.
В моем конкретном случае используются задачи vxWorks.
Это потенциально меняет дело.
Многие передовые методы разработки программного обеспечения нацелены на большие системы, в которых вы управляете только отдельными компонентами, а не целым приложением или системой, и где часто разумно пожертвовать некоторой степенью производительности для лучшего выбора дизайна (например, с использованием методов ООП для разделения компонентов).
Но такие передовые методы и методы часто неприменимы во встроенном контексте. Ранее предложенный метод перемещения состояния в аргумент функции отлично подходит, если вы хотите поддерживать несколько состояний, например, несколько экземпляров некоторого приложения. Это часто не вызывает беспокойства во встроенном контексте. Использование глобальных переменных также вполне уместно для встроенного кода, если они описывают состояние устройства, потому что это наиболее точное отражение реальности.
Лично я, если позволяют ресурсы целевой платформы, все же склоняюсь к «более чистому» дизайну, избегая глобального состояния. Я бы попытался разработать функции, отвечающие за сбор и агрегирование этих данных мониторинга/отладки/наблюдаемости, и передавать необходимые данные в качестве аргумента. Это также позволит вам переключать сбор диагностических данных во время выполнения. Однако, если это вызывает проблемы — или просто если отслеживание этих дополнительных параметров в вашей кодовой базе более раздражает, чем проблемы, связанные с глобальным состоянием — тогда я бы с радостью использовал вместо этого глобальные переменные.