Re: Почему Singleton антипаттерн
От: the_dip Таджикистан  
Дата: 13.08.07 10:48
Оценка: :)
Здравствуйте, IB, Вы писали:

IB>1. Синглтон нарушает SRP (Single Responsibility Principle) — класс синглтона, помимо того чтобы выполнять свои непосредственные обязанности, занимается еще и контролированием количества своих экземпляров.

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

IB>2. Глобальное состояние. Про вред глобальных переменных вроде бы уже все знают, но тут та же самая проблема. Когда мы получаем доступ к экземпляру класса, мы не знаем текущее состояние этого класса, и кто и когда его менял, и это состояние может быть вовсе не таким, как ожидается. Иными словами, корректность работы с синглтоном зависит от порядка обращений к нему, что вызывает неявную зависимость подсистем друг от друга и, как следствие, серьезно усложняет разработку.

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

IB>3. Зависимость обычного класса от синглтона не видна в публичном контракте класса. Так как обычно экземпляр синглтона не передается в параметрах метода, а получается напрямую, через GetInstance(), то для выявления зависимости класса от синглтона надо залезть в тело каждого метода — просто просмотреть публичный контракт объекта недостаточно.

Ну и что? Какие *практические* последствия это имеет? Чтобы выявить все зависимости, достаточно текстового поиска по коду. Если зависимость имеет критическое значение, ее можно (и нужно) отразить в комментариях.

IB>4. Наличие синглтона понижает тестируемость приложения в целом и классов, которые используют синглтон, в частности. Во-первых, вместо синглтона нельзя подпихнуть Mock-объект, а во-вторых, если синглтон имеет интерфейс для изменения своего состояния, то тесты начинают зависеть друг от друга.

Не совсем так. Например, в C++ можно тест сделать friend-ом синглтона, открыв тесту доступ к приватному конструктору синглтона. Тогда тест сможет самостоятельно создавать "свеженькие" синглтоны в любом нужном количестве.

IB>Естественно, можно акккуратненько пройти по граблям и использовать синглетон, но (цитата из доки к пикоконтейнеру) "Overuse makes for bad solutions. At the enterprise level, it makes for very very bad solutions"...

Ну так там сказано четко overuse, а не use.
Re[21]: Singleton действительно антипаттерн в enterprize при
От: IB Австрия http://rsdn.ru
Дата: 13.08.07 11:06
Оценка:
Здравствуйте, adontz, Вы писали:

A>Я не понял твой мысли о явности, приведи пример языка и кода.

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

A>Я с этим мнением не согласен

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

A>В том что синглтон при правильном использовании не причиняет проблем

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

A>Извини, но твоя моральная неустойчивость никогда не будет моей проблемой.

К сожалению получается наоборот — твоя моральная неустойчивость становится проблемой окружающих.

A>Верно.

Твои проблемы..

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

"The term factory method is often used to refer to any method whose main purpose is creation of objects"
Это объективная реальность. Ты можешь с этим не соглашаться, но тогда у тебя будут постоянные терминологические проблемы.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[10]: Почему Singleton антипаттерн
От: IB Австрия http://rsdn.ru
Дата: 13.08.07 11:06
Оценка:
Здравствуйте, adontz, Вы писали:

A>Я теперь играю в игру "кто не смог остановиться".

У тебя хорошо получается..

A>Опять личный наезд?

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

A>Про синглтоны пожалуйста, про синглтоны...

Я тебе уже все про них рассказал, если не понимаешь — извеняй.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[19]: Singleton действительно антипаттерн в enterprize при
От: WolfHound  
Дата: 13.08.07 11:25
Оценка:
Здравствуйте, adontz, Вы писали:

WH>>Псевдокод можно? А то словами у тебя както не очень получилось объяснить.

A>Можно.
Это мягко говоря не то.
Мне не нужно выводить в несколько логгеров. Хотя эсли это понадобится я это легко сделаю.
Логгер у меня один но много сессий. И для каждой сесии нужно что-то дописать в лог.
А внутри сессии есть запросы. И для каждого запроса тоже что-то нужно дописать в лог.
Таким образом из лога в который в много потоков пишут кучу всякой дряни можно банальным grep'ом выцепить отдельную сессию и каждый отдельный запрос сессии.
На синглетонах это не делается.

A>Проблема очевидная. Пишешь managed обёртку в виде какого-нибудь

хъ
A>потому что заставлять клиента явно создавать делегат и хранить на него ссылку не катит.
A>Таких сюрпризов у меня в своё время было не мало.
Скрещивание ежа с ужом это разговор отдельный и в любом случае требует изучения работы всех функций.
Кстати зачем выделеное SomeGlobalDelegateTable? В многопоточностью проблем не боишься?

A>Случай простой — инициализация тяжёлая операция и не всегда нужная. Мне, например, не нравятся приложения стартующие 2-3 минуты потому что программист не стал заморачиваться и решил инициализировать всё сразу.

Не грузить то что грузить не нужно никак не связано с тем используются синглетоны или нет.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[18]: Singleton действительно антипаттерн в enterprize при
От: adontz Грузия http://adontz.wordpress.com/
Дата: 13.08.07 12:23
Оценка:
Здравствуйте, AndrewJD, Вы писали:

AJD>Не совсем понял, что ты конкретно предлагаешь: на каждом уровне добавлять/удалять логгеры


На каждом, конечно же не надо, но Wolfhound захотел иметь возможность подменить (декорировать?) на уровне 2 логгер скончифурированный на уровне 1 и используемый на уровне 3. Эта возможность есть, задача решена.

AJD>или чтобы фильтры сами разбирались какое сообщение куда они пишут и должны ли они передовать вызов дальше по цепочке фильтров?


Это уже детали реализации, я привёл лишь один из вариантов. На самом деле message bubbling одно из самых гибких и расширяемых решений, не говоря уже о том, что оно мною очень любимо . Как именно будет реализована передача вызовов по цепочке сильно зависит от задачи.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[20]: Singleton действительно антипаттерн в enterprize при
От: adontz Грузия http://adontz.wordpress.com/
Дата: 13.08.07 12:39
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Мне не нужно выводить в несколько логгеров. Хотя эсли это понадобится я это легко сделаю.

WH>Логгер у меня один но много сессий. И для каждой сесии нужно что-то дописать в лог.
WH>А внутри сессии есть запросы. И для каждого запроса тоже что-то нужно дописать в лог.

Chain of Responsibility позволяет декорировать поведение. Ты делаешь базовый логгер и логгер который что-то дописывает в зависимости от сессии, расшряя (но не заменяя) поведение базового. Я не зря указал отдельно is_handled и отдельно is_canceled. Воспринимай Chain of Responsibility как список декораторов (собственно это и есть список декораторов).

WH>Скрещивание ежа с ужом это разговор отдельный и в любом случае требует изучения работы всех функций.

WH>Кстати зачем выделеное SomeGlobalDelegateTable? В многопоточностью проблем не боишься?

Global потому что время жизни подписки может быть больше, чем время жизни объекта. Например, возьмём интероп к HTMLayout.
Есть HTML код
<html>
    <head>
    </head>
    <body>
        <div id="box" style="width: 100px; height: 100px">
           Click me!
        </div>
    </body>
</html>

и я хочу подписаться на мышиное сообщение для div. Выглядит это так
HtmlTag div = _htmlView.Root.SelectFirst("div#box");
div.Mouse += OnMouse;

После чего объект div благополучно уничтожается и собирается сборщиком мусора, а вот оповещения в OnMouse приходят.

WH>Не грузить то что грузить не нужно никак не связано с тем используются синглетоны или нет.


Просто с синглтонами эта проблема решается сама собой, без дополнительных усилий.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Почему Singleton антипаттерн
От: Ужасть бухгалтера  
Дата: 13.08.07 12:47
Оценка: 46 (4) +4 :)
IB>"главная проблема синглтона в том, что это первый паттерн описанный в GoF" (c) MaximVK.

Подумалось...
"Вторая главная проблема синглтона в том, что это первый описанный антипаттерн".

Раньше же как было? На встреченную глобальную переменную: "Вы чё, чуваки, офигели? Всем срочно юзать паттерны! Есть же синглтон, в конце концов!". Говорящий при этом выглядит до фига крутым и умным: как же, умные книжки читает, использует паттерны проектирования, последние модные технологии, все дела...

То сейчас на встреченный синглтон: "Вы чё, чуваки, офигели? Вы шо, не знаете, шо синглтон — АНТИПАТТЕРН, ёптыть?!" Говорящий выглядит еще более крутым и умным, ибо читает, оказывается, еще более умные и модные книжки. При этом заодно повышает свою самооценку, т.к. получает возможность возвыситься над ретроградами, ничтожными юзерами синглтонов.

ИМХО, всему найдется свое место. И IoC полезен, и у синглтона есть область применения. И даже глобальную переменную иногда можно куда-нить приткнуть

ИМХО, лучше просто трезво оценивать возможную область применения синглтона, его плюсы/минусы и возможные альтернативы. А то из-за ожесточенного флейма в этой ветке возникает впечатление, что некоторые зачем-то пытаются свести использование синглтона вообще к нулю.
Re[2]: Почему Singleton антипаттерн
От: adontz Грузия http://adontz.wordpress.com/
Дата: 13.08.07 13:03
Оценка: :)
Здравствуйте, Ужасть бухгалтера, Вы писали:

УБ>ИМХО, лучше просто трезво оценивать возможную область применения синглтона, его плюсы/минусы и возможные альтернативы. А то из-за ожесточенного флейма в этой ветке возникает впечатление, что некоторые зачем-то пытаются свести использование синглтона вообще к нулю.


Охотники на ведь всегда были есть и будут. Главное помнить, что у каждой ведьмы есть внучка — девочка Таня и она объязательно отомстит программисту под новый год.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[19]: Singleton действительно антипаттерн в enterprize при
От: AndrewJD США  
Дата: 13.08.07 13:08
Оценка:
Здравствуйте, adontz, Вы писали:

AJD>>Не совсем понял, что ты конкретно предлагаешь: на каждом уровне добавлять/удалять логгеры

A>На каждом, конечно же не надо, но Wolfhound захотел иметь возможность подменить (декорировать?) на уровне 2 логгер скончифурированный на уровне 1 и используемый на уровне 3. Эта возможность есть, задача решена.

В случае многопоточности, прийдется все запихивать в TLS, а иначе будет ой.
Использование TLS многие проблемы решает, поскольку это контекст поддерживаемый системой. Но отлаживать его вряд ли будет удобно.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[21]: Singleton действительно антипаттерн в enterprize при
От: WolfHound  
Дата: 13.08.07 14:51
Оценка:
Здравствуйте, adontz, Вы писали:

A>Chain of Responsibility позволяет декорировать поведение. Ты делаешь базовый логгер и логгер который что-то дописывает в зависимости от сессии, расшряя (но не заменяя) поведение базового. Я не зря указал отдельно is_handled и отдельно is_canceled. Воспринимай Chain of Responsibility как список декораторов (собственно это и есть список декораторов).

И как мне поможет цепочка? Мне нужно дерево. Есть один логгер который пишет в файлик. Есть сотня активных сессий. У каждой сесии куча запросов. При помощи DI я это делаю легко. Как это сделать синглетонами не ясно.
Передавать при каждом вызове логгера информацию о сессии и запросе не вариант.

A>Global потому что время жизни подписки может быть больше, чем время жизни объекта. Например, возьмём интероп к HTMLayout.

A>Есть HTML код
хъ
A>После чего объект div благополучно уничтожается и собирается сборщиком мусора, а вот оповещения в OnMouse приходят.
Оповещения для мертвого объекта?! Ахринеть! ИМХО либо ты либо c-smile гдето накосячили.

A>Просто с синглтонами эта проблема решается сама собой, без дополнительных усилий.

синглетоны сами по себе одни сплошные дополнительные усилия.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: Почему Singleton антипаттерн
От: Igor Trofimov  
Дата: 13.08.07 16:18
Оценка:
iT>>И плюсы/минусы этих зависимостей остаются теми же.
IT>Плюсы/минусы остаются. Разница в том, что количество проблемных мест с этими плюсами/минусами резко сокращается, а в большинстве случаев стремится к нулю.

Да ладно уж — резко... что реализацию статического свойства подкрутиить, возможно даже заменив тип реально возвращаемого экземпляра, то ли в конфиге то же поправить — один фиг.
Re[4]: Почему Singleton антипаттерн
От: Igor Trofimov  
Дата: 13.08.07 16:20
Оценка: :)
КЛ>На Spring смотреть не охота, но верю на слово.

Лучше посмотри А то сейчас тебе тут наговорят, а ты и возразить аргументированно не сможешь
Re[2]: Почему Singleton антипаттерн
От: IT Россия linq2db.com
Дата: 13.08.07 17:13
Оценка: +5
Здравствуйте, Ужасть бухгалтера, Вы писали:

УБ>ИМХО, всему найдется свое место. И IoC полезен, и у синглтона есть область применения. И даже глобальную переменную иногда можно куда-нить приткнуть


Качество кода и применяемых решений легко проверяется, когда возникает необходимость в модификации кода. При этом чем качественнее код, тем проще делать более сложные изменения. И наоборот, чем некачественнее код, тем сложнее делать даже простые вещи.

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

УБ>ИМХО, лучше просто трезво оценивать возможную область применения синглтона, его плюсы/минусы и возможные альтернативы. А то из-за ожесточенного флейма в этой ветке возникает впечатление, что некоторые зачем-то пытаются свести использование синглтона вообще к нулю.


Это очень легко объясняется. Разумные люди стараются не наступать на одни и теже грабли дважды и, поимев проблемы с синглетоном один раз, предпочитают больше с ним не связываться даже если его применение локально ограничено и проблем при модификации кода не вызывает. А учитывая, что серьёзных архитектурных преимуществ синглетон не даёт, то гораздо проще и разумнее предать его анафеме и не связываться с ним даже в тех случаях, когда с ним проблем не возникает.
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Почему Singleton антипаттерн
От: IT Россия linq2db.com
Дата: 13.08.07 17:25
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>Да ладно уж — резко... что реализацию статического свойства подкрутиить, возможно даже заменив тип реально возвращаемого экземпляра, то ли в конфиге то же поправить — один фиг.


Проблемы не с самим синглетоном, проблемы с кодом, который его использует. И вообще, ты синглетон с фабрикой случайно не путаешь?
Если нам не помогут, то мы тоже никого не пощадим.
Re[22]: Singleton действительно антипаттерн в enterprize при
От: adontz Грузия http://adontz.wordpress.com/
Дата: 13.08.07 18:05
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>И как мне поможет цепочка? Мне нужно дерево. Есть один логгер который пишет в файлик. Есть сотня активных сессий. У каждой сесии куча запросов. При помощи DI я это делаю легко. Как это сделать синглетонами не ясно.

WH>Передавать при каждом вызове логгера информацию о сессии и запросе не вариант.

Я что-то совсем не понял зачем тебе дерево. Можно примерчик простенький?

WH>Оповещения для мертвого объекта?!


Нет, OnMouse метод формы. Форма жива, куда она денется?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[3]: Почему Singleton антипаттерн
От: adontz Грузия http://adontz.wordpress.com/
Дата: 13.08.07 18:11
Оценка:
Здравствуйте, IT, Вы писали:

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


Игорь, а причём тут синглтоны? Если ты попытаешься вынести с сервера на клиент любой код который завязан на что-то, чему на клиенте делать нечего, будут проблемы. Ты понимаешь в чём дело, я не фанат синглтонов, но вы всё время приводите какие-то левые недостатки непосредственно к синглтонам отношения не имеющие. Неубедительно.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[22]: Singleton действительно антипаттерн в enterprize при
От: adontz Грузия http://adontz.wordpress.com/
Дата: 13.08.07 18:19
Оценка:
Здравствуйте, WolfHound, Вы писали:

A>>После чего объект div благополучно уничтожается и собирается сборщиком мусора, а вот оповещения в OnMouse приходят.

WH>Оповещения для мертвого объекта?! Ахринеть! ИМХО либо ты либо c-smile гдето накосячили.

Вобщем вот как оно выглядит. Выздал из примера.
        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            // Подписались.
            // Временные объекты HtmlTag которые вернули вызовы this._htmlView.Root.SelectFirst сдохли.
            this._htmlView.Root.SelectFirst("#add_row").Behavior += new HtmlBehaviorEventHandler(AddRow_OnMouse);
            this._htmlView.Root.SelectFirst("#remove_row").Behavior += new HtmlBehaviorEventHandler(RemoveRow_OnMouse);
        }

        public bool AddRow_OnMouse(
            IntPtr forInternalUse,
            IntPtr hTag,
            HtmlEventGroup eventGroup,
            ref HtmlBehaviorEventParameters parameters)
        {
            // While this application is an example, it can be used as test of event dispatching system.
            // The following lines make you sure that Nabu.Forms.HtmlLayout keeps
            // managed references to delegates internally not allowing them to be collected.
            GC.Collect();
            GC.WaitForPendingFinalizers();

            return false;
        }

        public bool RemoveRow_OnMouse(
            IntPtr forInternalUse,
            IntPtr hTag,
            HtmlEventGroup eventGroup,
            ref HtmlBehaviorEventParameters parameters)
        {
            // While this application is an example, it can be used as test of event dispatching system.
            // The following lines make you sure that Nabu.Forms.HtmlLayout keeps
            // managed references to delegates internally not allowing them to be collected.
            GC.Collect();
            GC.WaitForPendingFinalizers();

            return false;
        }
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[3]: Почему Singleton антипаттерн
От: IB Австрия http://rsdn.ru
Дата: 13.08.07 19:19
Оценка:
Здравствуйте, IT, Вы писали:

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

"Устав написан кровью" (с)
=)
Мы уже победили, просто это еще не так заметно...
Re[2]: Почему Singleton антипаттерн
От: IB Австрия http://rsdn.ru
Дата: 13.08.07 19:26
Оценка:
Здравствуйте, Ужасть бухгалтера, Вы писали:

УБ>"Вторая главная проблема синглтона в том, что это первый описанный антипаттерн".

Ну, не первый... Но можно сказать — классический..

УБ>То сейчас на встреченный синглтон: "Вы чё, чуваки, офигели? Вы шо, не знаете, шо синглтон — АНТИПАТТЕРН, ёптыть?!" Говорящий выглядит еще более крутым и умным, ибо читает, оказывается, еще более умные и модные книжки. При этом заодно повышает свою самооценку, т.к. получает возможность возвыситься над ретроградами, ничтожными юзерами синглтонов.

Бывают же такие...
Нет бы им, как я — четко описал основные недостатки (чтобы если взялись пользоваться — знали чего бояться) и рекомендации, что можно использовать в замен, по ситуации.

УБ> А то из-за ожесточенного флейма в этой ветке возникает впечатление, что некоторые зачем-то пытаются свести использование синглтона вообще к нулю.

Ой не говори. Не флеймили бы по пустякам, да еще бы внимательно читали, с чем спорят — вообще рай был бы...
Мы уже победили, просто это еще не так заметно...
Re[4]: Почему Singleton антипаттерн
От: IT Россия linq2db.com
Дата: 13.08.07 19:55
Оценка: +1
Здравствуйте, adontz, Вы писали:

A>Игорь, а причём тут синглтоны? Если ты попытаешься вынести с сервера на клиент любой код который завязан на что-то, чему на клиенте делать нечего, будут проблемы. Ты понимаешь в чём дело, я не фанат синглтонов, но вы всё время приводите какие-то левые недостатки непосредственно к синглтонам отношения не имеющие. Неубедительно.


Ну давай на примере, если не убедительно.

public class MyClass : MyBaseClass
{
  void MyMethod()
  {
    IMyService service = ServiceProvider.GetService<IMyService>();
    if (service != null)
        service.DoSome();
  }
}

Что мне нужно сделать, чтобы данный код заработал как на сервере так и на клиенте? Правильно ничего. Нужно лишь обеспечить доступность интерфейса IMyService и там и там.

public class MyClass : MyBaseClass
{
  void MyMethod()
  {
    Singleton<MyService>.Instance.DoSome();
  }
}

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