Re[3]: Почему Singleton антипаттерн
От: Константин Л. Франция  
Дата: 12.08.07 13:26
Оценка: :)
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, Константин Л., Вы писали:


КЛ>>Ты серьезно? Неужели у нас _вообще_ не бывает глобально одиноких сущностей, в приципе?

C>А зачем они нужны? Типичное приложение можно построить без единой глобальной переменной.

Что значит нужны? Они есть независимо от того, хотим мы этого или нет.

КЛ>>А почему мы не знаем его текущее состояние? Че за лажа?

КЛ>>Зависимость? ну так строй все на интерфейсах. Совсем уйти от зависимости тебе и IServiceProvider не поможет.
C>Поможет. Можешь посмотреть, например, на Spring — как там задают зависимости с помощью внешнего конфига.

На Spring смотреть не охота, но верю на слово.
Re[3]: Почему Singleton антипаттерн
От: Константин Л. Франция  
Дата: 12.08.07 13:29
Оценка: :))
Здравствуйте, IB, Вы писали:

IB>Здравствуйте, Константин Л., Вы писали:


КЛ>>неправда. adontz уже показал почему.

IB>Гм.. Повторить сможешь? Увы, но Роме это не удалось...

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

КЛ>>А почему мы не знаем его текущее состояние? Че за лажа?

IB>Господи, ну что за манеры... Выйди из класса, и зайди как учили.
IB>"- Иван Дмитриевич, объясните пожалуйста, почему нам не очевидно состояние глобальной переменной". Давай, я жду... Дневник оставь.



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

КЛ>>Извини чувак, но это

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

Чувак и лажа появились не просто так, а в ответ на твою учительско-дневниковскую манеру высказывать своё мнение. Вот она и тут проявилась
Re[14]: Singleton действительно антипаттерн в enterprize при
От: Константин Л. Франция  
Дата: 12.08.07 13:39
Оценка:
Здравствуйте, IT, Вы писали:

IT>Здравствуйте, adontz, Вы писали:


A>>В целом вырисовывается следующая картина:


IT>А так?


IT>
IT>void level3()
IT>{
IT>    log.log("level 3!");
IT>}
IT>void level2()
IT>{
IT>    level3();
IT>}
IT>void level1()
IT>{
IT>    level2();
IT>}

IT>logger log;

IT>int main(logger pLog)
IT>{
IT>    log = pLog;
IT>    level1();
IT>}
IT>


А это, пардон, откуда? Да и разницы особой не вижу
Re[4]: Почему Singleton антипаттерн
От: Cyberax Марс  
Дата: 12.08.07 13:39
Оценка: :)
Здравствуйте, Константин Л., Вы писали:

КЛ>>>Ты серьезно? Неужели у нас _вообще_ не бывает глобально одиноких сущностей, в приципе?

C>>А зачем они нужны? Типичное приложение можно построить без единой глобальной переменной.
КЛ>Что значит нужны? Они есть независимо от того, хотим мы этого или нет.
Что значит "есть"? Можешь привести хороший пример?

У меня, например, в GUI-приложении ровно 0 глобальных переменных в моем коде (что творится в библиотеках — я точно не знаю).
Sapienti sat!
Re[5]: Почему Singleton антипаттерн
От: adontz Грузия http://adontz.wordpress.com/
Дата: 12.08.07 14:00
Оценка: -1
Здравствуйте, Cyberax, Вы писали:

C>У меня, например, в GUI-приложении ровно 0 глобальных переменных в моем коде (что творится в библиотеках — я точно не знаю).


Извини, это прыжок в сторону. Если ты накидал на форму компоненты и обошлся без глобальных сущностей, это вовсе не означает, что их нет.
Любой аппаратный или разделяемый системный ресурс представляет собой глобальную сущность. У тебя всего одно сетевое соединение, а не по штучке на пакет, у тебя всего один принт-спулер, у тебя всего одно соединение с БД. Далеко не для всех из них надо городить синглтон. Я уже указывал, что синглтоны полезны когда мы хотим протащить сущность из верхнего слоя в нижний (или наоборот) минуя (не затрагивая) промежуточные слои. В остальных случаях IoC бывает достаточно. Но IoC через 4-5 слоёв абстрагирования это редкостный геморрой.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[4]: Почему Singleton антипаттерн
От: adontz Грузия http://adontz.wordpress.com/
Дата: 12.08.07 14:03
Оценка: +1
Здравствуйте, Константин Л., Вы писали:

КЛ>Чувак и лажа появились не просто так, а в ответ на твою учительско-дневниковскую манеру высказывать своё мнение. Вот она и тут проявилась


Мания Величко страшная женщина...

P.S. На самом деле, чем больше Бодягин выставляет свою "мудрость" на показ, тем больше я в неё не верю. Имел счастье общаться с действительно хорошими педагогами, прямо скажем — другой стиль. Иван не плохой специалист, но как и всякий долго работавший, оброс субъективными предрассудками, которые, увы, любит выставлять истиной в последней инстанции.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[6]: Singleton действительно антипаттерн в enterprize прил
От: Константин Л. Франция  
Дата: 12.08.07 14:19
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, Константин Л., Вы писали:


КЛ>>Дык, а откуда брать рутовый сервис? Ручками создавать? Типа rootService = new RootService( ...... ). Ха-ха. Так это еще больше связывает код, чувак.

C>Про IoC (он же "dependency injection") ты слышал?

только что прочел, что это такое. идея, оказывается не нова. а во что я думаю по этому поводу хорошо прднмонстрировал IT в последующих "вопросах" тебе.
Re[6]: Почему Singleton антипаттерн
От: Cyberax Марс  
Дата: 12.08.07 14:20
Оценка:
Здравствуйте, adontz, Вы писали:

C>>У меня, например, в GUI-приложении ровно 0 глобальных переменных в моем коде (что творится в библиотеках — я точно не знаю).

A>Извини, это прыжок в сторону. Если ты накидал на форму компоненты и обошлся без глобальных сущностей, это вовсе не означает, что их нет.
У меня кроме простого GUI еще много чего интересного есть.

A>Любой аппаратный или разделяемый системный ресурс представляет собой глобальную сущность.

С чего ты взял? Вот сетевая карта, к примеру — делаем ее синглтоном (hint: драйверы для всем известного Realtek 8149). А потом грызем бамбук, когда пользователь устанавливает ДВЕ сетевые карты.

Точно так же и почти со всем остальным оборудованием: звуковухами, приводами CD-ROM, мониторами, видеокартами и т.п.

A>У тебя всего одно сетевое соединение, а не по штучке на пакет, у тебя всего один принт-спулер

C чего ты взял?

A>у тебя всего одно соединение с БД.

С чего ты взял?

Большая часть перечисленого тобой в один прекрасный момент может вдруг перестать быть синглтоном. Кроме, разве что, спулера — это сущность операционной системы (кстати, в некоторых ОС спулеров вполне может быть больше одного), у нас над ним нет контроля.

A>Далеко не для всех из них надо городить синглтон. Я уже указывал, что синглтоны полезны когда мы хотим протащить сущность из верхнего слоя в нижний (или наоборот) минуя (не затрагивая) промежуточные слои. В остальных случаях IoC бывает достаточно. Но IoC через 4-5 слоёв абстрагирования это редкостный геморрой.

Если IoC делать заранее — то потом добавление еще одного параметра делается легко и безболезненно. А в существующее приложение, действительно, приходится иногда вставлять синглтоновые хаки.
Sapienti sat!
Re[4]: Почему Singleton антипаттерн
От: Константин Л. Франция  
Дата: 12.08.07 14:21
Оценка: -1 :)))
Здравствуйте, Igor Trofimov, Вы писали:

iT>>>Значит, любой клас с конструктором — антипаттерн.

IB>>А что, в любом классе конструктор занимается контролем количества экземпляров?

iT>Конечно! Он позволяет создать еще один экземпляр, что увеличивает количество на 1.


iT>>>А если у тебя экземпляр предоставляется IoC-контроллером, то типа, этих проблем нет?

IB>>Этих нет, без типа.
iT>И как же это так получается, интересно... Вот ты настраиваешь IoC так, чтобы тебе возвращался один и тот же экзе+мпляр (singleton scope).
iT>И что — это не будет похоже на глобальную переменную в плане разделения состояния?

+1

iT>IoC — это только способ вынесения зависимости в другое место. Какие это зависимости — по-прежнему зависит от тебя.

iT>И плюсы/минусы этих зависимостей остаются теми же.

+10

iT>>>А если у тебя экземпляр предоставляется IoC-контроллером, то типа, этих проблем нет?

IB>>И этих тоже нет.

iT>Теперь здесь. Я надеюсь, ты не включаешь в понятие "публичного контракта класса" конфиг IoC, в котором написано, какие компоненты нужно к нему прицепить?

iT>И по-прежнему, зависимость просто выносится в конфиг, а в контракте ее как не было, так и не нет.
iT>То есть тот, кто будет разрабатывать клиента для этого класса, точно также не узнает, что в результате клас будет использовать такой-то синглтон/сервис для своей реализации.

+100

iT>>>Вот это, по-моему, единственная реальная проблема.

IB>>Странная логика, если проблема, по твоим словам, проявляется не только в синглтоне, то это вроде как уже и не проблема?

+1

iT>Если проблема проявляется не только в синглтоне, то не нужно приписывать ее синглтону как таковому, выявляя таким образом, его "антипаттерность".


+1

iT>>>А с IoC-контроллерами своя беда — возрастает сложность (и вероятность ошибок) в нсатройке и корректном соединении всех компонентов.

IB>>Выбирай, но осторожно, но выбирай.
iT>Именно. Вешай ярлыки, но осторожно

+1

Re[15]: Singleton действительно антипаттерн в enterprize при
От: WolfHound  
Дата: 12.08.07 14:28
Оценка: +1
Здравствуйте, adontz, Вы писали:

A>Тоже не будет работать. level1, level2, level3 будут в разных единицах компиляции и иметь общую глобальную переменную им не светит.

extern никто не отменял.

Короче ты можешь тут говорить что угодно но синглетон == глобальная переменная.
Различия косметические.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[13]: Singleton действительно антипаттерн в enterprize при
От: WolfHound  
Дата: 12.08.07 14:28
Оценка: +1
Здравствуйте, adontz, Вы писали:

A>Callback'и на мой взгляд более приемлемое решение (особенно делегатами), но практическая реализация нередко затруднена. Кроме того этот самый указатель/делегат надо опять таки передать через все уровни и реальная разница в сложности реализации и поддержки между Dependency injection и Callback стирается.

Если использовать Dependency injection правильно, а не как ты то получается совсем другая картина:
void level3(ServiceProvider const* sp)
{
    sp->get<ILogger>()->log("level 3!");
}
void level2(ServiceProvider const* sp)
{
    level3(sp);
}
void level1(ServiceProvider const* sp)
{
    level2(sp);
}
int main()
{
    logger log;
    log.initialize(bla-bla-bla);

    ServiceProvider sp;
    sp.add<ILogger>(&log);

    level1(&sp);
}

А теперь добавим в лог вывод информации о втором уровне
void level3(ServiceProvider const* sp)
{
    sp->get<ILogger>()->log("level 3!");
}
void level2(ServiceProvider const* baseSp, bla-bla-bla)
{
    loggerWithSomeInfo log;
    log.initialize(baseSp->get<ILogger>(), bla-bla-bla);

    ServiceProvider sp(baseSp);
    sp.add<ILogger>(&log);

    level3(&sp);
}
void level1(ServiceProvider const* sp)
{
...
    level2(sp, bla-bla-bla);
...
}
int main()
{
    logger log;
    log.initialize(bla-bla-bla);

        ServiceProvider sp;
        sp.add<ILogger>(&log);

    level1(&sp);
}

Таким образом мы на каждом уровне можем: добавлять, удалять и заменять сервисы.

Жду решение на синглетоне...
Только учти что level1 навызывал level2 в куче потоков с разными bla-bla-bla...
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Почему Singleton антипаттерн
От: adontz Грузия http://adontz.wordpress.com/
Дата: 12.08.07 14:48
Оценка: :)
Здравствуйте, Cyberax, Вы писали:

A>>Любой аппаратный или разделяемый системный ресурс представляет собой глобальную сущность.

C>С чего ты взял? Вот сетевая карта, к примеру — делаем ее синглтоном (hint: драйверы для всем известного Realtek 8149). А потом грызем бамбук, когда пользователь устанавливает ДВЕ сетевые карты.

Э, нет-нет. По синглтону на каждую физическую карту Realtek'у горячий привет.

A>>У тебя всего одно сетевое соединение, а не по штучке на пакет, у тебя всего один принт-спулер

C>C чего ты взял?

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

A>>у тебя всего одно соединение с БД.

C>С чего ты взял?

Ты подключаешься к БД заново для каждого запроса?

C>Большая часть перечисленого тобой в один прекрасный момент может вдруг перестать быть синглтоном.


Не перестанет, просто синглтон станет чуть сложнее обычного и в метод GetInstance придётся веести уточняющий параметр. В GoF это упоминается в комментариях.
Хорошим примером такого синглтона является класс CultureInfo. Метод CultureInfo.GetCultureInfo возвращает по-разному инициализированные экземпляры CultureInfo (в отличие от фабричного метода, который бы возвращал наследников CultureInfo). Уникальность поддерживается уже не на уровне типа, а на уровне типа+локали. Последовательные вызовы CultureInfo.GetCultureInfo(1049) вернут один и тот же объект и даже вызовы CultureInfo.GetCultureInfo(1049) и CultureInfo.GetCultureInfo("ru-RU") возвращают один и тот же объект. Это синглтон, просто уникальность экземпляра определяется уже не только типом. В твоём примере с реалтеками вполне могло быть NetworkAdapter.GetNetworkAdapter("15:35:28:15:14:95") и NetworkAdapter.GetNetworkAdapter("40:63:40:83:00:96") и это были бы синглтоны на уровне typeof(NetworkAdapter)+MAC.

C>Если IoC делать заранее — то потом добавление еще одного параметра делается легко и безболезненно. А в существующее приложение, действительно, приходится иногда вставлять синглтоновые хаки.


Никогда в проекте ты не сможешь задействовать сторонние библиотеки полностью удовлетворяющие все твои фантазии.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[16]: Singleton действительно антипаттерн в enterprize при
От: adontz Грузия http://adontz.wordpress.com/
Дата: 12.08.07 15:14
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>extern никто не отменял.


Из DLL ок?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[14]: Singleton действительно антипаттерн в enterprize при
От: adontz Грузия http://adontz.wordpress.com/
Дата: 12.08.07 15:21
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Жду решение на синглетоне...

WH>Только учти что level1 навызывал level2 в куче потоков с разными bla-bla-bla...

Во-первых, ты подменил задачу, так что никакого решения на синглтоне не будет. Задача подмены сервисов изначально не стояла.
Во-вторых, представь что level2 и level3 менять нельзя (библиотечный код, причём не твой). Очень интересно как тебе помогут сервисы...
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[5]: Почему Singleton антипаттерн
От: Константин Л. Франция  
Дата: 12.08.07 15:40
Оценка:
Здравствуйте, adontz, Вы писали:

[]

да и мы иногда страдаем, чего греха таить
Re[15]: Singleton действительно антипаттерн в enterprize при
От: IT Россия linq2db.com
Дата: 12.08.07 15:55
Оценка:
Здравствуйте, adontz, Вы писали:

A>Так не скомпилируется, у функции main параметрами могут быть только (int argc, char ** argv)


Ну да, а так?

void level3()
{
    log.log("level 3!");
}
void level2()
{
    level3();
}
void level1()
{
    level2();
}

logger log;

int main1(logger pLog)
{
    log = pLog;
    level1();
}

int main()
{
    logger log;

    log.initialize(bla-bla-bla);
        
    main1(log);
}

A>Тоже не будет работать. level1, level2, level3 будут в разных единицах компиляции и иметь общую глобальную переменную им не светит.

Ну так ты тогда и приведи пример с разными единицами.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[15]: Singleton действительно антипаттерн в enterprize при
От: IT Россия linq2db.com
Дата: 12.08.07 15:55
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>А это, пардон, откуда?


Попытайся мыслить абстрактно.

КЛ>Да и разницы особой не вижу


Здрасьте. Рома больше всего протестует по причине наличия у всей цепочки вызываемых методов дополнительного параметра. Скажу тебе по секрету. Такие параметры элементарно убираются и никаких проблем не вызывают.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[15]: Singleton действительно антипаттерн в enterprize при
От: WolfHound  
Дата: 12.08.07 15:59
Оценка:
Здравствуйте, adontz, Вы писали:

A>Во-первых, ты подменил задачу, так что никакого решения на синглтоне не будет. Задача подмены сервисов изначально не стояла.

Она подменилась после того как наколбасили 10 метров кода... Или ты хочешь сказать что у тебя никогда требования не меняются?
В случае с Dependency injection проблем не возникает, а вот как такое провернуть на синглетонах...

A>Во-вторых, представь что level2 и level3 менять нельзя (библиотечный код, причём не твой). Очень интересно как тебе помогут сервисы...

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

А теперь всетки попробуй предоставить решение на синглетоне... да у нас уже есть 10 метров кода... использующие синглетон.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[17]: Singleton действительно антипаттерн в enterprize при
От: WolfHound  
Дата: 12.08.07 15:59
Оценка:
Здравствуйте, adontz, Вы писали:

WH>>extern никто не отменял.

A>Из DLL ок?
Гм:
dll.h
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

DLL_API void iddqdPrint();
DLL_API extern int iddqd;

dll.cpp
#include <iostream>
#include "dll.h"

DLL_API int iddqd = 0;
DLL_API void iddqdPrint()
{
    std::cout << iddqd << "\n";
}

test.cpp
#include "dll.h"
int main()
{
    for (int i = 0; i < 1000000; ++i)
    {
        iddqd = i * i;
        iddqdPrint();
    }
    return 0;
}

Ы?

Если ты про переносимый способ по его нет ибо С++ ничего про dll не знает.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Почему Singleton антипаттерн
От: Cyberax Марс  
Дата: 12.08.07 16:15
Оценка:
Здравствуйте, adontz, Вы писали:

C>>С чего ты взял? Вот сетевая карта, к примеру — делаем ее синглтоном (hint: драйверы для всем известного Realtek 8149). А потом грызем бамбук, когда пользователь устанавливает ДВЕ сетевые карты.

A>Э, нет-нет. По синглтону на каждую физическую карту Realtek'у горячий привет.
Как ты себе это представляешь?
class CardOneSinglton
{
};
CardOneSinglton cardOneInstance;

class CardTwoSinglton
{
};
CardTwoSinglton cardTwoInstance;
...

Так что ли?

A>>>У тебя всего одно сетевое соединение, а не по штучке на пакет, у тебя всего один принт-спулер

C>>C чего ты взял?
A>С чего я взял что ты не создаёшь новое подключение на каждый сетевой пакет? Я считал тебя умным, других оснований нет.
HTTP — он connectionless. То есть, иногда по одному соединению с keep-alive'ом могут несколько запросов пройти, но в общем случае — да, по соединению на запрос.

A>>>у тебя всего одно соединение с БД.

C>>С чего ты взял?
A>Ты подключаешься к БД заново для каждого запроса?
У меня из приложения вообще нет соединений с БД В качестве источника данных используется библиотека, которая общается с load-ballanced statless-сервисами на серверах.

C>>Большая часть перечисленого тобой в один прекрасный момент может вдруг перестать быть синглтоном.

A>Не перестанет, просто синглтон станет чуть сложнее обычного и в метод GetInstance придётся веести уточняющий параметр. В GoF это упоминается в комментариях.
Ага. А откуда ты значение этого "уточняющего параметра" будешь брать?

A>Это синглтон, просто уникальность экземпляра определяется уже не только типом. В твоём примере с реалтеками вполне могло быть NetworkAdapter.GetNetworkAdapter("15:35:28:15:14:95") и NetworkAdapter.GetNetworkAdapter("40:63:40:83:00:96") и это были бы синглтоны на уровне typeof(NetworkAdapter)+MAC.

А нафиг такое нужно? Это уже клиника.

Мы передаем MAC-адрес вместо того, чтобы передавать явную ссылку на NetworkAdapter.

C>>Если IoC делать заранее — то потом добавление еще одного параметра делается легко и безболезненно. А в существующее приложение, действительно, приходится иногда вставлять синглтоновые хаки.

A>Никогда в проекте ты не сможешь задействовать сторонние библиотеки полностью удовлетворяющие все твои фантазии.
У меня вот получается. Тем более, что никаких экзотических требований я не выдвигаю — нужно просто уметь передавать контекст. Я даже не могу вспомнить нормальную библиотеку, где это явно нельзя было бы делать. Разве что на ум приходит несколько кривых мест в WinAPI.
Sapienti sat!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.