LINUX.ORG.RU

Синглтоны

 ,


1

5

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

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

И вот мне тут для картины мира одного штриха не хватает. Поправьте, если что.

Прав ли я, что основная претензия к синглтону не в том, что он есть, и не в том, что он такой обычно один на все приложение, а в том, что каждый другой объект, которому этот синглтон нужен, магически знает, как этот синглтон называется в глобальном пространстве имен? И чтобы не попадать в категорию «фу быть таким», достаточно передавать этот синглтон параметром всем, кому он полагается для работы (а как он создается на самом-самом верхнем уровне, даже если это типичное foo = MySingleton.getInstance(), никому не интересно)?


P.S. Я точно знаю, что есть хуже синглтона: глобальное состояние, размазанное по пердиллиону модулей. По-моему, это даже хуже goto.

Перемещено mono из talks

★★★★★

Последнее исправление: shimon (всего исправлений: 1)

Других претензий быть не может, поскольку если удовлетворить указанную, становится внезапно пофиг на то, static Foo instance; там или Foo* instance = new Foo; (если выражаться на плюсах). ИМХО.

Это был сеанс телепатии и попытки применения логики. Лично я синглтоны использую.

intelfx ★★★★★
()

Да, твои догадки в точности верны.

Вброс: состояние нужно хранить в аргументах рекурсивной фии. Но к сожалению мейнстрим он совсем другой, да.

nanoolinux ★★★★
()

где-то же должна программа в общем случае держать свое состояние

в монаде, само собой. чай не средневековье на дворе

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

Например, по нескольким синглтонам. %)

Можно представить архитектуру, где за каждую «ветвь» функционала программы отвечает некий модуль, который синтаксически реализован как класс-синглтон. Спрашивается, почему бы и нет.
KDevelop такую имеет — и вроде бы ничего, изнутри всё выглядит вполне удобно и красиво. ICore::self()->documentController()->какой_нибудь_openFile()

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)

Не знаю как вам, а мне синглтоны нужны бывают только разве что для логов. Для всего остального - как-то легко обхожусь и без них ;)

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

Например, по нескольким синглтонам. %)

Ага, причем одного класса %)

ICore::self()->documentController()->какой_нибудь_openFile()

Ну, если в данном случае DocumentController «хранит состояние программы», окей. Но протаскивать его в разные части программы через, скажем, параметры функции - так себе идея.

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

Да ХЗ, лично мне это не кажется логичным - состояние программы обычно размазано по многим объектам.

А ты не пробовал ВСЁ состояние программы засунуть в один объект-синглтон? И показательно иметь всю остальную программу stateless? Такой себе сферический MVC. Очень интересно получается, между прочим.

Pavval ★★★★★
()

претензии к синглтонам унаследованны от претензий к модулям(в языках в которых модули были_реальне) т.е синглтон(и не важно переменая это или тип (у которого уникальная и единственная переменная)) это глобальное общее имя.

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

Тезис S: дизайн программы должен исходит из того , что не существуют типов с единственой переменной.

Тезис S - догма , хош принимаеш , хош ведать о нём не ведаеш.

qulinxao ★★☆
()

это которые на олимпиаде с горки катаются?

feofil
()

Тут две взаимосвязанных проблемы.

1 - сильное связывание. В модульном программировании считается плохим тоном сильное связывание. При изменении требований и переделывании одной части неизбежно затрагивается вторая.

2 - сложность тестирования. Это уже зависит от языка, но обычно глобальные переменные подменять для теста сложно и неудобно. Простой пример - у нас есть алгоритм, в котором прописан System.currentTimeInMillis(). Ну и как его подменять? Не, можно, если сильно захотеть, но это такой гемор.

Решений второй проблеме я знаю два.

1 решение это репозиторий. При этом у нас таки есть одна глобальная переменная, Map<String, Object>. В нём хранятся все остальные синглтоны.

2 решение это dependency injection. В самом начале (или во фреймворке) создаётся один объект и он через setter вставляется в нужные объекты. Зачастую во фреймворке он скомбинирован с первым решением, т.е. у фреймворка есть внутри репозиторий созданных объектов и он может его отдать, если попросить, либо попросить его вставить все зависимости в указанный объект, он этот объект исследует, найдет все зависимости и передаст ему.

Более популярно второе решение. Без фреймворка там получается много писанины, поэтому «на коленке» лучше делать первый вариант. А если на тестирование пофиг и код на выброс, то никаких проблем использовать синглтоны нет.

Соответственно решение первой проблемы это ввод промежуточного интерфейса между модулями. Но это усложняет программу и не всегда оправдано.

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

хранит состояние программы

Ну блин. Любой объект в некотором смысле «хранит состояние программы» (а что ж он ещё-то делает?).

Состояние бывает короткоживущее (внутри worker-тредов и т. д.), а бывает долгоживущее, которое сохраняется между итерациями цикла обработки событий или его аналога. Соответственно, объект, который его хранит, должен быть создан вне цикла сообщений.

Внезапно, это и есть global scope, и мы получаем синглтон или почти синглтон. И это совершенно оправданно, если в программе не может быть больше одного цикла обработки событий.

intelfx ★★★★★
()

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

Кажется, еще чуть-чуть и ты изобретешь монады.

Алсо, по заголовку и тегам думал, что автор — qulinxao или anonimous.

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

Это называется «автомат» (который state machine).

intelfx ★★★★★
()

Синглтон не плох, можешь официально обьявлять негодяями всех кто говорит что это антипаттерн. Плоха его реализация, в которой его нельзя простым способом заменить в тестах или нельзя одновременно инстанциировать два логических инстанса приложения в одном процессе, например голый статический getInstance. Хороший способ - singleton scope в IoC контейнере

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

Не тру, в заменяемых лямбдах-стратегиях обработки следующего сообщения актором

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

не не не .

тут вопрос же про уровень[абстракции] контекста.

в контексте некоторого исполнителя такой то тип(переменая этого типа) должна быть синглтоном ибо ...

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

ясно же?

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

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

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

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

ясно же?

Абсолютно ясно только то, что это НЕ синглтон.

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

А когда у тебя «передаёт ей в качестве аргумента окружение» - это, извините меня, не синглтон. Это нормальная архитектура.

Резюмируя: синглтон - это такой баззворд, который ничего не обозначает. Когда мы заменяем глобальное состояние на «синглтоны», мы занимаемся бесполезными синтаксическими упражнениями. Когда же мы заменяем синглтоны на «аргументы окружения», то всё становится на свои места, и благодать наполняет вселенную.

anonymous
()

Синглтоны — добро

Использую синглтоны, состояние в них не держу.

Проблем с тестированием не возникает :)

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

Внезапно, это и есть global scope, и мы получаем синглтон или почти синглтон. И это совершенно оправданно, если в программе не может быть больше одного цикла обработки событий.

Ну и храни состояние в локальной переменной функции-цикла обработки событий. Но это не синглтон.

tailgunner ★★★★★
()

Я как-то много лет назад создавал такую тему.

В общем, в итоге я пришёл к выводу что явная передача состояния гораздо лучше для целей отладки и тестирования. Да и, скажем, не будет проблем с многопоточными приложениями.

По моему опыту синглтоны таки зло.

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

А ты не пробовал ВСЁ состояние программы засунуть в один объект-синглтон? И показательно иметь всю остальную программу stateless?

На первый взгляд это акробатика ради цели, которая мне непонятна.

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

Синглтон это модуль в языке где нет модулей.

Модуль - это тоже баззворд.

На практике у нас либо есть возможность иметь ссылку на _конкретный_ объект, предоставляющий интерфейс; либо её нет, а неявной ссылкой является сам экземпляр процесса.

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

ты в каком языковом окружении , что для тебя модуль токмо базворд?

модуль это (в том числе) то что гарантированно в одном экземляре в программе на той же дельфи/модуле/ и прочих.

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

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

ты в каком языковом окружении , что для тебя модуль токмо базворд?

В основном Си, Ruby, JS.

для тебя модуль токмо базворд?

Есть понятия «пространство имён», «область видимости», «объектный файл» (или шире «единица компиляции»), «запускаемый файл», «процесс», «динамически линкуемая библиотека» и т.п. Они, так сказать, даны нам в ощущениях. А модуль - это случайное сочетание этих понятий, зависящее от воли субъекта.

модуль это (в том числе) то что гарантированно в одном экземляре в программе на той же дельфи/модуле/ и прочих.

Гарантированно уникальное в каком контексте?

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

Ничо она не поработила у нормальных людей. Хотя конечно да, классы в крестах плохи сразу с обеих сторон: и со стороны теории типов, и с той стороны, что в классы быдлокодеры обычно херачат глобальное состояние static переменными. Убивать.

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

подобно сказке про слона и 7 слепых.

у " реальных " сущьностей есть наборы свойств.

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

в результате если в одних сокрытие через реализующую часть модуля в других через приват.

полезно про акторы вспомнить и вообще почему ооп понадобилось - а потому что «реальных мир» распределён.

qulinxao ★★☆
()

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

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

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

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

Для меня синглтон - единственный обьект в контексте инстанса приложения. Много инстансов приложения может существовать в процессе, возможно из-за мого java бекграунда. Есть хорошие или плохие способы обеспечения существования и доступа к синглтону

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

А ты не пробовал ВСЁ состояние программы засунуть в один объект-синглтон? И показательно иметь всю остальную программу stateless? Такой себе сферический MVC. Очень интересно получается, между прочим.

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

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

Ну блин. Любой объект в некотором смысле «хранит состояние программы» (а что ж он ещё-то делает?).

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

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

Хороший способ - singleton scope в IoC контейнере

Это тоже часто считается анти-паттерном.

crowbar
()

Когда прогрессивное человечество уже во всю использует ReaderT, в ООП все еще выясняют, устаревшая ли концепция Синглтон или нет

anonymous
()

Походу все зависит от ЯП. Считать, что синглтон == глобальной переменной исходит от того же опыта. Т.е. критик данной концепции использовал синглтоны как глобальные переменные, потом прочитал, что последние есть зло и сказал: синглтоны - зло. Офигенная логика друзья.

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

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

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

На первый взгляд это акробатика ради цели, которая мне непонятна.

А цель интересная - явным образом избавиться от дублирования состояния в проге. Т.е. если есть объект Foo, и два других объекта хранят на него указатели - то это дублирование состояния. Плохо тем, что эти два указателя кто-то как всегда забудет синхронизировать - обнулить/обновить и т.п. В едином state такого нет. И практика, к удивлению многих, показывает, что кол-во багов от такого финта резко уменьшается. Оставшиеся баги можно классифицировать как 1) нарушение инварианта состояния (возможность такого бага очень снижается некоторыми финтами дизайна этого god-объекта), 2) логические ошибки остального stateless кода, которые сильно проще отлаживать и которые очень хорошо заметны (ибо stateless код), 3) ошибки, вызываемые отсутствием в stateless коде подписки на обновление нужного элемента состояния (тоже тривиально).

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

Pavval ★★★★★
()

есть естественные одиночки и есть надуманные. Например Program/Application всегда одиночки. Бесконтрольное введение одиночек ухудшает.

Можно и нужно использовать паттерн Регистр/Реестр и или шину.

Как говаривал Линус вы не о том думаете - думайте о данных, структурах.... примерно так.

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

есть естественные одиночки и есть надуманные. Например Program/Application всегда одиночки. Бесконтрольное введение одиночек ухудшает.

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

Ну, мне так кажется.

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

каждый отвечает за свой участок

чем меньше объекты знают друг о друге тем лучше

слишком осведомленные это признак нарушения SOLID

Program это в общем корневище дерева дальше пошла вязка узлы и так далее

swwwfactory ★★
()
Последнее исправление: swwwfactory (всего исправлений: 1)

Тут вроде всё уже сказали, так что я просто переформулирую предыдущие комментарии.

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

Ну и следует учесть, что «предсказывать трудно, особенно будущее» (с).

lodin ★★★★
()

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

swwwfactory ★★
()
Последнее исправление: swwwfactory (всего исправлений: 1)

Все претензии к Singleton имеют одну природу, и высказываются одной и той же категорией людей.

Ту же природу имеют претензии к Abstract factory, Builder, Factory method, Prototype, Adapter Bridge, Composite, Decorator, Facade, Flyweight, Proxy, Chain of responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template method, Visitor.

Природа этих претензий такова. Все вышеперечисленное — паттерны проектирования. В головах представителей маргинальных IT-течений «паттерн» однозначно ассоциируется с промышленной разработкой ПО. Но маргинальные технологии не востребованы в промышленной разработке, равно как нет спроса и на маргинал-программистов. Технологии не удовлетворяют промышленным требованиям, а «программисты» не удовлетворяют требованиям социальным. В результате этого формируются комплексы, происходит сублимация негативных эмоций, которые в результате выплескиваются на любой объект, ассоциированный с enterprise.

Проще говоря — бугурт борщевиков.

anonymous
()

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

anonymous
()

У меня в хранилище у каждого объекта есть поле ID, и генератор ID, очевидно, синглтон. А как вы генерируете уникальные численные ID?

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