Re[2]: Singleton действительно антипаттерн в enterprize прил
От: adontz Грузия http://adontz.wordpress.com/
Дата: 10.08.07 13:58
Оценка: 7 (1) +1 :)
Здравствуйте, IB, Вы писали:

IB>"главная проблема синглтона в том, что это первый паттерн описанный в GoF" (c) MaximVK. На него набрасываются и не замечают его недостатков, из коих:


Это не недостатки синглтона ни в коем случае, не надо воодить народ к заблуждение.

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


Это глупость, причём документально подтверждённая GoF. Действительно, в GoF синглтон описан как
class Singleton {
public:
    static Singleton* Instance();
protected:
    Singleton();
private:
    static Singleton* _instance;
}

и в таком виде описанная тобой проблема существует. Однако, не стоит заниматься буквоедством, тем более там, где это нелепо выглядит. Пример из книжки всегда прост и передаёт лишь суть и никогда не является объектом для дословного копирования. Всякий нормальный программист отделяет задачу контроля количества копий и пишет нечто вроде
template<T>
class singleton
{
    public:
        static const T * get_instance();
    private:
        static T * _instance;
}

либо
class Singleton<T> where T: new
{
    private static T _instance = default(T);
    public static T Instance { get; }
}
// или даже
class Singleton<T> where T: new, ISingleton
{
    private static T _instance = default(T);
    public static T Instance { get; }
}

либо как-то ещё, смотря от языка.

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


Singleton это stateless объект. Всякая другая его реализация ошибочна. Я тебя тут вообще не понял. Ты сперва сделал синглотон statefull объектом, а потом начал рассказывать какой синглотон плохой. Но это не синглтон плохой, это ты плохой, что сделал его statefull. Не надо путать тёплое с мягким.

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


Опять таки, ты сперва делаешь неверное предположение, а потом исходя из него строишь какие-то домыслы о недостатках синглтона. Кто сказал что зависимость обычного класса от синглтона должна быть видна? Вот у меня DAL зависит от системы журналирования, но из внешнего интерфейса DAL это не видно. И что? Я не вижу тут абсолютно никакой проблемы, тем более не вижу проблемы в синглтоне через который ведётся журналирования. Такого рода зависимости видны в настройках проекта и этого боле чем достаточно.

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


Во-первых, подкинуть Mock объект запросто можно (смотри второй пример на C#), во-вторых наличие состояний у синглтона это зло, причём зло в мозгах программиста, а не в синглтоне.

IB>Говоря же проще — синглтон повышает связность, и все вышеперечисленное, в том или ином виде, есть следствие повышения связности.


Да вообще зависимость одних модулей от других повышает связность

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


Граблей никаких нет, если есть элементарное понимание области применения синглтона.

IB>Наибольшая же опасность, как было сказано, подстерегает при попытке построить на основе сиглтонов всю архитектуру приложения, такому подходу существует масса замечательных альтернатив. Например, IoC контейнеры — там проблема контроля создания сервисов решается естественным образом, так как они, по сути, являются "фабриками на стероидах" =). Другой альтернативой являются Service Locator-ы, из известных вариантов этого подхода — паттерн IServiceProvider.


Объясни мне доступно чем
GetService(typeof(MyService))
принципиальное лучше чем
Singleton<MyService>.Instance
если у нас всего один сервис.
Аргументы за сервисы, которые ты приводишь, актуальны, когда есть потребность в Chain of Responsibility, но это совсем другая задача.
A journey of a thousand miles must begin with a single step © Lau Tsu
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.