Комментарии 79
Все ругают goto и «знают», что оно плохо, но почти никто не ругает break/continue, хотя это то же goto. Такое расслоение как раз из-а того, что goto в некоторых языках позволяет входить внутрь конструкций. Реинкарнации в современных языках такого не позволяют.
Что касается структурного программирования, то проблема вовсе не в том, что людям в суть не хочется вникать, а в том, что оно попросту неудобно. Просовывать всюду кучу флагов для прерывания всех циклов вверх по уровням абстракций — это очень неудобно. И если с отсутствием break/continue современный программист ещё смирится, то с отсутствием исключений (которые суть те же навороченные goto) — точно нет.
При структурном программировании совсем не обязательно просовывать кучу флагов, если этого не требует сама задача. Речь об этом и неудобстве подтверждает то, что я сказал ранее — большинству людей не хочется вникать в суть.
С исключениями тоже интересно, учитывая тенденции новых языков. В Go избыточное использование исключений сделали неудобным, поэтому даже не все знают, что там они есть, а в Rust исключений нет вовсе. Со Swift ещё не разобрался, но, похоже, его разработчики тоже пытаются найти что-то своё. Всё быстро меняется и Ваше понятие о современном программисте могло и устареть, не говоря о том, сколько современных программистов используют С. Думаете, они поголовно мучаются без исключений?
При структурном программировании совсем не обязательно просовывать кучу флагов, если этого не требует сама задача. Речь об этом и неудобстве подтверждает то, что я сказал ранее — большинству людей не хочется вникать в суть.Напишите статью на эту тему, раз так, общественность скажет «спасибо»! Меня структурному программированию учили в КГУ (ныне КФУ), вдруг незабвенный Самитов, который это преподавал о чём-то нам не рассказал.
В Go избыточное использование исключений сделали неудобным, поэтому даже не все знают, что там они есть.Нигде не видел, чтобы авторы языка рассказывали о таком, на мой взгляд, они просто не очень-то продумали этот момент.
Всё быстро меняется и Ваше понятие о современном программисте могло и устареть, не говоря о том, сколько современных программистов используют С. Думаете, они поголовно мучаются без исключений?Собственно результат их мучений — язык Си++.
Напишите статью на эту тему, раз так, общественность скажет «спасибо»!
К сожалению, мои наблюдения говорят об обратном. Легко можно получить тонну ненависти.
вдруг незабвенный Самитов, который это преподавал о чём-то нам не рассказал
А в каком виде он это рассказывал -«оно есть, но неудобно»?
Собственно результат их мучений — язык Си++
То есть, они все перешли на C++? Вроде бы нет же, не переходят. Зачем они «мучаются»?
К сожалению, мои наблюдения говорят об обратном. Легко можно получить тонну ненависти.Ну а как можно продолжать этот разговор, если непонятно что вы имеете ввиду?
А в каком виде он это рассказывал — «оно есть, но неудобно»?У меня в дипломе записано, что я «математик-системный программист», нас учили программировать, структурному программированию тоже учили, естественно, как без этого?
То есть, они все перешли на Cи++? Вроде бы нет же, не переходятСобственно, я сам пишу на Си, а на Си++ не пишу и не собираюсь, это долгий вопрос почему, об него сломано много копий — есть множество статей на эту тему, почему Си++ всё же не торт. А вот на Гоу, например, я программирую охотнее, чем на Си. Хотя всё, что хочется на нём не напишешь.
О том, что break и continue — это частные случаи goto знают не только избранные, и ругают точно также как и goto.Беглый поиск по «Хабру» не подтверждает вашу точку зрения. goto не ругает только ленивый, break/continue вспоминают значительно реже.
Масштабы трагедии обычно в том, что из-за синглтонов возникает жесткая связанность компонентов. Как следствие — невозможность нормально всё это дело тестировать.
А зачем явно указывать scope? Controller же по умолчанию имеет scope Singleton.
А еще у нас есть очень специальный человек, Егор Бугаенко, у него свой подход, и даже книжка имеется: http://www.yegor256.com/elegant-objects.html
читаемость де-факто нулевая, но зато не магия.
Один из основных принципов Spring'а: "Convention over Configuration". Т.е. чтобы разработчикам нужно было делать как можно меньше однообразных действий, спринг практически для всего делает "дефолтную" конфигурацию.
Я думаю они просто решили сделать синглтон скоуп, потому что он лучше всего подходит под эту философию.
Автор не Controller, а Component приводит в статье. Но, думаю, это не особо критично в данном контексте, просто оставил комментарий, потому что автор попросил :)
Получается, что мощным оружием синглтон становится, если только «спрятан» в IoC. Иначе — жесткая связанность. Да и что в нём такого мощного? :)
Если использовать DI контейнер, то объект и не узнает, что он является синглтоном.
Об этом вообще никто не узнает кроме контейнера.
Возможно, я немного из другого поколения, но видео мне кажется просто невероятно растянутым. 17 минут для меня очень долго, да и суть можно было бы уложить в куда более мелкий формат. Для лайв-стрима, может быть, было приемлемо, но для видео с возможностью редактирования, обрезки и монтажа я считаю 17 минут слишком большим количеством времени. Возможно, имело бы смысл написать статью и зачитать ее — тогда было бы меньше моментов, когда начинаете подбирать слова и получаются «эээ» и «ммм».
В целом весьма интересно смотреть, и я с радостью посмотрел бы другие видео, если они будут покороче :)
На скорости 1.5х нормально было смотреть.
Это типичная проблема технодокладов — ты начинаешь рассказывать какую-то элементарщину на 5 минут, но пара иллюстраций — и он еле упихивается в стандартные 50 минут, причем выбросить что-то затруднительно.
Да, в следующий раз я постараюсь формулировать точнее. Можно считать это частью continuous improvement — каждый пост должен учитывать (или хотя бы пытаться учитывать) ошибки предыдущего. Именно поэтому так важен живой фидбек — нет фидбека, нет повышения качества.
Плюс, как уже заметил автор, какие-нибудь «хранители подключения к базе» или другому ресурсу вполне могут быть синглтонами. Только непонятно зачем там instance как таковой, если можно сделать статический класс со своим методом init() или load(), запускаемым при старте приложения.
Я к чему весь этот базар-вокзал развел, к тому что я, как раз тот кто начинает постигать великий и могучий Java и я вот только и вижу, что все хают синглтон, но никто не дает реальные примеры как быть без него. Не используй и все тут, а неопытному уму и не вдомек, а как же, вот у нас есть и в Collections.singletonList
и что, его не использовать теперь? А оказывается, это не тот самы синглтон, что из GoF, а совсем иной.
Собственно и хочу, что бы один раз вразумили, что синглтон это все же не плохо, просто исторически так сложилось…
Использовать инъекцию зависимости вместо прибивания её гвоздями.
Что посоветуете делать, чтоб и протестировать, и синглтон заюзать?
Не совсем понятно, как это поможет избавиться от захардкорженных зависимостей. Если честно, я не умею Java, можно пример?)
Да моя позиция видимо такая же как и ваша все способы хороши. Чтобы не хардокодить можете сделать синглетон с тем парметром который иначе пришлось бы хардкодить, можете передавать параметр по стеку до всех мест использования, можете создать врап-функции (такие врапы будут на каждом вызове или по разу лезь за параметром в конфигурацию), а можете сгенерировать такой врап и выставить ее синглетоном в глобальной области видимости. Никакой разницы.
Проще всего, мне кажется, использовать DI-контейнер.
Не всегда проще но никогда не просто.
1) Ломается стройность API. Видно на пример EF Core. Вместо того чтобы создать контекст и передать в конструктор параметры. Создаешь контекст, достаешь контейнер и параметры пихаешь в контейнер. Хорошо когда есть и контйнер и конструктор (передача по стеку). А значит не просто.
2) Бардак вылезает из других мест, начинаются всякие per thread, xml configuration. И дебаг значительнос сложнее.
Я использую и IoC контейнер (получить конфиграцию в «юзер коде», но это может быть просто функция `Resolve` передаваемая по стеку).
И когда удобней переменная в глобальной области видимости, это значит что удобней переменная в глобальной области видимости. Никто не передает Math.Round через DI.
Иии у Роберта Мартина есть на это готовый ответ :) .
Если ситуация не знакома и вычурна разирсую: функция может быть сложнее, например сериализации (не потоковая, а именно конструируется проход по полям так что сериализация вообще без reflection, так быстрее потоковой на процентов 50-20)? Почему рантайм а не сохранить сгенерированную функцию в файл? Не надо управлять кодом.
public class Something {
private Something() {}
private static class LazyHolder {
static final Something INSTANCE = new Something();
}
public static Something getInstance() {
return LazyHolder.INSTANCE;
}
}
https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
Как эта реализация решает проблему сильной связанности?
Эта реализация дает то что описано в заголовке Специфика Java.
Она простая понятная и совершенно ленивая.
Проблема сильной связанности решается использованием интерфейсов и передачей зависимостей через конструктор, что позволит и тесты написать и использовать разные реализации.
Вот хорошая статья здесь на хабре как раз по этому поводу https://habrahabr.ru/post/334636/
public final class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
Singleton pattern
и больше никакова :)
А есть объект синглтон (по нашему одиночка), то есть один объект в системе, но при этом не обязательно чтобы он был создан с помощью паттерна Singleton.
То что вы называете синглтоном курильщика это скорей реализация паттерна dependency injection. Поэтому вопрос синглтонов, но объектов да решен, паттерн DI решает проблемы которые создает паттерн Singleton, при этом дает вам возможность иметь один инстанс объекта в системе, если это нужно. При этом паттерн Singleton лучше не использовать.
Я пользуюсь синглтонами. Но чтобы ограничить скоуп, я назначаю ссылку на instance в конструкторе самого синглтона, а сам синглтон создаю где-то в мэйне. Это даёт 1) возможность управлять порядком инициализации синглтонов, в том числе если какие-то из них вдруг зависят друг от друга. 2) возможность управлять порядком их разрушения (полезно например в С++), ну и 3) стандартная возможность синглтонов — доступ из любого места кода.
Иными словами синглтон не создаётся по запросу instance, а создаётся как обычный объект, разница только в том что создаться может лишь один экземпляр, и доступ к нему может быть отовсюду.
Создавать этот паттерн надо так, что он был мокующимся (инъекции и т.д.)
То что некоторые пихают в эти объекты состояния — это проблема исключительно этих персон и не дай им сделать это, они найдут другой способ отстрелить себе ногу.
Синглтон если уж и делать, то как раз для stateful объекта, чтобы везде был доступен один и тот же объект с одним и тем же состоянием.
заведите себе статический util класс с этими методами
В теории, конечно, статический метод можно превратить в компаратор ссылкой на этот метод, но компаратор — это ведь далеко не единственное, что не имеет состояния. Например стратегии часто не имеют состояния, их вы тоже будете статическими методами делать?
А вот что касается синглтона с состоянием, то я совсем перестал их использовать. Только иногда
ThredLocal
и то, по возможности стараюсь избегать.Не всегда. статик Util класс не так просто "замокать" как синглтон.
Удар по перфомансу от синглтона-бина небольшой, бОльшая часть этого удара случается при поднятии контекста(старте аппликейшена, если это НЕ ленивая инициализация).
В юнит-тестах желательно тестировать только один класс, чтобы не было "каскадов ошибок" когда неправильно отрабатывает один, а за ним падают все на него ссылающиеся.
Поэтому Spring'овые синглтоны порой следует использовать даже для stateless классов.
[Археология Live] Стыдный разговор о синглтонах