LINUX.ORG.RU

Зачем нужен синглетрон?

 ,


1

3

Зачем нужен шаблон «проектирования» синглетрон? Почему про него везде пишут, почему я его ни разу не применял? Зачем он нужен, для чего?

class OneInstance{

   static $ya = null; 
    
   static function factory(){
       if(!self::$ya){
            return self::$ya = new self;       
       }else{
           return self::$ya;
       }
   }

}  

★★★★
Ответ на: комментарий от anonymous

Финализация это тоже сахарок. Я к тому, что, да, это хорошо что условность «сюда не лезь» воткнули в ООП (или интерфейсы вот тоже, типа призывают не забыть что-то реализовать), но, свинья найдет грязи и в другом месте. Если бы никто не свинячил, то и говнокода бы не было.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

но, свинья найдет грязи и в другом месте.

Пфф, так сахарок-то он хоть как-то к коду относится. И твой «отнаследуется» тоже. А тут ты говоришь о другом уровне. Так-то обобщенную проблему рукожопости никто не отменял, да. легенда_о_стеклянном_фаллосе.fb2

anonymous
()
Ответ на: комментарий от anonymous

Так это не легенда. Открой любые сорцы, в 99% случаев найдешь осколки ))

А еще бывает так, что апи такие не удобные и нельзя вылепить нужное, оно просто заставляет говнокодить и велосипедить. Например, в культях я столкнулся с хистори, которая не тредсейв и не умеет в трансляцию в языки, ну пришлось писать свой «Q"UndoStack и все обвязки.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Открой любые сорцы, в 99% случаев найдешь осколки

...с обрывками окровавленных бинтов.

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

anonymous
()
Ответ на: комментарий от vinvlad

это зачем же его так передают, если есть механизм прямого доступа?

Затем, что я знаю, что этот объект используется внутру класса/метода, при необходимости я могу подменить его mock объектом при тестировании (вы конечно же можете весь singleton подменить и выкрутится, но проблема остаётся) это всё к вопросу о глобальности и завязанности на одном глобальном состоянии И так, всё началось c

Тот же DI запросто можно использовать в сочетании с синглтоном

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

Lancelot
()
Ответ на: комментарий от anonymous

Глупый чтоль? Любой анонимус — другой.

А ты уверен, что все кто пишут в этом треде - разные люди? :)

anonymous
()
Ответ на: комментарий от anonymous

А ты уверен, что все кто пишут в этом треде - разные люди? :)

конечно разные. анонимусы vs регистранты

anonymous
()
Ответ на: комментарий от anonymous

конечно разные. анонимусы vs регистранты

пока мы все не предоставим паспорта, мы можем быть кем угодно, даже одним и тем же :) логика

anonymous
()
Ответ на: комментарий от anonymous

логика сарказм

не благодари

anonymous
()
Ответ на: комментарий от deep-purple

Например, в культях я столкнулся с хистори, которая не тредсейв и не умеет в трансляцию в языки

Можно поподробнее?

RazrFalcon ★★★★★
()
Ответ на: комментарий от anonymous

Далее. В-самыглавных.

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

Тут и есть подвох, аналоги писать НЕ НАДО! Надо писать хранимые. То есть, всю логику извлечения/сохранения данных вынести на сторону СУБД, благо даже пресловутый mysql уже давно может в хранимые, триггеры и т.п. Более того, если сделать это правильно, то получишь полноценный API, через который эти два модуля преспокойно будут общаться — да-да, модульность, она, родимая.

Если выбрана конкретная СУБД-шка (как я изначально формулировал), то полностью согласен - оптимальнее и логичнее максимум SQL-кода вынести в хранимые процедуры и не городить лишних промежуточных уровней внутри модели. Помимо всего прочего мы тогда получаем повышение производительности работы БД.

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

Дальнейшие мои рассуждения - это ответ на критику из разряда «и рыбку съесть и всё остальное...» )) : и чтобы всё быстро и оптимально пахало, и чтобы не переплачивать за сервера, и чтобы все автоматом, без доработки кода, перескакивало на СУБД других производителей. Я в такие чудеса не верю, но в порядке общего трепа попытался пофантазировать и на эту тему... ))

Если вкратце: cпроектированная «ручками» схема БД, код SQL-запросов (в том числе хранимые процедуры, триггера и пр.) являются неотъемлемыми частями исходного кода проекта. Попытка автоматической генерации этой части исходников с помощью ORM - это зло.

vinvlad ★★
()
Ответ на: комментарий от Serg_HIS

я могу такой код написать с такими гибкостями и раздольями, что докажу другим, что смогу яички(ногу) себе отстрелить наспор

Если задача требует стрелять себе в яички(ногу), а язык не даёт — нафиг такой язык?

bodqhrohro_promo
()
Ответ на: комментарий от Lancelot

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

Да в общем-то, я не настаиваю на его обязательном применении - это дело вкуса и степени личного перфекционизма. К примеру, в YII2 класс связи c БД - не синглтон. Запросто можно создать несколько отдельных экземпляров. Но поскольку на практике нужно только одно соединение, то имеется механизм создания такого объекта по первому требованию и последующего глобального доступа к нему c помощью свойства Yii::$app->db

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

vinvlad ★★
()
Ответ на: комментарий от bodqhrohro_promo

Паспорта тоже подделать можно, что за стереотипы об идентификации человека через паспорт?

это фольклор

anonymous
()
Ответ на: комментарий от anonymous

В фольклоре ещё справка от христианского священника была, но её почему-то не вспоминают.

bodqhrohro_promo
()

Он нужен в яве когда нельзя делать функции без класса.
А так же необходим для интеграции с нативным кодом, который подразумевает 1 инстанс. А ещё он нужен когда много синглтонов пронаследовано от одного класса. Например, диалог настроек в приложении может быть только один, но он пронаследован от диалога, а их может быть много

mittorn ★★★★★
()
Последнее исправление: mittorn (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

1) Не тредсейф.

https://code.woboq.org/qt5/qtbase/src/widgets/util/qundoview.cpp.html#59

Модель юзает этот стек, а вьюха юзает эту модель, в стек добавляются объекты команд, которые манипулируют объектами данных, которые могут отображать свои состояния в других вьюхах. Проблема в том, что на стек оно лезет напрямую, плюс сигналы меж моделью и вьюхой тоже. Невозможно сделать так, чтобы: а) полезная работа не фризила гуй, б) полезная работа не играла в рейс кондишн с кликами на вьюхе истории.

2) Не умеет в транслейт.

Даже если эту проблему окостылить через «поймать QEvent::LanguageChange там где это можно, пройтись в цикле по командам истории и обновить тексты» — первый пункт все еще остался бы не решенным.

deep-purple ★★★★★
()
Ответ на: комментарий от bodqhrohro_promo

Я именно про это и написал.

Если язык даёт делать всё что угодно - это хороший язык. Плохой программист врядли знает про то, как это сделать (всё что угодно).

Например тот же reflection в java - весьма полезная и интересная штука, но на практике её использует очень не многие либо там где это совершенно бессмысленно (просто выпендриваются). У меня было несколько однотипных проектов в которых именно паттерн «как любят говорить» проектирования моей архитектуры был запилен именно на нём, что удешевило/ускорило расширяемость проекта в десятки раз практически без переделок ядра.

Serg_HIS
()
Ответ на: комментарий от Serg_HIS

Проблема в том, что рефлексия, по сути — побочная штука, которой могло бы не быть. Её начали использовать не по назначению, потому что другого способа не оказалось. И таких примеров масса — API для интерактивных обучалок в Win32, который начали использовать для управления чужими окнами, хищения курсора и всякого прочего, потому что WinAPI не предоставлял для этого прямых средств; a11y в Android, которую используют для подстановки паролей, определения запущенных приложений, отображения экранной клавиатуры и т. п.; локалки через электросеть в зданиях, где сложно проложить ещё проводку.

Есть вещи, которым так не повезло, и обходных путей нету. Далеко ходить не надо, взять хоть переопределение операторов в Java. Разработчики стандарта сказали «ненужно» — обмазывайтесь методами на каждый чих. Или отсутствие беззнаковых типов, хоть это и не столь большая проблема, их можно эмулировать.

bodqhrohro_promo
()
Ответ на: комментарий от bodqhrohro_promo

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

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

Да и могли бы уже сделать Parallel_For удобный как в C++, а не заставлять изворачиваться с Stream Servers. Хоть сам садись да пиши пародию на этот Фор. К стати вот продумываю свой вариант реализации.

Serg_HIS
()
Ответ на: комментарий от vinvlad

(как я изначально формулировал)

Да, именно по твоим вводным. И чтоб два раза не вставать — да, согласно им же — «ORM - это зло».

Просто в конкретном проекте могут быть компромиссы, порождаемые

Это понятно, и даже местами правильно. Однако решение «прыгнуть до середины» при принятии такого уровня решений — это не компромисс. Это... См. кирпич ниже. Короче — это фиаско.

...Есть такое совершенно удивительное транспортное средство, «ишак-арба» называется. Проверенное временем (c). И тут возникает «свежая мысль» — а давайте установим на нее моторчик! Ура! Встречай нас новый дивный мир!

Подвох в том, что если убрать ишака, она завалится. Ну, то есть, «прыгнуть до середины» в данном случае — это моточик поставить «чтоб бежало», но ишака оставить «чтоб не падало». В итоге, либо ишак таскает висящий мертвым грузом моторчик, либо моторчик включается и ушатывает арбу, груз, ишака, его водителя, подвернувшихся непричастных и моторчик.

А дальше еще интереснее — следующая итерация «апгрейда»! Которая с вероятностью в 200% пойдет не по пути №1 «заменить ишака самобеглой подпоркой» (поскольку это «слишком сложно», и «слишком кардинально, только ведь что кардинально впилили моторчик, зокащщик низоплотить-нипаймет кардинально», и вообще «ты что, хочешь сказать, мы ща вот только что по крупному накосячили?» со всеми вытекающими). А пойдет по пути №2 «разработать и внедрить систему согласованного взаимодействия ишака с моторчиком во избежании [и далее по тексту]» (поскольку «ну мы же тут ща по-быстрому, чо тут делать-то?!» и «объявим фичей, рубанем бабла влегкую»).

И вот уже на этом пути №2 расстилается перед нами бескрайний зовущий простор. «Ну что тут может пойти не так?» Можно поупражняться в подсчете вариантов. Например, источником управляющего сигнала выбрать ишака или моторчик? (датчик скорости мы с негодованием отметем по причинам п.№1). На самом деле, первое, и возможно единственное, что будет реализовано, причем действительно быстро и дешево, так это «моторчик тарахтит, но колеса не крутятся, движение осуществляется посредством опи@#дюливания ишака». С ненулевой вероятностью дальше креативное бессознательное покатится в направлении создания автоматического опи@#дюлятора с приводом от моторчика...

Уфф, нехило анонимуса бомбануло, ну извини. Конечно, это всего лишь беллетристика (уточнение для любителей «подловить» на доказательстве по аналогии, им, понимаешь, кругом аналогии видятся).

Ладно, далее серьезно. Раз уж опять пошла тема получаемых приемуществ.

anonymous
()
Ответ на: комментарий от vinvlad

Ладно, далее серьезно. Раз уж опять пошла тема получаемых приемуществ.

оптимальнее и логичнее максимум SQL-кода вынести в хранимые процедуры и не городить лишних промежуточных уровней внутри модели. Помимо всего прочего мы тогда получаем повышение производительности работы БД.

По этому тексту у кого-то может сложится мнение, что упомянутое «все прочее» ограничивается лишь упрощением модели, пусть и существенным. Но это не так.

Будем счить, что все делается правильно, и на стороне СУБД у нас организовался вполне приличный API, хорошо задокументированный при этом.

Это означает изменение структуры приложения. Теперь есть (условно) модуль PHP и модуль SQL взаимодействующие по API.

Выше по ходу дискуссии было два похожих вопроса: изменения в модели и изменить (сменить) СУБД. Теперь ответ очевиден: вплоть до замены модуля, при условии реализации API, разумеется.

Кроме того, модули проявляют свою специализацию. Назначение отдельного специалиста на SQL модуль — его объем теперь позволяет ставить полноценные задачи — повысит эффективность оптимизаций и качество модуля в целом. Пхп-шник же сосредоточится на своих задачах.

Итог: даже на таком простом примере видно, как законченное решение, в отличии от половинчатого, открывает возможности по оптимизации (способность к изменению и адаптации тоже тут) системы на всех, практически, уровнях от «железа» до маркетинга: запросы ускорили, код моделей упростили, в архитектуре связанность лишнюю убрали, деплой облегчили, работу реорганизовали, продажник с ПМом закрылись в переговорке — пишут ТЗ переноса «ПХП модуля» на айфончик.

anonymous
()
Ответ на: комментарий от Serg_HIS

Ну взять, например, использование рефлексии для доступа к приватным свойствам. Во многих языках понятия приватных свойств нету, вместо них используется конвенция: свойства и методы, у которых имена начинаются с андерскора, внутренние: трогать их не стоит, но если очень надо, то можно. Можно пойти дальше и сделать реализацию на уровне языка, что-то типа friend-функций в C++, только наоборот, или mut/unsafe в Rust: без явно прописанного модификатора доступа ты доступа к приватным свойствам не получаешь, с ним получаешь; по использованию такого модификатора явно видно участки кода, где что-то может сломаться от влезания в чужой объект с потенциально изменившейся внутренней логикой.

bodqhrohro_promo
()
Ответ на: комментарий от bodqhrohro_promo

в языках тоже есть архитектурные проблемы

Я бы обобщил так: во всём что делают люди - есть проблемы. Это факт.

Serg_HIS
()
Ответ на: комментарий от bodqhrohro_promo

Во многих языках понятия приватных свойств нету, вместо них используется конвенция: свойства и методы, у которых имена начинаются с андерскора, внутренние: трогать их не стоит, но если очень надо, то можно

Именно для этого в Java и приняты геттеры и сеттеры.

Но если челу очень надо без них - да пожалуйста! :) (но он ведь сам дурак раз не понимает зачем есть get, set и is)

Тут проблема в головах а не в языке.

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

Есть принятые правила (этикет программирования так сказать), но ведь можно и на банкетный стол поставить унитаз и сказать «если дамы не против...» (с) Ржевский

Serg_HIS
()
Ответ на: комментарий от bodqhrohro_promo

На счёт культуры программирования:

Вот например очень давно. Ещё в институте. Помогал одному своему товарищу/соученику по группе, писать курсовую по программированию.

Он писал совсем простую прогу. Я как-то пришёл к нему в общежитие и ради забавы попросил её мне скопировать.

Он писал игру «Змейка». Да в текстовом режиме 40 символов в ширину.

У него тогда была мегакрутая на те времена «тачка» с процом 486dx2/120 которая обгоняла первые пни 90-100МГц. У него его вариант змейки «летал». Когда я пришёл к себе домой на «тачку» «Поиск 1», у меня после того как змейка становилась длиннее нескольких десятков символов начинала дико тормозить...

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

Ну я пока сидел дома и причёсывал прогу, чтобы она на моей «тачке» тоже «летала» и притом с такой же скорость как и на любой тачке мощнее моей. Причесал по скорости, добавил еще пару(один :)) режимов разрешения экрана, сделал режим паузы и запилил в нём примтивный синтезатор чтобы можно было что-то попиликать, сохарнение результатов, запилил чит бессмертия ну и т.п.

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

А баг был в том, что у меня было две глобальных переменных; «X1» и «1X» которые отвечали за разные вещи. После двух дней мучений с отладкой я таки понял, что нужно называть переменные длинными понятными именами.

PS. Да это было очень давно.

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

PPPS. Параллельно я написал свою курсовую. Это была совсем не «Змейка».

Serg_HIS
()
Ответ на: комментарий от Serg_HIS

добавил еще пару(один :)) режимов разрешения экрана

Гы только что запустил в досбоксе - таки да 3 режима разрешения экрана :)

Serg_HIS
()
Ответ на: комментарий от bodqhrohro_promo

Согласен.

У меня сейчас большая проблема придумывать названия пакетам, функциям и переменным.

Многие этого не понимают но порой сидишь и минут по 10 если не больше бьёшься об стол головой пока что нибудь приемлемое проявится.

Хотя там ту функцию зафигачить минут 5. Дольше на выдумывание названий выходит.

А если сразу не придумаешь нормально то так и будет как у большинства... foo1, foo2, ... (Папка 1, Папка 2, ...) :)

А потом через месяц сиди и вспоминай что это...

Serg_HIS
()
Ответ на: комментарий от bodqhrohro_promo

Вот например сейчас для своего движка для пиления прог на андроиде продумываю конструктор меню.

И вот трабл. Не могу придумать как назвать функции по конструированию меню и уничтожению собраных конструкций.

Constructor и Destructor?

Assembler и Disassembler?

как-то всё не так... А может просто у меня отторжение этих слов как забитые по умолчанию в области программирования в разных языках и даже названия языков и программ.

Serg_HIS
()
Ответ на: комментарий от Serg_HIS

Ящитаю, в таких случаях надо сначала как-нибудь назвать, а после реализации переименовать. А то пока будешь биться — идея реализации из головы вылетит. Главное — не забивать на это вообще, как делает «большинство» :-)

bodqhrohro_promo
()
Ответ на: комментарий от Serg_HIS

Что за фигня, «producer» конечно. На ещё «fabricator» и «erector».

anonymous
()
Ответ на: комментарий от RazrFalcon

1) Да. И? Каким боком к гую относится QUndoStack? Никаким, но юзается моделькой вьюхи напрямую, т.е. по факту вьюхой напрямую. Палец вверх, чо.

2) QUndoCommand, QUndoStack и модель вьюхи не умеют в tr(), умеет только вьюха, и да, мне нужен динамический.

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Сами создаёте себе проблемы - сами их героически решаете.

В динамические переводы вообще никто не умеет. Можно даже не пытаться.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

создаёте себе проблемы

Так, стоп. Почему использование отдельного (от гуя) треда для обработки задач — есть создание проблемы?

динамические переводы вообще никто не умеет. Можно даже не пытаться.

Тогда что это: http://dropmefiles.com/4f69I

deep-purple ★★★★★
()
Ответ на: комментарий от anonymous

Будем считать, что все делается правильно, и на стороне СУБД у нас организовался вполне приличный API, хорошо задокументированный при этом.
Это означает изменение структуры приложения. Теперь есть (условно) модуль PHP и модуль SQL взаимодействующие по API.
Выше по ходу дискуссии было два похожих вопроса: изменения в модели и изменить (сменить) СУБД. Теперь ответ очевиден: вплоть до замены модуля, при условии реализации API, разумеется.

Кроме того, модули проявляют свою специализацию. Назначение отдельного специалиста на SQL модуль — его объем теперь позволяет ставить полноценные задачи — повысит эффективность оптимизаций и качество модуля в целом. Пхп-шник же сосредоточится на своих задачах.

Итог: …

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

… продажник с ПМом закрылись в переговорке — пишут ТЗ переноса «ПХП модуля» на айфончик.

Ну и если уж затронута тема модульности, то можно пару слов сказать о той части, которая поближе к конечным пользователям. Условный «ПХП модуль» во многих случаях можно разбить на два модуля: UI модуль и Серверный модуль бизнесс-логики. А между ними - тоже хорошо задокументированная API-шка (типа REST).

Реализация UI модуля может изначально подразумевать несколько вариантов: веб-приложение и нативные мобильные приложения. Надо сказать, что веб-обозреватели становятся вполне себе полноценными тонкими клиентами - появляется поддержка всяких полезные внутренних сервисов. Так что, в некоторых случаях достаточно будет веб-приложения (или начинать с него).

Что касается Серверного модуля - если уж «считать, что все делается правильно», - то его, конечно, нужно реализовывать не на PHP. Здесь нужен хороший FastCGI-сервер, стоящий за NGINX, с возможностями асинхронного программирования или с «зелёными» потоками, оптимизированными под работу с сокетами. Какой-нибудь Golang здесь гораздо более подходит. Тогда единственным реальным узким местом будет работа с БД.

Вот как-то так...

vinvlad ★★
()

Фигасе тут нафлудили.

Зачем он нужен, для чего?

Для того чтобы иметь глобальную сущность с контролем доступа. Фишка в том, что глобальную переменную ты можешь поменять в любом месте своего кода, просто $var = 'fck', а вот синглтон так просто не сломаешь, т.к. OneInstance::factory() = 'fck' пошлёт тебя лесом. Состояние синглтона можно менять (если вообще можно) только через методы, т.е. контролируемо.

почему я его ни разу не применял?

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

no-such-file ★★★★★
()
Ответ на: комментарий от Lancelot

кто угодно может поменять его состояние в любой точке программы, он завистит от последовательности обращений к нему (если не readonly)

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

no-such-file ★★★★★
()
Ответ на: комментарий от vinvlad

имеется механизм создания такого объекта по первому требованию и последующего глобального доступа к нему c помощью свойства Yii::$app->db

Но это именно механизм DI, а не синглтона. В качестве примитивного синглтона можно рассматривать сам класс Yii.

no-such-file ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.