Pull to refresh

Comments 33

Вот мой вариант синглтона на Objective-C, который использует по минимуму имя класса: https://gist.github.com/virasio/9941612 И ещё я запрещаю alloc и new.

Да, так определенно лучше. Кстати насчет alloc: если запретить alloc, то запрещать init еще есть смысл или можно тогда этого не делать?

Вы заставили меня задуматься. :) Похоже, что реально в таком случае init уже не нужно запрещать. Но нужно будет обдумать этот вопрос ещё раз на свежую голову.
Обоих языков не знаю, так что больно не бейте. Но возник вопрос — а как на счет клонирования?
UFO just landed and posted this here

Я думаю, что нужно это вопрос переадресовать Apple насчет UIApplication и NSUserDefaults. :)

Библиотеки взаимодействующие с некоторыми системными объектами необходимо реализовывать как синглтон. Обычно это какие-нибудь элементы управления системы: элементы управления плейером на «шторке» в iOS; «лоадер» в верхней инфо-полоске, keychain и т.п. Хотя можно разрешить юзеру создать два объекта, но смысла в этом нет, если они будут в итоге взаимосвязаны через системный объект. Нужно дать понять пользователю библиотеки что реально объект всего один, и не нужно пытаться с ним извращаться.
UFO just landed and posted this here
Не «библиотека-синглтонов», а «синглтоны полезны в системных библиотеках, чтобы дать пользователю библиотеки понять, что в системе этот объект единственный». Если разработчик не понимает, что объект всего один, то он может, например, попытаться взять «контакты», создать копию объекта и пытаться её использовать для отката состояния. Можно придумать ещё множество подобных примеров. Учтите, что есть люди, которые учатся программировать сразу под iOS, например. А есть более сложные примеры объектов, которые должны быть единственными. Естественно этот паттерн очень хитрый, и его нельзя использовать везде где хочется. Но когда ты пишешь библиотеку для разработчиков с неизвестным уровнем квалификации, то иногда нужно.
UFO just landed and posted this here
«Должен отвечать DI» — значит отвечать придётся программисту, а смысл в том, чтобы по возможности не дать ему ошибиться. В конце концов, можно и синглтон инжектить если уж так хочется, чем он вам мешает?
Вообще все антипатерны — это использование инструментов не по назначению. Вот допустим есть, топор для рубки дров, но им можно легко оттяпать свою же ногу -> топор стал антитопором. Берем отвертку хренакс она в глазу по ручку, хотя из начально разрабатывалась винтики крутить -> отвертка стала антиотверткой. Берем синглтон и сохраняемся в него из разных тредов -> синглетон стал антипатерном.

Ну и с другой стороны есть у Вас база данных, что вы на каждый запрос свою копию sql порождаете?
от сюда могу сделать вывод, что антипатерны появились благодаря кривым ручкам, которые не научились ими пользоваться. Это как тушить пожар бензином на космической станции наполненной чистым кислородом.
Я вот сам ООП до конца не понимаю, и считаю что ООП это сплошной антипатерн в FP.
Хотя есть друзья которые умеют Scala и я на них смотрю с белой завистью.

Да ладно, идите объясните Дейкстре, что goto это нормально [1] и он просто не умеет его готовить, потом расскажите сэру Tony Hoare что null ссылки это ок [2], ну а под конец поведайте Erich Gamma и Ralph Johnson, что они заблуждаются называя синглтон своей ошибкой [3][4].


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


[1] http://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf
[2] https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare
[3] http://www.informit.com/articles/article.aspx?p=1404056
[4] https://twitter.com/daverooneyca/status/529799186795884544

Вот Вы только подтверждаете мои слова. Давайте ПО для спутников писать на Flash и потом статьи что Flash антипатер и мертвая технология? ;)

Попытаюсь перефразировать. Инженер как и любой другой человек подвержен заблуждениям и предрассудокам из-за которых сложно трезво оценивать технологии. Если мы всю жизнь использовали goto, то нам сложно признать что это было ошибкой. Такой эффект известен в психологии как эскалация обязательств [1].


Вопрос в том, как замечать такое поведение и избегать его. Хороший подход — смотреть за авторами технологий и гигантами индустрии. Если изобртатель технологии смог перешагнуть через свою гордость и признать ошибку, то вероятно что-то дейсвительно с ней не так. Ссылки выше были как раз про это. Tony Hoare придумал null ссылки, Erich Gamma и Ralph Johnson — синглтоны.


Я согласен, что каждому инструменту — свое назначение, просто назначение некоторых инструментов — отправиться на свалку истории :)


Забавно что вы упоминули спутники, вот тут [2] пишут что там как раз используют наработки сэра Tony Hoare и наисвежайшие идеи, такие как TLA+. В общем, не держитесь за то, что уже доказало свою несостоятельность.


[1] https://en.wikipedia.org/wiki/Escalation_of_commitment
[2] http://www.altreonic.com/content/main-mission-rosettas-philae-lander-accomplished

Дак да, я полностью с этим согласен, я пытаюсь донести мысль о том, что синглетон меня ни разу не подвел при создании ТОДО приложения ;) И я хорошо понимаю какое зло синглетон при подсчетах бухгалтерии в многопоточности.

p.s. за ссылки спасибо.
В каждой коммерческой программе сданной вовремя есть свой «GOTO», в том смысле что без технического долга невозможно писать экономически обоснованные крупные программы. Важно чтобы этого долга было мало. Но это уже вопрос уместности.
UFO just landed and posted this here
>Что в данном случае означает «копия SQL»?
ну я имею введу базу данных, на каждый запрос отдельно файл целый. Кстати идея очень хорошая. в Erlang гдето используют похожий подход.

>Scala один из самых мощных функциональных языков современности.
Которая умеет ООП ;)
А DI у вас как реализован? Даже если у нас зависимости вызываются из прикладного объекта напрямую, то есть общее место где оно хранится, и это или статика, или синглтон (который тоже под собой подразумевает статику, но не суть).
Статику сложнее тестировать, поэтому синглтон в этом плане лучше.
Поэтому СервисЛокатор лучше таки делать синглтоном.
Если приложение небольшое, у нас буквально один или два класса-одиночки. Городить DI особо смысла нет. Ну или нужна пачка одиночек в рамках отдельной подкомпоненты, и не хочется их держать в общем стеке. Тут тоже можно или пачку одиночек, или отдельный сервисЛокатор. По ситуации.
Так то я соглашусь что в реальном проекте оно нужно не часто, но это же классика.
У меня лично синглтон один — СервисЛокатор).
Ой, ну что тут сказать — синглатон на обжектив-си, как правило далеко не синглотон, особенности языка таковы что если очень захотеть — можно создать другой объект, разве что alloc/init выбросить из класса после первого вызова. Так что с недоступным инитом могли не заморачиваться.
s_suhanov, нет, тут Psionic немного о другом говорит, как я понимаю. Objective-C в рантейме позволяет что только не творить, и подобный запрет не гарантирует полной недоступности методов. И при этом можно просто удалить из объекта класса (как я понимаю) методы alloc и init (и initPrivate), после того как первый объект был создан. Вот быстренько нашел немного про рантайм: https://habrahabr.ru/post/177421/
Кстати, ещё есть allocWithZone, например, который и я не запретил.
Для Psionic хочу заметить только то, что паттерны используются не для того чтобы что-то уж совсем так перекрыть со всех сторон, а просто для того, чтобы другой разработчик понимал что же тут было задумано. Если ему хочется головной боли, то пусть лезет в рантайм, но описание класса как синглтона должно дать понять разработчику-пользователю библиотеки, что автор библиотеки не предполагал создания нескольких объектов, и не стоит потом ему предъявлять претензии. Образно говоря: автор библиотеки пистолет поставил на предохранитель, но пользователь может снять с предохранителя и всё же отстрелить себе мешающую ногу. :)
И я не придумал лучшего способа, чем взять книгу «Паттерны проектирования» Эрика и Элизабет Фримен, и написать примеры каждого паттерна на Objective-C и Swift.

Плохая идея. Паттерны, это не про реализацию набора правил, это про применение этого набора правил в подходящем для этого месте. Хотя, может и нужно пройти такого рода эволюцию:
1) паттерн головного мозга — это когда только прочитал про них и везде, чаще не к месту, применяешь их;
2) просветление — это когда реально познал дзен и можешь аргументированно рассказать почему в этом месте нужен именно этот паттерн, а при немного других вводных при той же функциональности уже нет.

Ну и да, антипаттерн — это не про тот или иной конкретный паттерн, а про неправельное его применение.
О этот комент, надо распечатать и в кабинете повесить!
private(set) empty = true
private(set) boiled = false

// И getter'ы убрать

По'swift'ее будет вроде как.
По'swift'ее будет и так:

class MyClass: {
    static let shared = MyClass()
}

На всякий случай повторю концовку поста. :)


// Swift
class Singleton {

    static let shared = Singleton()

    private init() {}

}
Спасибо за
private init()
, забыл «маленькую» деталь.

А почему не вставить в тело поста короткий код? Почему только в конце?

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

Если не требуется изменять или проверять property на что-то, то в Objective-C можно писать вот-так:
@property (assign, nonatomic, getter=isEmpty) BOOL empty;
@property (assign, nonatomic, getter=isBoiled) BOOL boiled;

и тогда не нужно реализовывать гетеры

Да, так удобнее и правильнее.

Sign up to leave a comment.

Articles