LINUX.ORG.RU
Ответ на: комментарий от Manhunt

Например, ты можешь захотеть скормить разным подсистемам разные экземпляры лог-стрима

Им скармливаются «категории», которые кормят сообщениями общий логгер. Можно как раскидать по отдельным файлам... так и не раскидывать. То же мне, бином Ньютона.

Построй свою программу вокруг логгера-синглтона, и этой возможности ты лишишься.

По факту, оч. спорное утверждение.

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 1)
Ответ на: комментарий от Manhunt

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

А если мне такая возможность и нахрен не нужна? Мне просто нужен простой лог который умеет переключаться между выводом в файл и в терминал. Накой черт мне твой огород городить?

Ты упоролся что ли?

Мне в каждом модуле предлагаешь считывать/парсить/кэшировать/автоматически бекапить настройки программы? Или в каждый класс передавать экземпляр объекта Settings?

И еще, есть вот у меня БД с кэшем в RAM. Кэш для клиентов общий и единственно существующий - почему мне не вытащить его в Singleton?

NegatiV
()
Ответ на: комментарий от UVV

Ok, ну так чё советуешь в итоге? Убрать синглтон и параметром во все объекты передавать?

Синглтон у тебя притянут за уши. Ты сам этого разве еще не осознал?

Экземпляр хоста/сессии — да, явным образом передать всем, кто этими экземплярами должен пользоваться.

Manhunt ★★★★★
()
Ответ на: комментарий от slackwarrior

Им скармливаются «категории»

Ну так если у тебя весь код явно обращается к синглотну, то категория будет только одна, как ни крутись.

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

Ну так если у тебя весь код явно обращается к синглотну, то категория будет только одна, как ни крутись.

Logger::get()->warn("core", "core category"); // категория core
Logger::get()->warn("common category"); // категория common
NegatiV
()
Ответ на: комментарий от NegatiV

Мне просто нужен простой лог который умеет переключаться между выводом в файл и в терминал. Накой черт мне твой огород городить?

Я ж говорю, что с решение с логгером-синглтоном — спорное, а не непригодное.

Мне в каждом модуле предлагаешь считывать/парсить/кэшировать/автоматически бекапить настройки программы?

Модуль должен получать предназначенные для него настройки в готовом виде. Парсить/кэшировать/бэкапить — не его компетенция.

Или в каждый класс передавать экземпляр объекта Settings?

Да. В конструктор и (если надо) в OnSettingsChanged().

И еще, есть вот у меня БД с кэшем в RAM. Кэш для клиентов общий и единственно существующий - почему мне не вытащить его в Singleton?

Потому что каждый клиент должен работать со своим торчком от «бд». Тот факт, что торчок под капотом проверяет общий RAM-кэш и лезет в общую БД --- лежит вне компетенции клиентов. Сегодня логика кэширования и работы с БД одна, а завтра по каким-то причинам может стать совсем другая. Может быть принято решение разным клиентам разный объем RAM каким-то образом предоставлять, разное время жизни кэшированных объектов в RAM сделать, и тому подобное. Чем меньше клиенты обо всей этой кухне знают, тем легче будет внести изменения.

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 2)
Ответ на: комментарий от Manhunt

Модуль должен получать предназначенные для него настройки в готовом виде. Парчить/кэшировать/бэкапить — не его компетенция.

Правильно, это все может быть скрыто под капотом у Settings::get()->init()/Settings::get()->value(...)/Settings::get()->save()(по таймеру, например)

Потому что каждый клиент должен работать со своим торчком от «бд». Тот факт, что торчок под капотом проверяет общий RAM-кэш и лезет в общую БД --- лежит вне компетенции клиентов.

Клиенты и не лезут в кэш напрямую, к нему лезет БД (которая разбита на кучу бэкэндов с общим кэшем).

NegatiV
()
Ответ на: комментарий от Manhunt

Не-а, весь и явно не обращается. Что стоит за «категориями» коду нихрена неизвестно :) Может, отдельные логгеры :) Может RAII обертки, flushающиеся при выходе из блока. Много вариантов.

категория будет только одна, как ни крутись.

«Категория» - это абстракция. Так же как «severity». В файле лога текст букв слов в специальном формате или «набор каких-то байт»? Смотря чем откроешь :) Может там поток хеш-кодов, на которые натравливается специально обученный splunk и раздает всем сестрам по категориям. «Вот тут блондинка в красном! А тут агенты матрицы» :)

slackwarrior ★★★★★
()
Ответ на: комментарий от Manhunt

Поддерживаю этого товарища.

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

nanoolinux ★★★★
()
Ответ на: комментарий от Manhunt

Ну тут зависит от сложности системы, кстати.
В небольшой программке, имхо, синглтон-логгера будет достаточно. В другом проекте у нас класс логгера висит как private inherited, и ему скармливается имя класса в конструкторе.

UVV ★★★★★
() автор топика
Ответ на: комментарий от Manhunt

Это тебе нужно руками поправить каждое обращение к логгеру, в котором ты захотел изменить категорию.

Logger::get()->warn(THIS_MODULE_CATEGORY, "msg");

Не?

NegatiV
()
Ответ на: комментарий от nanoolinux

Эк ты скрестил singleton и static variable... Про static поддерживаю, кстати. Тоже имел секас с log функцией, буфер в которой был объявлен как static char*. Забавно работала в несколько потоков.

UVV ★★★★★
() автор топика
Ответ на: комментарий от NegatiV

Клиенты и не лезут в кэш напрямую, к нему лезет БД (которая разбита на кучу бэкэндов с общим кэшем).

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

Правильно, это все может быть скрыто под капотом у Settings::get()->init()/Settings::get()->value(...)/Settings::get()->save()(по таймеру, например)

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

Manhunt ★★★★★
()
Ответ на: комментарий от NegatiV

Logger::get()->warn(THIS_MODULE_CATEGORY, «msg»);

Не?

Как насчет

this_logger->warn(«msg»);
?

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от NegatiV

Мне в каждом модуле предлагаешь считывать/парсить/кэшировать/автоматически бекапить настройки программы? Или в каждый класс передавать экземпляр объекта Settings?

Некоторые так и делают... Каждый модуль парсит свои настройки. И не классами, а свободными функциями - по параметру за раз (в упоротых случаях - посимвольно, в огромном цикле со свичом на шесть экранов) :) «Ой, неудобно как-то, тормозно, пока проще по файлам раскидать». «Ой, простыня... несопровождабельно!» Потом им приходит на ум менеджер или заказчик с отличной идеей «ннада возможность свести пачку конфигов в один файл!111адин» (который обнажит недостатки простых решений, если конфиг достаточно объемный). Или «сделать что-то типа инклюдов» (которые тот же один файл, вид сбоку...). «Да. И чтоб конфиг с фтп вытягивался, а редактировался локальной утилитой!» (смотрим в кот и фрустрируем... «каждый модуль вытягивает свои настройки по фтп? Да ну нах...» Хотя видал коммерч. проекты и с подобными решениями - система деплоя как Мюнгхаузен вытягивает с фтп конфиг, дальше тащит модули, которые тащат свои зависимости со своими конфигами... (ниче не напоминает?) Один тимлид наваял себе такую билдсистему - чтоб значит, все глобально и надежно... Искаропки само скачалось, настроилось, сконпелялось... Только первые же пионеры, которые это сопровождали - все сломали и сделали cmake-простыню с вручную настраиваемыми переменными окружения и «USE-флагами»)

slackwarrior ★★★★★
()
Ответ на: комментарий от Manhunt

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

«Дайка мне такой же, но с крыльями» (с) Фабрика звонит дежурному декоратору/врапперу/приспособленцу/прокси/хрену с бугра - и дальше код имеет дело с ним, а лезет он в синглтон (considered harmful & deprecated) или делает умный вид (> /dev/null)- кого это колыхает?

повсеместно явным бразом

с какого потолка ты это взял - умонепостигаемо.

slackwarrior ★★★★★
()
Ответ на: комментарий от slackwarrior

повсеместно явным бразом

с какого потолка ты это взял - умонепостигаемо.

А в противном случае синглтон и вовсе лишен смыла.

Manhunt ★★★★★
()
Ответ на: комментарий от slackwarrior

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

Синглтон — один, а экземплятров которые нужно в него запихнуть — два. Кто из пользователей синглтона к какому из этих двух экземпляров должен начать обращаться? :D

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

А зачем тебе два экземпляра одного синглтона? :) Это только при косяке в инициализации статически вкомпиленных рантаймов в экзек и в динамик либу такая хрень происходит (так можно раве что по нубизму сделать и удивляться). «Покупайте наших слонов!» Легким движением параметров в темлпейте брюки превраща... Больше синглтонов, хороших и разных :) Лежат отдельно, друг другу никак не мешают... От слова вообще. Синглтонами для своих нужд они при этом быть не перестают. (Счетчики всякие и всего так например на ура создаются. Разобраться инстансам, кто из-них «Ъ-синглтон», а кто дурилка картонная (решением пленума партии) - тоже никакая не проблема)

Синглтон — один, а экземплятров которые нужно в него запихнуть — два.

Это просто узкий, надуманный, высосанный из пальца взгляд на проблему :) Может нужно кому-то... А может и нет. Экземпляров два? А может, их... «по-одному». И нехрен смешивать. «Эта половинка таблетки от головы, эта от живота... Смотри не перепутай!»

slackwarrior ★★★★★
()
Ответ на: комментарий от Manhunt

А в противном случае синглтон и вовсе лишен смыла.

Я тебе уже говорил про «абстракцию» и смыслы? Смыслами наделяет кто-то. Они не «имманентно присущи».

slackwarrior ★★★★★
()
Ответ на: комментарий от Manhunt

У тебя в предметной области помойки и кладбища предусмотрены?

регулярно их вижу, называются *Util/*Helper, всех их делают

значит сделать такую помойку и потом справляться с последствиями удобней, чем постоянно нагружать мозг ооп итп

stevejobs ★★★★☆
()
Ответ на: комментарий от Manhunt

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

Вот тут поподробнее. Конфигурация программы, имхо, должна лежать строго в одном месте: на диске, в БД и всем компонентам должен предоставляться унифицированный доступ к настройкам. Если один модуль сует настройки в файл в $HOME/.appname/app.config, а другой - в БД, то это повод дать программисту по рукам.

NegatiV
()
Ответ на: комментарий от maloi

А завтра ты захочешь в программе не только солнечную систему, а ещё и систему какого-нибудь сириуса.

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

вот тебе бритва стивджобса - не плоди сущности без предоплаты

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

В некоторых языках singleton - вещь вполне себе обыкновенная и повсеместно используемая и никто ни о каких антипаттернах не кричит.

NegatiV
()
Ответ на: комментарий от stevejobs

регулярно их вижу, называются *Util/*Helper, всех их делают

Только они не синглтоны, а наборы статичных функций обычно.

UVV ★★★★★
() автор топика
Ответ на: комментарий от slackwarrior

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

NegatiV
()
Последнее исправление: NegatiV (всего исправлений: 1)
Ответ на: комментарий от iVS

Как будто в солнечной системе ты этой проблемы можешь избежать

maloi ★★★★★
()
Ответ на: комментарий от UVV

А что, есть доказательства, что там как-то по-другому работает физика?

maloi ★★★★★
()
Ответ на: комментарий от Manhunt

по делу можешь сказать что-нибудь?

Говори по делу и будешь получать ответы по делу

Найди десять различий между синглтоном и энумом с одним значением.

maloi ★★★★★
()
Ответ на: комментарий от stevejobs

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

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

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

maloi ★★★★★
()
Ответ на: комментарий от Manhunt

Чем меньше разные части программы знают друг о друге, тем программа проще.

Нет, если вместо Солнца возможно что-то еще, нужно заводить доп. параметр planet => Sun, что есть лишняя сущность.

Такой класс будет гораздо проще будет переиспользовать, потому что его можно «как есть» разместить в абсолютно непохожем окружении, и он попросту не заметит никаких изменений.

Только при этом нужно быть уверенным, что он работает в другом окружении.

Такой код легче юнит-тестировать, потому что в него можно просто передать тестовую версию солнца, не хакая глобальное окружение.

В том-то и дело, что вы зачем-то хотите другое окружение («а что, если вместо Солнца будет Луна?»), но при этом вводите юнит-тесты, чтобы убедиться, что паттерн корректно работает в другом окружении. Тесты ради тестов, ага.

iVS ★★★★★
()
Ответ на: комментарий от maloi

Проблема с синглтоном не нем самом по себе, а в том, что джуниоры, прочитав книжку по паттернам, начинают их лепить где попало.

Вот именно!
Разруха не в клозетах, а в головах. © Преображенский

iVS ★★★★★
()
Ответ на: комментарий от NegatiV

Конфигурация программы, имхо, должна лежать строго в одном месте: на диске

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

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 2)
Ответ на: комментарий от iVS

при этом вводите юнит-тесты, чтобы убедиться, что паттерн корректно работает в другом окружении.

Юнит-тесты вводят для того, чтобы убедиться, что код корректно работает. То, что проверяют его в синтетическом окружении — это вторично и самоцелью не является. С другой стороны, если объект нельзя запустить в синтетическом окружении, это почти всегда говорит о дерьмовенькой архитектуре. Проблемы у этой архитектуры будут не только с юнит-тестами, но и с развитием функциональности программы по мере поступления новых неожиданных бизнес-требований.

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от Manhunt

Файл-то один, а вот по-разному настроенных объектов одного и того же класса может быть несколько.

void MyObject::load() {
   auto SM = Settings::get();
   auto state = SM->has_value("my_object", this->id())? SM->value("my_object", this->id()) : SM->value("my_object", "common");

   ....
}

void MyObject::save() {
   Settings::get()->store("my_object", this->id(), this->state());
}

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

NegatiV
()
Ответ на: комментарий от Manhunt

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

Или о том что состояние объекта зависит от внешнего окружения.

NegatiV
()
Ответ на: комментарий от iVS

«Лишняя сущность» это сам синглетон. Делаешь нормальный класс и создаёшь объект. Один. Вот и всё. Зато потом, когда у тебя вдруг появятся другие хотелки не пришлось на ушах стоять от того, что уже написано.

anonymous
()
Ответ на: комментарий от Manhunt

по мере поступления новых неожиданных бизнес-требований

В том, что нет четкого ТЗ, виноват паттерн?

iVS ★★★★★
()
Ответ на: комментарий от NegatiV

Сторадж должен попадать в методы load() и store() не через синглтон, а через агрумент. Примерно так, как сделано в boost::serialization.

Manhunt ★★★★★
()
Ответ на: комментарий от iVS

В том, что нет четкого ТЗ, виноват паттерн?

Ты, видимо, путаешь «четкость» и «неизменность». То, что ТЗ меняется прямо во время разработки программы — это рыночная необходимость.

Manhunt ★★★★★
()
Ответ на: комментарий от anonymous

Зато потом, когда у тебя вдруг появятся другие хотелки не пришлось на ушах стоять от того, что уже написано.

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

iVS ★★★★★
()
Ответ на: комментарий от anonymous
class ISettings {

};

class Settings: public ISettings, public Singleton<Settings> {

};

class IHaveSettings {
public:
    IHaveSettings(const std::string &category, const std::string &id);
    ...
    virtual ISettings *settings() { return Settings::get(); }
};

class MyObject: protected IHaveSettings {
public:
    MyObject(): IHaveSettings("my_object", "") {}
    virtual ISettings *settings() { return my_fucking_settings; }
};

Или ты думал что синглтонами пользуются напрямую?

NegatiV
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.