![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Как-то я не врубался во вред синглтонов - пока не пришлось рефакторить одну и ту же апликацию, разнесённую по двум платформам методом копи-пейста. Всякая собака ссылается на синглтон. Будто нельзя в параметрах получить (di, т.е.)
Так я о чём? Да вот: синглтон класса - это примерно как поименованная общая область. Вот вам имя, вот вам инстанс, и делайте вы с этим что хотите.
Тьфу.
Так что осознал, да. Синглтоны не то что зло, а большая глупость, имеющая причиной отсутствие дизайна. Десяток синглтонов - и вот вам помойка. В добавок к которой возникает священное знание: чтобы сделать то-то и то-то, надо взять три таких-то синглтона (и передать их друг другу, во).
Так я о чём? Да вот: синглтон класса - это примерно как поименованная общая область. Вот вам имя, вот вам инстанс, и делайте вы с этим что хотите.
Тьфу.
Так что осознал, да. Синглтоны не то что зло, а большая глупость, имеющая причиной отсутствие дизайна. Десяток синглтонов - и вот вам помойка. В добавок к которой возникает священное знание: чтобы сделать то-то и то-то, надо взять три таких-то синглтона (и передать их друг другу, во).
no subject
Date: 2010-02-11 01:11 am (UTC)С такими же минусами и отсутствием плюсов.
no subject
Date: 2010-02-11 02:02 am (UTC)Разговор о том, что синглтоны добавляют неявных зависимостей между модулями, что в дальнейшем мешает развитию/использованию. К примеру, через синглтон реализован интерфейс logger'а ("а, что, удобно, из любого места можно можно информацию вывести"). Позже, когда разным модулям требуется выводить свой лог в _разные_ места, выясняется, что сделать это в нынешнем виде невозможно.
А передавали бы интерфейс -- проблемы бы и не возникло.
no subject
Date: 2010-02-11 02:24 am (UTC)no subject
Date: 2010-02-11 02:38 am (UTC)Вообще, кеширующий контекст - это какие-то странные слова. Но важно-то тут то, что описанною мною ситуация, это не совсем инициализация. Инициализация происходит раньше. То есть объект существует априори в единственном числе.
no subject
Date: 2010-02-11 03:34 am (UTC)GetFileOpenIfClose(int FileNumber)
В парадигме синглтона, это решается заведение синглтона на каждый файл. Код инициализации синглотона также открывает файл. И можно в двух словах объяснить, как кеширующий контекст поможет заменить синглтон?
no subject
Date: 2010-02-11 02:28 pm (UTC)Что такое контекст - читать тут http://members.verizon.net/~babkin/tpopp/05exit.txt , в конце страницы.
no subject
Date: 2010-02-11 03:30 pm (UTC)no subject
Date: 2010-02-11 03:53 pm (UTC)no subject
Date: 2010-02-12 01:27 am (UTC)Контекст же типа мешка. Вначале кто-то создает всякие полезные объекты и кладет их в мешок. После чего ссылка на этот мешок передается везде где нужно, и когда этим прочим местам что-то нужно, они находят готовый объект в этом мешке. Таким образом глобальные переменные оказываются не совсем глобальными, а только в пределах мешка (т.е. контекста).
no subject
Date: 2010-02-11 03:37 am (UTC)GetFileOpenIfClose(int FileNumber)
В парадигме синглтона, это решается заведение синглтона на каждый файл. Код инициализации синглотона также открывает файл. И можно в двух словах объяснить, как передача интерфейса поможет заменить синглтон? Или Вы имеете в виду интерфейс в смысле COM-объектов? Но так ведь там все равно возникает проблема однократной инициализации объекта. Чем это не синглтон.
no subject
Date: 2010-02-11 04:13 am (UTC)Было:
Стало:
no subject
Date: 2010-02-11 04:16 am (UTC)Всё для того же - сэкономить время в будущем.
no subject
Date: 2010-02-11 05:03 am (UTC)Но все равно придется написать:
Или инициализировать OutCoolUtils::Logger глобально.
no subject
Date: 2010-02-11 05:08 am (UTC)no subject
Date: 2010-02-11 02:37 am (UTC)no subject
Date: 2010-02-11 03:15 am (UTC)Так или иначе всегда оказывается какой-нибудь сервис из серии "а вот как бы мне тут получить reference на что-то такое очевидное, но без передачи параметров?"
no subject
Date: 2010-02-11 03:36 am (UTC)no subject
Date: 2010-02-11 09:28 am (UTC)no subject
Date: 2010-02-11 07:06 pm (UTC)no subject
Date: 2010-02-12 05:26 am (UTC)Phemto имеет встроенные классы: Factory (по умолчанию), который всегда создает новый экземпляр объекта, Reused который отдает ссылки на один и тот же экземпляр, и Sessionable, который хранит экземпляр объекта в системной переменной PHP $_SESSION. Они все наследуют от базового абстрактного класса Lifecycle. Разработчики могут расширять эти классы...
http://h-type.com/filez/lj/articles/di/
no subject
Date: 2010-02-11 10:30 pm (UTC)А вообще-то синглтон нужен, скажем, для описания конфигурации. Ну или где у нас логи лежат, такие вещи (тоже конфигурация). В каком-то смысле аспекты? (Могу путать, аспекты не знаю толком.)
no subject
Date: 2010-02-12 12:11 am (UTC)Да, надо сказать, где логи лежат. И так дюжину различных вещей надо сказать. Потом передавать эти штуки друг другу.
no subject
Date: 2010-02-12 05:36 am (UTC)Меня как раз в этом месте и колбасило, я так и пользуюсь несколькими синглтонами -- конфиг, фабрика соединений к БД, Environment (GET, POST, SESSION), но ощущение того, что я в главный контроллер ака точка входа могу запихнуть чтение конфигов а потом все это передавать через DI пришло.
Я инстинктивно боялся методов в т.ч. и конструкторов с большим количеством параметров, а DI как раз поощряет такие списки параметров, поскольку заполняет их автоматически. Таким образом в удобстве по сравнению с синглтонами мы ничего не теряем.
no subject
Date: 2010-02-12 12:39 pm (UTC)Разумеется я читал про DI и про IoC. Но "тащить" подобный контейнер или делать service locator мне не нравится по нескольим причинам.
1. Код становится менее читаемым.
2. Для php нету устоявшейся практики применения IoC и вообще я сомневаюсь, что есть грамотные имплементации. Например порт pico выглядит ужасно, синтаксис конфигурации ужасен.
3. Производительность. Reflection все еще очень медленный на php(в особенности "new" Reflection API).
Мы использовали подход, что все служебные вещи(типа singltone, abstract factory, accert и так далее) это как бы часть языка. У нас был хороший framework, в котором мы все это хорошо реализовали.
Программист, который садился писать приложение, писал его фактически не на php, а на onPHP :-)
То есть если ему нужен был класс, который инстанциируется лишь однажды на все приложение, то он просто наследовался от abstract singleton.
Вы ведь не используете DI для внутренних классов языка или библиотеки.
Конкретно с сессией пример.
Имплементация сессии врядли меняется в php.
То есть вы пишите класс SessionUtils например. Его методы будут обычными врапперами для session_* и все. Считайте этот класс частью языка.
С контроллерами тоже все просто. Если мы говорим про web, то на входе контроллера будет HttpReqeust. Он заполнется глобальными данными из _GET/_POST/_SESSION в Front Controller (если это MVC).
То есть мой поинт в том, что сложные IoC контейнеры и не нужны вовсе.
Для реализации обычно хватает DI через конструктор или сеттер.
no subject
Date: 2010-02-12 12:45 pm (UTC)Практически все аспекты связанные с сущностями и их связями в вашем приложении предлагается описывать с помощью конфигурационных файлов, которые потом использует местный IoC контейнер. Впрочем можно использовать и императивный стиль, вместо конфигов. Не в этом дело. Также используется AOP.
Но в java, с моей точки зрения, этот подход более оправдан, потому что java строится на jcp, а он в свою очередь состоит из небольших спецификаций. И для каждой из них есть по несколько распрастраненных имплементаций. Поэтому здесь нужна максимальная гибкость и слабосвязность компонентов и сервисов.
Но такой подход сложнее.
no subject
Date: 2010-02-12 01:09 pm (UTC)И автор, известный в общем-то -- Маркус Бейкер (aka lastcraft)
no subject
Date: 2010-02-12 01:20 pm (UTC)Но, привеликой разницы, писать ли:
...new Reusable(new Object))...
Object extends Singleton
применительно к топику я не вижу, кроме того, что вторая запись более простая. А в целом да, IoC - это скорее добро.