хорошо, глобальная переменная осуждается, синглтон презирается, какова альтернатива? - PullRequest
35 голосов
/ 13 декабря 2008

Для настольного приложения, которое есть. Это всего лишь общий вопрос, на который, возможно, нужны только общие ответы.

Ответы [ 9 ]

34 голосов
/ 13 декабря 2008

Статический класс со статическими членами данных? Но кого это волнует. Статические члены данных - это просто глобальные переменные с более политически корректной упаковкой.

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

Если вы используете C / C ++, я бы порекомендовал вам не иметь глобальных переменных, которые являются экземплярами классов, которые выделяют память из кучи. Они затруднят вам использование инструментов, которые проверяют утечки памяти. Объявите глобал как указатель, добавьте его в начало main (), удалите в конце.

РЕДАКТИРОВАТЬ ПОСЛЕ 6 КОММЕНТАРИЙ: Подумайте о регистрации. Разве вы не хотите иметь возможность писать строки в ваш журнал из любого места в вашем приложении? Как конкретно вы достигнете этого, не имея чего-либо видимого в глобальном масштабе для ведения этой регистрации? Если вы хотите что-то глобально видимое, тогда сделайте это глобально видимым.

14 голосов
/ 13 декабря 2008

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

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

typedef struct Pnmrdr_T *Pnmrdr_T;

struct Pnmrdr_T *Pnmrdr_new(FILE *);
pixel Pnmrdr_get(Pnmrdr_T);
void Pnmrdr_close(Pnmrdr_T);
void Pnmrdr_free(Pnmrdr_T *rp); // frees memory and sets *rp = NULL

Этот стиль программирования очень похож на методы ОО.

Почему лучше, чем глобальные переменные? Сюрпризов нет . Если что-то идет не так или вы хотите добавить функцию, вы знаете, что все явно указано в передаваемых значениях. Более того, вы знаете, что вы можете подключить множество модулей вместе, и они не будут мешать, если вы явно не передадите состояние между ними. Мой контакт в бизнесе по мобильному телефону говорит, что это свойство имело огромное значение для его компании - они являются программным обеспечением OEM-производителя и могут легко объединять разные компоненты для разных клиентов.

Мне действительно нравится программировать таким образом, потому что я вижу все, что происходит, и мои частные структуры данных защищены от посторонних глаз: -)

8 голосов
/ 13 декабря 2008

Во-первых, нет смысла притворяться, что синглы как-то лучше или более приемлемы, чем глобальные. Синглтон - это просто глобальный наряд, похожий на ООП. С кучей других проблем.

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

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

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

3 голосов
/ 13 декабря 2008

Мне все равно, не рекомендуются ли одноэлементные или глобальные переменные. Если я чувствую, что это самый логичный способ его реализации, тогда я воспользуюсь им.

2 голосов
/ 13 декабря 2008

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

1 голос
/ 13 декабря 2008

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

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

0 голосов
/ 23 февраля 2016

после использования глобалов и синглетонов и наблюдения за тем, как все запуталось, я пришел к этому решению.

  1. делает каждую глобальную переменную членом класса. Логически каждая глобальная переменная принадлежит приложению (или системе). просто создайте класс приложения. определить глобальные объекты как свойства. поэтому они создаются при первом вызове.

  2. создать синглтон для класса приложения, чтобы вы могли обращаться к нему глобально. Это будет единственный синглтон в вашем коде. ну, в конце это похоже на объекты system.out или system.in в java.

примечание: я знаю, что это очень старый вопрос, но все еще популярный.

0 голосов
/ 13 декабря 2008

глобальные переменные хороши в небольших программах, но когда они становятся больше, вы начинаете получать странные побочные эффекты, когда кто-то вносит изменения или исправляет ошибку, говоря: «О, я просто установлю это глобально, и проблема исчезнет»

0 голосов
/ 13 декабря 2008

Распространенным решением для этого является использование классов с одним экземпляром вместо одноэлементных / глобальных переменных.

Ваше приложение будет отвечать за то, чтобы у вас был только один экземпляр.

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

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

...