Игорь З.
29 повідомлень
#14 років тому
Известно, что использование глобальных переменных не рекомендуется. Основная причина - т.к. любая функция может изменить их значение. В связи с этим вопрос - как лучше организовать хранение глобальных значений? Т.е. это те переменные, значения которых требуются всей программе в разных частях.

Вариант 1 (как я сделал сейчас):


template<class T>
class Global
{
public:
void set(const T value);
T get() const;

private:
T value_;
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
template<class T>
void Global<T>::set(const T value)
{
value_ = value;
}

template<class T>
T Global<T>::get() const
{
return value_;
}


Тогда использование глобальной переменной будет выглядеть как


Global<string> myString;
myString.set("text of my string");
myString.get();


Оптимальный ли это вариант? Из минусов здесь вижу тот факт, что дальше всюду при использовании потребуется указывать get(), ну и то, что значения по умолчанию не будут прописаны в самом классе, а могут быть разбросаны по всей программе и при необходимости их придется искать.
Может лучше все глобальные переменные просто объявить в отдельном пространстве имен и дальше работать с ними как с обычными? Или определить их как статические переменные одного класса, а не как экземпляры класса?
И еще, как лучше задавать глобальные константы - по идее, их, наверное, можно как обычно, сразу в main, т.к. константы уже никто изменить не сможет. Либо определить все в отдельном .h файле.

Посоветуйте, кто как работает с глобальными переменными.
Владимир А.
246 повідомлень
#14 років тому
Вообще стоит почитать о паттернах проектирования, в частности, Вам поможет такой паттерн как синглтон.
Игорь З.
29 повідомлень
#14 років тому
Посмотрел про синглтоны, действительно полезная вещь. Но поиск также выдаёт, что следует избегать и их использования. Правда пока что вся информация про то, что следует избегать синглтонов, которую нашел, была на английском, и как-то без толковых объяснений. В итоге так толком и не понял, почему же нужно и их избегать и что тогда использовать...
Игорь З.
29 повідомлень
#14 років тому
Выяснил про синглтоны следующие их недостатки:

1. Класс синглтона, помимо своих прямых обязанностей должен еще и контролировать свои экземпляры (нарушение принципа Single Responsibility Principle).
2. При доступе к синглтону мы не знаем текущее состояние класса, кто и когда его менял, т.е. его состояние может оказаться совсем не таким, как мы ожидаем.

Остаётся открытым вопрос - что тогда использовать вместо синглтонов.
Сергей Р.
2 повідомлення
#14 років тому
Варианта всего 2, либо таскать за собой структуру в которой будут все общеиспользуемые переменные, либо использовать глобальные переменные в том или ином виде.
Синглетон - это те же самые глобальные переменные, только в случае синглетона можно в явном виде оформить "протокол" взаимодействия остальной части программы с этими переменными.

Насчет того что не стоит использовать синглетоны - тезис скорее о том что если есть возможность использовать молоток то не зачем микроскопом забивать гвозди.
Роман Беляев
16382 повідомлення
#14 років тому
Синглтон в данном случае будет тоже самое что и глобальные переменные, только в красивой обертке - какой смысл?
Что у вас в тех переменных вообще? Может быть стоит как-то изменить подход к тому что вы там храните, а не к способу хранения?
Александр В.
58 повідомлень
#14 років тому
Ну для исходной задачи ТС, лучше вместо синглтона задействовать паттерн Реестр (Registry) - он тут более уместен чем одиночка. А вообще согласен с frig, возможно можно пересмотреть архитектуру так, чтобы глобальные переменные не были нужны вовсе....
Но в то же время паттерн Реестр нормальное решение проблемы - довольно часто без него не обойтись...
Игорь З.
29 повідомлень
#14 років тому
В переменных хранится ряд конфигурационных данных, например, пути к специфическим (в т.ч. конфигурационным) файлам, или булевы значения, определяющие поведение программы. Эти значения все установлены по умолчанию, но также и могут быть изменены при запуске программы из командной строки как параметры. Ну и соответственно, они используются многими логически никак не связанными модулями программы. Т.е. изменить подход к хранению - пока что не совсем понятно как, тем более хотелось бы весь этот набор держать вместе, чтобы не искать по всем .cpp или .h файлам, вспоминая, в каком из них какая переменная задана.

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

Так что сдаётся мне, что пространство имен - самое оптимальное решение...
Роман Беляев
16382 повідомлення
#14 років тому
Цитата ("tri777ki"):
В переменных хранится ряд конфигурационных данных, например, пути к специфическим (в т.ч. конфигурационным) файлам


Ну так заведите класс для конфига и получайте из него значения. Устанавливать их извне вообще под большим вопросом - рядовым классам делать это вовсе не обязательно. Пускай будет реестр несколько видоизмененный. Если это именно конфиг, то писать в него каждому давать нельзя - именно так можно отойти от глобальности.
Игорь З.
29 повідомлень
#14 років тому
frig,
а может и верно. И дать доступ на запись в этот класс только тому, кому это действительно нужно. Пожалуй так и попробую.
Сергей Р.
2 повідомлення
#14 років тому
А про синхронизацию при Multithreading не забываем?
Николай М.
1895 повідомлень
#14 років тому
Я пишу на делфи, но делаю примерно так: создаю класс TSettingsConfig, с полями всех настроек, при том что использую потокобезопасные наследники, проблем не возникало