Почему я ненавижу Spring

http://samatkinson.com/why-i-hate-spring/
  • Перевод
В начале своей карьеры я реально влюбился в Spring. Я так долго ждал его. Я использовал его во всех своих проектах. Вдобавок мне даже удалось впихнуть туда кучу всякой всячины из Spring Integration. Я был кем-то вроде короля XML. Я делал RPC-слой на основе JMS, protobufs и Kaazing для всего нашего отдела и банка в целом. Я думал: «Это так конфигурируемо. Всего-то пара XML-файлов — это действительно гибко». Я был очень доволен собой.

Но некоторые мои коллеги были склонны не согласиться. У них возникали проблемы, когда они пытались связать всё так, как им хочется; они не знали, где какие XML-файлы им нужны. Были проблемы с версиями Spring, с тем, как подружить их (я, к тому же, далеко зашел с модульностью: у нас было 5 или 6 разных модулей с разными номерами версий, и нельзя было просто так взять и понять, какой из них использовать, не спросив меня). Это были тревожные звоночки, но я их не замечал; я думал, что нужно больше документации или что те ребята просто тупые. Такая ситуация типична сама по себе: мольбы пользователей одного из самых нелюбимых и трудных в использовании фреймворков о помощи часто разбиваются о «да там один файл и немного параметров, это не так уж и тяжело», в то время как все остальные целыми днями пытаются найти магическую комбинацию файлов и параметров, чтобы хоть что-нибудь как-нибудь заработало.

Я всё ещё работаю в той же организации, но теперь я пользователь своего старого фреймворка. В результате этого питания кормом своей собаки я стал ненавидеть Сэма (автор имеет в виду себя — прим. пер.) 2009-2010 годов по нескольким причинам, но в основном — за Spring. Spring — это зло в хорошую погоду, но когда его включают в состав библиотеки или API, которым пользуются другие программисты, — это уже другой уровень зла: как плод любви Гитлера и дьявола. Не позволяйте Spring торчать из вашего API наружу.

Spring — отстой по ряду причин, и я почувствовал, что их нужно перечислить, т.к. в google нет четких контраргументов.

  • Конфигурация в XML. Хотел бы я думать, что мы как профессия оставили XML в прошлом. Он невероятно многословен, но это ещё цветочки. Намного важнее то, что я не хочу программировать на XML. Связывание всех классов воедино — чрезвычайно важная часть вашего приложения. Вы Java-разработчик, а не XML-разработчик. Одна из прелестей Java как языка — compile time safety. Я могу скомпилировать свои приложения, в которых нет Spring, и быть на 100% уверенным, что всё собрано, подключено и готово к работе. Но если в приложении есть Spring, ты запускаешь его, ждешь 30-60 секунд, пока оно инициализирует бины, прежде чем упасть. В современном мире это безумие, особенно если это еще и умножается на кучу интеграционных тестов, в которых вам нужно вертеть контейнер так и этак. Отдельного места в расстрельном списке заслуживает «это значит, что я могу менять реализацию без перекомпиляции!». Так никто не делает. Никогда.

  • Магия. Тут обычно следует реплика: «Теперь вы можете делать всё с помощью аннотаций! Больше никакого XML!». Здорово, когда не нужно программировать на XML, но аннотации — это всё ещё магия. Пока вы не запустите приложение, вы понятия не имеете, свяжется ли оно правильно. И даже потом вы не знаете, правильно ли оно связалось; вы всего лишь знаете, что оно связалось. Не люблю магию.

  • Импортирование других Spring-файлов. В данный момент это бесит меня больше всего. Я обнаружил, что существует тенденция разбивать Spring-файлы на более мелкие и раскидывать их по модулям. Я только что убил 2 недели, продираясь сквозь JAR'ы и пытаясь найти правильную комбинацию/порядок/версию Spring-файлов, чтобы кое-что заработало. Spring-файлы в JAR'ах — это плохая, плохая идея. Ужасная. Каждый раз, когда вы размазываете зависимые Spring-файлы по JAR'ам, где-то умирает ребенок.

  • Сложность. Когда на собеседовании спрашиваешь кандидата: «Какие подводные камни есть в Spring?» — чаще всего слышишь в ответ, что у него крутая кривая обучения. Правда это или нет — отдельная тема, но я хотел бы подчеркнуть тот факт, что Spring сейчас настолько сложен, что у него есть собственный фреймворк — Spring Boot. Фреймворк для фреймворка. Мы во «Framework Inception» — фильме о Леонардо Ди Каприо, который пытается найти свой давно потерянный Java-код, всё глубже и глубже погружаясь в слои XML и аннотаций, прежде чем в конце концов покончить с собой.

Штука в том, что я уверен: удачно использовать Spring в приложении теоретически возможно. Я еще никогда такого не видел, и это проблема. Как по мне, все «плюшки», которые он предлагает, вполне возможны и без него. Когда мы спрашиваем о Spring на собеседовании, кандидат обычно отвечает: «Со Spring у вас есть чистый код, разделение ответственности, к тому же он действительно хорош для тестирования». В общем, все те вещи, большим поклонником которых я являюсь (особенно тестирование), но на самом деле это результаты не использования Spring, а хорошего программирования. Возможно, для новичков Spring — это хороший костыль для освоения таких идей, как внедрение зависимостей, mocking и тестирование, но на самом деле они ортогональны Spring. Если вы применяете TDD, у вас в коде не будет геттеров и сеттеров — только внедрение зависимостей через конструкторы, которые вы можете «замокать» для тестирования, а затем, когда вы связываете своё приложение воедино, просто используете часто забываемый способ создания объектов — ключевое слово «new». Зачастую мы создаем класс «ApplicationContext», который отвечает за связывание всего воедино. Он чистый, всё тестируемо, у меня есть compile time safety, и мои тесты выполняются чертовски быстро.
Метки:
Поделиться публикацией
Похожие публикации
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 256
  • +4
    Я только осваиваю Spring, но по смыслу статьи так ине понял чем он плох (я не защищаю и не осуждаю, я просто не понял) Про аннотации в самой же статье сказали, а про магию — ну извините, это инверсия. В любой инверсии вам придется знать ЧТО именно делает каркас к который вы встраиваетесь — это не магия спринга это магия DI.

    А вот кривая обучения — да. Примеры на сайте не промасштабированы, нихрена не понятно с первого взгляда, на каком уровне ты работаешь и что именно за тебя делает магия. Вот тут конечно можно было бы поработать.
    • +6
      это не магия спринга это магия DI.

      Посмотрите на Guice — это маленькая библиотека, которая позволяет сделать DI. Но она маленькая, легковесная и в ней много конкретики. Хороший конфиг выглядит как: «для интерфейса Х создай имплементацию Y со всеми зависимостями».
      Хотя тут тоже свои подводные камни для больших проектов.

      В случае со спрингом это Можно сделать так, но редко кто делает — «это сильно много кода». Сервисы и компоненты просто декларируются и закидываются в класспас, а дальше «магия спринга» решит кого куда внедрить и кто кому нужен для работы. Контроля в этом случае нету в принципе.
      Для небольших проектов, где есть по одной имплементации – это вполне удобно. Для крупных — не уверен.
      • 0
        В таком случае лучше уж Dagger, там конкретный код можно посмотреть.
        • 0
          А есть примеры использования Dagger за пределами Android? Мне он показалась каким то уж усложненным по конфигурации, по сравнению с Guice.
          • 0

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


            Мы использовали в десктопщине.


            Если интересует пример — можно посмотреть в github репозитории самого dagger — dagger/examples.

        • 0
          Для небольших проектов, где есть по одной имплементации – это вполне удобно.


          Кстати, а зачем там вообще DI?

          Вот глобальный вопрос: посмотрите на типичный Spring-проект и ответьте себе честно: там есть польза от DI?
          • 0
            Если смотреть на те проекты где я работал со spring boot, там есть польза. В проекте 50-100 файлов и все само в кучу собирается. Красиво и удобно, нету тонны кода для ручного создания всего кода.
            ps: но это было удобно только потому, что нужно было получить результат быстро и не париться с веб-фреймворками.

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

            У меня нету однозначного мнения на счет DI — это и хорошо и плохо одновременно.
            • 0
              Нет, польза от DI только в тестах
              • 0
                О блин, как я мог забыть.
                • 0
                  А что, нет? У вас в проекте обычно одна реализация для интерфейса + для теста
                  • –1
                    У нас очень и очень редко для теста нужна прям другая реализация. Обычно просто разные значения пропертей.
                    • –1

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

              • 0

                А ещё можно посмотреть на HK2 — оно ещё меньше и проще.

                • 0
                  не надо на него смотреть, это древнючий, ужасно написанный контейнер к которому буквально приклеен кусок guice (но не очень аккуратно). смотрите или просто на guice или на чудесный picocontainer
            • +12
              Я, кажется, превращаюсь в адвоката Spring, но статья и хорошая, и не очень одновременно.

              Думаю, можно опустить пункты про XML (его ещё кто-то пишет?) и импортирование других файлов, что бы это ни значило. Если речь идёт про размазывание конфигурации по куче jar ов… Ну так и правда делать не нужно :)

              Важный пункт это про магию. И тут надо понимать, что если магию перевести в технический термин «уровни абстракции», то вместо иронично-негативного получим чисто субъективное — нравится подход скрытых абстракций и реализаций или нет. Кто-то хочет написать код руками, чтобы избежать магии, кто-то наоборот, предпочтет добавить понятную ему и документированную аннотацию. Поэтому демонизация Spring из-за его магии — это странно. Spring потому и используют, что он магией скрывает все детали реализации.

              Но очень хороший совет, и его прямо сложно переоценить — это не включение в свои Api / библиотеки зависимости на Spring. Этого и правда нужно избегать, в идеале код библиотеки вообще не должен знать про Spring. В крайнем случае, можно выделить отдельную библиотеку интеграции. Но это ещё Дядюшка Боб завещал, это не особенность конкретно Spring.

              Поэтому отвечая автору «Почему я ненавижу Spring» я бы сказал «Скорее всего, потому что вы не любите уровни абстракции которые не контролируете и предпочитаете им написанный руками boilerplate код».
              • –5
                Думаю, можно опустить пункты про XML (его ещё кто-то пишет?)

                Эммм… Да, под Андройд, и еще как) Там это вообще каркас.
                • +5
                  Я имел в виду XML для конфигурации Spring :)
                  • 0
                    А, ну это другое дело, да) А-то думаю ничего себе товарищ за бортом оказался, ибо то, что под Андройд на нем пишется чуть ли не половина логики, знает даже простой обыватель)
                • 0

                  Да пишет (XML) — Егор Бугаенко

                  • +1
                    обычно если тащат в приложение спринг, то тащат почти всё (веб, дао, и т.д.) ваше приложение опирается на разномастное, местами старинное дерево абстракций, навязывающих свои интерфейсы, свои, подчас, не самые оптимальные способы работы с core-DI и проч.
                    для поддержки всего этого добра уже мало знать underlying технологии, надо знать интеграционную специфику спринга.
                    авторы многих интеграционных подпроектов одержимы причесыванием всего под одну гребенку, бывает, что суют свои интерфейсы даже если нативные лучше.
                  • +3

                    зачем использовать new в тестах, когда есть @MockBean и @SpyBean?


                    и если вас напрягает DI и иже с ним, то как вы выживаете в этом мире микросервисов и распределённых систем?

                    • +1
                      Это вопрос автору, переводчику или вообще всем мимо проходящим?
                      • 0

                        то, что это перевод заметил не сразу. Так что, давайте так:
                        0) вопрос выше — всем мимо проходящим
                        1) вопрос переводчику — зачем такой вброс сюда был? Какую цель вкладывал, когда переводил это?

                        • +2
                          то, что это перевод заметил не сразу


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

                          вопрос переводчику — зачем такой вброс сюда был? Какую цель вкладывал, когда переводил это?


                          В основном, хотел немного попрактиковаться в переводах :) А конкретно этот пост выбрал потому, меня тоже бесит Spring. Я мог бы еще набросить лично от себя, но холиворить в интернетах надоело :)
                    • 0
                      Автор, а вы знакомы с проповедями Егора Бугаенко yegor256?

                      http://www.yegor256.com/2014/10/03/di-containers-are-evil.html
                      http://www.yegor256.com/2016/04/12/java-annotations-are-evil.html

                      Выбросил Spring из проекта, остался только JdbcTemplate) Результатом доволен.
                      • +3
                        Выбросил Spring из проекта, остался только JdbcTemplate

                        расскажете как вы так сумели?

                        • +1
                          ОK, OK, я отказался от DI средствами Spring. Совсем выбросить руки не дошли пока.
                          • 0
                            Можно еще и Spring JdbcTemplate выкинуть, он не нужен.

                            Что обычно нужно от Spring JdbcTemplate?
                            — подготовить запрос, выполнить и смапить результат на какой-то бин или объект, правильно?

                            Если больше ничего не нужно — у меня есть хорошая новость, чистый JDBC с этим прекрасно справляется!
                            Миниатюрная обертка над бойлерплейт кодом подготовки JDBC запроса (~50-150 строк) и можно не подключать Spring JdbcTemplate в проект.

                            https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html#setObject(int,%20java.lang.Object)
                            — этот метод убирает всю сложность подготовки запроса (лучше использовать другой метод, но там немного усложняется код, может +50 строк будет).

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

                            ps: конечно, может это зависит от Jdbc драйвера, я тестировал только для PostgeSQL.
                            • 0
                              • 0
                                Нет, не нужно, я тоже умею обходиться JDBC.
                                Есть еще http://jdbc.jcabi.com/ от yegor256. Но с ним как-то не срослось под мои нужды.
                                • 0
                                  Для работы с базой есть прекрасная библиотека https://commons.apache.org/proper/commons-dbutils/
                              • +1
                                Автор, а вы знакомы с проповедями Егора Бугаенко yegor256?


                                ХЗ, спросите у него. Ссылка на его блог — под переводом.
                              • 0
                                Чем мощнее инструмент и чем больше он даёт возможностей, тем легче выстрелить себе в ногу. Так что либо ограничивайте способы применения, либо смиритесь.
                                • +1
                                  С другой стороны, чем мощнее фреймворк и чем больше он дает возможностей, тем он монструознее и тем больше шанс, что 95% его вам нафиг не сдались, и вообще лучше было разбить его на либы.
                                • +2
                                  Мне аннотации нравятся, тестируемость нравится и магия тоже нравится. Но вот когда выясняется, что либа, которая внутри сервера приложений используется для запросов в сеть не может работать через прокси, а в конфигах в ста местах уже прописано «работай зараза» и тебе приходится заменить ее апачевской, которая умеет после нескольких дней выяснения «где же эта сволочь конфиг берет я ведь все указал!?». В общем это да, раздражает. За широкие возможности готовой реализации (магия) приходится платить. Зато сервер разворачивается и работает «сам по себе с парой конфигов».
                                  • +5
                                    Одна из прелестей Java как языка — compile time safety.
                                    тут надо тогда не на Spring ругаться, а на весь AspectJ целиком, с включенным режимом инжектирования runtime.

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

                                    В общем ИМХО «не хочу учиться, хочу жениться» какое-то.
                                    • 0
                                      Совершенно согласен. Я даже подумал, что пока он будет свое ваять, если силенок хватит, он напишет огрызок спринга.
                                      • +5
                                        А кто сказал, что он будет «своё ваять»? Возьмет и заюзает тулзу, которая устраивает его больше. Как будто кроме Spring на планете Java ничего нет.
                                      • +1
                                        так навалом схожего и попрозрачнее. dropwizard, spotify apollo, lagom, play/slick, etc…
                                        чем больше народ будет уходить на микросервисы, тем сильнее будут отказываться от спринговой монструозности
                                        • 0
                                          Работал с Play первым и вторым. После него Spring (а конкретно Spring Boot + Spring MVC) — как глоток свежего воздуха.
                                          • 0
                                            а что именно вас так торкнуло в спринге на фоне плея?
                                            • +1
                                              Да много чего на самом деле.
                                              1. В Спринге есть куча проверенного и рабочего функционала как из коробки, так и в виде модулей. В Play же из коробки даже нет DI, это по-моему провал.
                                              2. Если в спринге пытаются держать хоть какое-то backward-compatibility, то в play оно отсутствует как класс. Я помню как наша команда неделю переводила плейовский проект с одной минорной (подчеркиваю — минорной) версии на другую минорную.
                                              3. Вероятность найти на том же стэковерфлове ответ на вопрос в контексте спринга в разы выше. Есть куча статей с примерами. Не плей кроме официальной документации толком негде больше смотреть (а если и есть, то из-за отсутствия backward-compatibility работать на конкретной версии плея оно вряд-ли будет).
                                              4. Все модули прибиты гвоздями. Хочешь вместо плейовского Ebean использовать Hibernate? А вот фиг тебе. Хочешь вместо sbt заюзать gradle или maven — то же самое.
                                              5. Свои конвеншены написания кода. (Например, модельки должны иметь публичные поля).

                                              Ну и еще много чего, сейчас все и не вспомню. Короче, после 2-х лет работы с плей я не вернусь на него ни за какие деньги. По крайней мере в ближайшем будущем.
                                              • +2
                                                Например, модельки должны иметь публичные поля
                                                А что в этом плохого?
                                                • 0

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

                                                • 0
                                                  это был 1.х Play?
                                              • 0
                                                Почему всех тянет именно на фреймворки? Попробуйте Akka HTTP что ли для разнообразия.
                                                • 0
                                                  Ну так с фреймворками быстрее же (если его знаешь, конечно).
                                                  • +1
                                                    у акка-хттп своя ниша, рест сервисы с гибкими урлами на нем странно делать
                                            • +1
                                              Пару лет назад осознанно отказался от Spring в одном своем проекте.
                                              Стал использовать Akka, jooq, dagger.
                                              За 2 года не пожалел ни разу.
                                              • 0
                                                А чем вы транзакции управляете? JOOQ ведь не умеет
                                                • 0
                                                  Упрощенно:
                                                  try {
                                                       dbConnection = getDBConnection();
                                                       dbConnection.setAutoCommit(false);
                                                       new JOOQ(dbConnection).query().execute(); //dbConnection.commit();
                                                  } catch (Exception e) {
                                                      dbConnection.rollback();
                                                  }
                                                  

                                                  • 0
                                                    Упрощенно, 6 строк, вместо одной, круто.
                                                    А как у вас с уровнями изоляции транзакций?
                                                    • 0
                                                      Эти 6 строк заворачиваете в обертку и все. Переиспользуете везде. Зато любой джун разберется за 1 минуту и не будет думать как же работает вся эта магия.
                                                      • 0
                                                        Да какая магия? Создается Proxy класс, т.е. та же самая обертка, и в ней тот же код, почти, как у вас.
                                                        В чем магия?
                                                        • +1
                                                          Ну так в том то и дело. Если нет разницы — так зачем платить больше (использовать спринг?)
                                                          • 0

                                                            чтобы писать меньше и концентрироваться на других задачах, чем пересоздание своих велосипедов с казалось бы такими же колёсами

                                                            • 0
                                                              Так без спринга получается меньше. Но да, минимальную инфраструктуру вокруг нужно будет набросать.
                                                            • 0
                                                              В веб приложении часто надо сериализовать/десериализовать json/xml, security, api documentation, интернационализация, миграции,… в Spring это все интегрированно и протестированно, ну а если мы используем Spring то и писать свои обертки не нужно
                                                              • +1
                                                                Все это точно так же легко решается и без спринга.
                                                                • 0
                                                                  Решается, но зачем решать если уже есть готовое?
                                                                  • +1
                                                                    Спринг многоцелевой и сложный. Чтобы начать работу со спрингом нужен определенный бекграунд. Любую задачу, которую решает спринг можно решить другими инструментами, которые простые и узконацеленные. Никто не говорит что нужно писать свои велосипеды.
                                                                    • 0
                                                                      т.е. разобраться с одним спрингом сложнее, чем с полусотней других «простых» решений? В спринге хотя бы всё более менее однообразно и всё работает из коробки, а набор «простых» решений еще придется друг к другу подгонять и писать интеграцию.
                                                                      • +1
                                                                        т.е. разобраться с одним спрингом сложнее, чем с полусотней других «простых» решений?


                                                                        Именно. Тут уже внизу писали, что спринг — в топах вопросов на СО.

                                                                        а набор «простых» решений еще придется друг к другу подгонять и писать интеграцию.


                                                                        Наоборот — в виду узкой специализации каждой из библиотек вместе их собрать гораздо легче, чем наконфигурить спринг. Гляньте, например, guice как пример DI. За 1 минуту подключаете и используете во всю.

                                                                        P. S. Если что — я 7 лет использовал спринг. Последние 3 год не использую. Моя продуктивность сильно выросла. Но это мой частный случай.
                                                                        • +1
                                                                          Тут уже внизу писали, что спринг — в топах вопросов на СО.
                                                                          возможно это не только в силу его непонятности, но еще и в силу высокой популярности?

                                                                          если я напишу жутко сложную неудобную либу-обертку над JDBC и повешу ее на гитхаб, смогу ли я на основании отсуствия вопросов по ней на СО констатировать ее понятность?
                                                                          • 0
                                                                            Гляньте, например, guice как пример DI. За 1 минуту подключаете и используете во всю.

                                                                            Вы так говорите, как будто спринговый di подключается дольше.
                                                                  • 0
                                                                    настройки серилизации спринга, кстати, одно из самых мутных мест. а так люди сами джексон или какой-нибуд gson интегрируют и все.
                                                                    спрингсек — ужасный монстр в котором почти никто не разбирается, тот уровень магии, когда она уже вышла из под контроля (как и многие другие спринговые подпроекты :))
                                                            • 0
                                                              А как у вас с уровнями изоляции транзакций?

                                                              Я надеюсь вы понимаете, что изоляцию транзакций и сами транзакции управляются исключительно базой данных. А команды для этого посылает jdbc драйвер. Спринг и хибернейт абсолютно ничего нового не делают с транзакциями, всё сводится в конце к jdbc драйверу и методам setTransactionIsolation()/setAutoCommit(false)/commit()/rollback() из java.sql.Connection.
                                                          • 0
                                                            Руками — написал обертку.
                                                            Выглядит так:
                                                            database.executeAsyncTransactional(create -> create.update...)
                                                            

                                                            Внутри там используется create.transaction
                                                            • 0
                                                              что угодно можно написать самому. Но зачем, если есть готовое, протестированное, удобное в использовании, знакомое другим людям и с советами на со?
                                                              • 0
                                                                А если оно таки неудобное?

                                                                А если я использую простенькую библиотечку, исходный код которой я могу прочитать за один присест и как угодно пропатчить под себя в случае необходимости, то на кой черт мне SO и другие люди?
                                                                • +1
                                                                  Потому что бэкенд на Akka стартует за 3 секунды и выдерживает 10 000 REST запросов в секунду на моем маке.
                                                                  Приложение на Spring стартует секунд 30, и держит хорошо если 100 запросов в секунду.

                                                                  Приложения примерно сравнимы — простенькие CRUD операции на базе.
                                                                  • 0
                                                                    Спринг это система интеграции. Если вам нужен перфоманс в ответах, не нужно использовать хибернейт для обращения к базе, а возьмите какое-нибудь другое решение, которое будет для этого предназначено, а не винить поезд за то, что он не летает, это же просто глупо. Более того можно без проблем прикруть акку к спрингу. Еще раз: спринг это система интеграции. Его сила в возможности быстро и удобно интегрировать какие-то решения или использовать готовые интеграции из коробки. Если интегрировать нечего, а надо отвечать быстро на простые запросы, то вероятно, что спринг просто не нужен. И да, было бы интересно взглянуть на тесты и их результаты, на которые вы ссылаетесь в своем комментарии.
                                                                    • +1
                                                                      Можно посмотреть на приложение на Spring?
                                                                      • 0
                                                                        Если вы имеете ввиду веб-приложение с реактором, то можно посмотреть на примеры из бута.
                                                                        • –1
                                                                          Хочу посмотреть на приложение на Spring которое стартует секунд 30
                                                                          • 0
                                                                            Да, прошу прощения, я не туда ответил. Мне тоже интересно, что это за приложение такое и почему оно 30 секунд стартует. Уверен, что спринг тут играет очень косвенную роль. Например включено сканирование всех 100500 классов проекта и зависимостей. Или кучу времени инциализируется хибернейт и тд…
                                                            • +1
                                                              Как по мне, все «плюшки», которые он предлагает, вполне возможны и без него.

                                                              С этих слов обычно начинается эпичное велосипедостроение. Насколько велосипедостроение хорошо или плохо — тема для отдельного холивара.
                                                              • +1
                                                                А еще эти слова внезапно могут значить, что автор нашел нормальный способ делать то же самое без Spring и велосипедов (другой способ DI, например).
                                                                • +3
                                                                  другой способ DI

                                                                  обычно в таком случае человек рассказывает об альтернативе и какие плюсы он получил от перехода с инструмента А на инструмент Б. Если же человек говорит "возможны и без него" не приводя примеров, то это начинает попахивать

                                                              • +11

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

                                                                • +4
                                                                  Полностью согласен, отдельно стоит упомянуть что при гуглении методов решения какой-то проблемы/задачи первыми вылезают наиболее «проверенные временем» варианты, т.е. те что были опубликованы раньше, и отдельной проблемой становится узнать «а надо ли еще вот это вот все писать/реализовывать» или в современных реалиях уже все что нужно это какая-нибудь аннотация на классе/jar в класспасе и все сработает само
                                                                  • 0
                                                                    Особый кайф ловишь, когда эти «проверенные временем» варианты на XML, а у тебя в проекте — нет, и конверсия не всегда тривиальна.
                                                                • +8
                                                                  Есть пачка бонусов которые перевешивают:
                                                                  1. огромное количество библиотек и реализаций.
                                                                  Попробуйте навелосипедить свой spring-security c каким-нибудь oauth собственнм сервером и клиентом. Куча багов и без гарантий что дырок нет. Альтернативу @Transactional с нетривиальнм двухфазным коммитом (например БД + Очередь в единой транзакции). Возможно вы напишете свое, но сколько это займет времени. Возможно вы найдете для всего альтернативы, но опять же время на изучение и не меньшее время чтобы все это подружить между собой.
                                                                  2. сообщество.
                                                                  Легко найти того, кто знает, делал и есть доки, SO и т.д. Представьте, что у вас ушел 1-2 ключевых разработчика, кто делал ваши велосипеды и потом найдите и пофиксите сложный баг.
                                                                  3. оттестированно.
                                                                  Куча проблем за вас решена, причем проблемы в основном транспортного уровня, безопасность и т.п. Туча народу пробежала по граблям и убрала большинство.
                                                                  4. относительно быстрый старт.
                                                                  Сделать достаточно сложный проект на spring-boot для быстрого старта как прототип относительно несложно по количеству кода и времени. Самостоятельные попытки найти нужные библиотеки и связать их вместе только для того чтобы быстро показать и выбросить/поменять намного труднее.
                                                                  • +7
                                                                    1. огромное количество библиотек и реализаций. Попробуйте навелосипедить свой spring-security c каким-нибудь oauth собственнм сервером и клиентом.

                                                                    В большинстве случаев это не нужно. Как правило вы используете какую-то одну конкретную технологию и уже готовую библиотеку для нее. Spring же предлагает навороченный абстрактный леер, интеграцию сразу со всеми известными технологиями и толстую книгу рецептов как это все засандалить в ваше приложение. Причем зачастую многие проблемы уже решены на более низком уровне, например тот же Servlet уже содержит простые средства security.


                                                                    Альтернативу @Transactional с нетривиальнм двухфазным коммитом (например БД + Очередь в единой транзакции).

                                                                    Двухфазный коммит делает не Spring, а стороннияя библиотека-координатор, например Atomikos, Narayana, etc. Spring @Transactional делает лишь наивный автоматический прокси на коммит/роллбэк, который также легко сделать вручную при помощи java.lang.reflect.Proxy, AspectJ или ByteBuddy. В реальных проектах практически всегда требуется вручную контролировать сбои и взависимости от типа ошибки нужно помимо роллбека повторить транзакцию, реинициализировать ресурс, отрапортовать о сбое, собрать метрики… Вот вам и свой @Transactional. Кроме того есть мнение, что XA вообще не рекомендуется использовать...


                                                                    но опять же время на изучение и не меньшее время чтобы все это подружить между собой

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


                                                                    Представьте, что у вас ушел 1-2 ключевых разработчика, кто делал ваши велосипеды и потом найдите и пофиксите сложный баг.

                                                                    Ваши 1-2 разработчика писали когда-нибудь bean postprocessors? Скорей всего они намолотили кучу кривой прикладной магии ввиде специфических @Заклинаний. Разобраться почему не проксируется бин, кто его процессит и в какой последовательности и почему вдруг что-то перестало работать — никто не будет. Девелоперы как правило понавтыкают костылей, чтобы хоть как-то решить требуемую задачу.


                                                                    Куча проблем за вас решена

                                                                    И на ровном месте создана другая куча. Если все так просто — почему на SO Spring держится в топе? Как правило всегда есть более простое и элегантное решение каждой конкретной проблемы. Spring же пытается влезть без вазелина везде, где это только возможно, вцелом значительно усложняя архитектуру и упрощая лишь какие-то конкретные простые случаи использования. Кроме того, подобное упрощение имеет негативный эффект: куча кодеров, не понимая принципы работы, начинает копипейстить туториалы и SO, допуская архитектурные ошибки. И, столкнувшись с проблемами или с незнанием того, как что-то конкретное сделать на спринге, начинают грязно костылить.


                                                                    Сделать достаточно сложный проект на spring-boot для быстрого старта как прототип относительно несложно

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

                                                                    • –2

                                                                      А как прекрасно становится, когда надо оверрайдить версии библиотек, прибитых гвоздём в parent pom'е spring boot.


                                                                      Например, если нужна определенная версия jetty-client с её зависимостями; у тебя уже есть нужный bom, но его не подключишь, т.к. parent pom оверрайдит.

                                                                      • +2

                                                                        а мне казалось, что чтобы заменить версию библиотеки, достаточно просто в своём pom-файле в properties переопределить для зависимости на новую версию...


                                                                        <properties>
                                                                          <jetty.version>9.4.2.v20170220</jetty.version>
                                                                        </properties>

                                                                        имена нужных переменных берутся тут поиском по необходимому артефакту

                                                                        • 0

                                                                          Похоже вы правы, если mvn dependency:tree -Dverbose=true меня не обманывает.


                                                                          Скорее всего, кусок pom'а вида


                                                                            <properties>
                                                                              <java.version>1.8</java.version>
                                                                          
                                                                              <jetty.version>9.3.20.v20170531</jetty.version>
                                                                            </properties>
                                                                          
                                                                            <dependencyManagement>
                                                                              <dependencies>
                                                                                <dependency>
                                                                                  <groupId>org.eclipse.jetty</groupId>
                                                                                  <artifactId>jetty-client</artifactId>
                                                                                  <version>${jetty.version}</version>
                                                                                </dependency>
                                                                                <dependency>
                                                                                  <groupId>org.eclipse.jetty</groupId>
                                                                                  <artifactId>jetty-http</artifactId>
                                                                                  <version>${jetty.version}</version>
                                                                                </dependency>
                                                                                <dependency>
                                                                                  <groupId>org.eclipse.jetty</groupId>
                                                                                  <artifactId>jetty-io</artifactId>
                                                                                  <version>${jetty.version}</version>
                                                                                </dependency>

                                                                          у меня появился неспроста. Возможно, зависит от версии мавена и на 3.5.0 просто не проявляется. IIRC, они несколько раз переделывали resolve зависимостей в третьей ветке.

                                                                      • 0
                                                                        О боже, вы только что перечислили всё то, что было у меня в голове все эти годы! Я чувствовал, что со Spring много чего не так, но чтобы вот так взять и выразить словами… Да вам надо статью пилить!
                                                                        • +3

                                                                          Хм. Ну вот так-то передергивать не нужно:


                                                                          например тот же Servlet уже содержит простые средства security.

                                                                          Вам про OAuth, а вы про сервлеты. Покажете, в каком месте у сервлетов OAuth? :)


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

                                                                          • +2
                                                                            Большинство джунов не в состоянии не только написать такой, но и понять зачастую. Поэтому посты типа "я ненавижу..." следует читать с солидной долей скепсиса.

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

                                                                        • 0
                                                                          свой spring-security c каким-нибудь oauth

                                                                          в мавен-репозитории значатся как минимум Apache Shiro и PicketBox Assembly, если искать в категории "Security Frameworks". Применительно к OAuth2, сервера и клиенты ищутся в гугле достаточно легко, и Spring там далеко не на первом месте.

                                                                        • +2
                                                                          Эх… когда же всё таки появится что-то похожее на Flask для джавы?
                                                                          • 0

                                                                            Spark не устроит?

                                                                            • 0
                                                                              Близко, но не оно. А какие есть ещё альтернативы?
                                                                            • 0
                                                                              ну можете глянуть на ratpack.io… у меня с ним положительный опыт в проекте (чистый API, UI отдельное SPA на JavaScript)
                                                                            • +1
                                                                              Использовал Spring, исключительно с полным описанием всех компонентов через XML и без всяких Autowired, могу сказать, что получается очень удобно. Во-первых никакой магии, всё описано в XML до последнего параметра. Во-вторых можно без перекомпиляции менять кучу всего и это, вопреки мнению автора статьи, действительно используется. В-третьих я никогда не пойму ненависть по отношению к XML, по-мне это чудесный формат и пока никому ещё не удалось создать что-то лучше, единственный его недостаток это то, что там нет синтаксиса для массивов, поэтому при маппинге возникают неоднозначные ситуации (но XML Schema это решает).
                                                                              • +2
                                                                                Тоже не понимаю ненависти к XML.
                                                                                Многословен? А вы куда-то все время торопитесь? :)

                                                                                Зачастую очень многих проблем с «многословностью» можно избежать если почитать стандарт + сопутствующие технологии (например namespaces)
                                                                                • 0
                                                                                  Абсолютно идентично можно всё описать в джава-конфиге, только с проверкой типов во время компиляции. Мне так даже больше нравится.
                                                                              • +1
                                                                                Вброшу свои пару мыслей на вентилятор:
                                                                                1. Любой фреймворк создается для решения какого-то определенного множества задач. Если ваша задача не входит в рамки фреймворка, то это проблема не фреймворка, а вашего выбора.
                                                                                2. Использовать какой-то фреймворк или не использовать, это как выбор религии — никто не в праве навязывать вам выбор и никто не в праве порицать ваш выбор.
                                                                                • 0
                                                                                  Любой фреймворк создается для решения какого-то определенного множества задач.


                                                                                  И в этом большая проблема самого подхода «фреймворк». Эй, люди, как насчет SRP? Хороший инструмент должен решать одну задачу. Помню, когда я только начинал осваивать Spring, я не мог понять, какую задачу решает он. После раскуривания манов у меня сложилось ощущение, что он пытается решить вообще все задачи. Так оно и оказалось. Это оборачивается тем, что потом вы начинаете думать, как подружить Spring с библиотекой/фреймворком X. Это ж звездец какой-то! Я программист, а не семейный психолог. Я хочу писать свой код, а не сглаживать межфреймворковые противоречия. Не припомню, чтобы мне приходилось даже думать о том, чтобы подружить две библиотеки. Одну ты вызываешь, когда нужно А, другую — Б.
                                                                                  • 0
                                                                                    Спринг сам по себе решает ровно одну задачу. Интеграцию решений. Плюс у спринга еще есть много дополнительных библиотек, которые решают другие задачи. Тоже обычно по одному за раз.
                                                                                    • 0
                                                                                      Спринг сам по себе решает ровно одну задачу. Интеграцию решений.


                                                                                      Интеграция решений — это работа программиста.
                                                                                      • 0
                                                                                        Ну вот заинтегрировал я 3 библиотеки, что, мне за это заплатят деньги?
                                                                                        • 0
                                                                                          Не знаю как Вам, а мне платят. А что такое программирование если не интеграция решений? Работа программиста в том и заключается, чтобы выдать продукт А, используя инструменты B, C и D. Ну это если не брать всяких мышевозов с джумлой.
                                                                                          • 0
                                                                                            Работа программиста — это решать задачи с использованием программирования.
                                                                                            Т.е. вам платят за программирование, не за решение задач?
                                                                                            • 0
                                                                                              Ну дык это никак не противоречит тому, что я сказал
                                                                                        • 0
                                                                                          Ну да, а так как я очень ленив, я люблю, когда за меня эту работу делает готовый фреймворк. Я как программист всегда думаю о том как автоматизировать любую деятельность, почему же интеграцию обязательно нужно делать руками?
                                                                                          • +1
                                                                                            Да просто потому, что зачастую руками сделаешь проще и понятнее, и поддерживать будет проще.

                                                                                            Есть easy, a есть simple. Easy — это когда написал пару строчек. Simple — это когда легко разобраться, как это работает, и просто изменить что-то в одном месте, будучи уверенным, что ничего не сломалось где-нибудь еще.

                                                                                            Spring — это easy (пока не нужно сделать шаг влево/вправо :)), но это очень, очень далеко от simple. И вот этот not simple оборачивается hard, когда нужно сделать тот самый шаг в сторону.

                                                                                            Вообще каждый выбирает сам. Я начинал с предпочтения easy, меньшего объема кода, минимального дублирования и т.д. Сейчас предпочитаю немного отойти от easy, чтобы сделать simple.
                                                                                            • 0
                                                                                              Очень люблю писать велосипеды, но с опытом приходит понимание, что обычно лучше использовать готовое решение, особенно если оно знакомо другим разработчикам и решает все твои задачи. А велосипеды требуют не меньшей работы, чем разобраться со спрингом хотя бы из за того, что для всех его частей придется писать тесты, а потом еще ловить баги, проблемы секьюрити, корнер-кейзы и тд. Да еще если кто-то после тебя на твои велосипеды придет, то будет материть тебя на чем свет стоит (а то и решит, что её нужно переписать), потому что спринг знаком более-менее каждому современному джава-разработчику, и имеет очень неплохой уровень качества — как кода и архитектуры, так и проработанности деталей и покрытия тестами, а ваш велик придется исследовать с нуля, неизвестно какого он качества, да и не был бы я уверен, что по ходу развития системы сложность вашей собственной интеграции не станет существенно выше её же в спринге.
                                                                                              • 0
                                                                                                Очень люблю писать велосипеды, но с опытом приходит понимание, что обычно лучше использовать готовое решение, особенно если оно знакомо другим разработчикам и решает все твои задачи.


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

                                                                                                ваш велик придется исследовать с нуля


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

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


                                                                                                Ну так не уверен — не берись, уверен — делай и никого не слушай. «Главное понимать что ты хочешь и что можешь.» (https://habrahabr.ru/post/259831/#comment_8453133)
                                                                                                • +2
                                                                                                  готовые решения — это не однозначное добро

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

                                                                                                  Да, спринг часто кастомизируют, тем он и ценен, но вот так, чтобы объем кода кастомизации превышал объем бизнес-кода… такого я еще не видал. Да еще и весь костыльный, точно ли тут дело в спринге?
                                                                                                  Простите, но в ваших комментах сквозит нечто вроде детского страха перед тем, что сделали «взрослые дядьки»: мол, они могут сделать хорошо, потому что взрослые,

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

                                                                                                  Управление сложностью большой программной системы дело не простое, а прогнозировать такое управление на будущее и подавно. Поэтому уверенным в таком вопросе быть никак нельзя, тут приходится решать вопросы по мере их поступления. В какой-то мере и в этом спринг лучше самописного решения, потому что он долгие годы собирает типовые решения типовых проблем, которые можно если не использовать из коробки, то по крайней мере в разумное время приспособить под свои нужды.
                                                                                                  • 0
                                                                                                    Вот вы в целом пишете правильные вещи, и всё-таки смотрите на спринг как на нечто божественное, что вам не дано понять, повторить или обойтись без этого. Годы собирания типовых решений типовых проблем — это, конечно, показатель, но тоже спорный. Во-первых, Spring — вещь общая, и вполне возможно, что собственное решение будет проще и лучше (в том числе — на long term). Во-вторых, что если многие из этих «решений» на самом деле решают проблемы, которые породил сам Spring.

                                                                                                    Кстати, вы часто говорите, что Spring — это решение для интеграции. Можете привести пример, когда что-то с чем-то не спринговое нужно интегрировать, это действительно проблема и Spring ее решает?
                                                                                                    • 0
                                                                                                      Во-первых, Spring — вещь общая, и вполне возможно, что собственное решение будет проще и лучше (в том числе — на long term).

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

                                                                                                      Уже не первый раз про это слышу, что собственно вы имеете ввиду? Приведите топ 10 проблем, которые создал спринг, которые он сам же и решает. Т.е. поймите правильно, спринг безусловно решает свои внутренние проблемы, с этим спорить глупо. И да для этого написано много кода. Но эти проблемы второстепенны по сравнению с теми какое количество решений моих проблем у него есть.
                                                                                                      Можете привести пример, когда что-то с чем-то не спринговое нужно интегрировать, это действительно проблема и Spring ее решает?

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


                                                                                                        Ясно, спасибо, я думал, вы имеете в виду что-то другое.
                                                                                                        • 0
                                                                                                          Что например? Может показаться, что мелочи, но на мой взгляд совсем нет, да и не так иллюзорно это, когда спринг из коробки поднимает стек нетфликса, например.
                                                                                                          • 0
                                                                                                            Я просто думал, что вы говорите о какой-то интеграции, о которой я не знал / забыл.
                                                                                                            • 0
                                                                                                              вмешаюсь немного в ваш диалог. Мне кажется (возможно я ошибаюсь) что под интеграциями обычно (если не оговорено иное) подразумевают что то типа круга задач решаемых например Apache Camel.
                                                                                                              • 0
                                                                                                                кто-то интегрирует системы, а кто-то библиотеки в системе, всем нужны свои инструменты
                                                                                                          • –1
                                                                                                            Приведите топ 10 проблем, которые создал спринг, которые он сам же и решает.


                                                                                                            Я не готов сейчас дискутировать на эту тему. Тем более, что вы сами понимаете, что они есть.
                                                                                      • +2
                                                                                        На самом деле автор статьи достаточно прав. Используя спринг на проекте — вы все больше и больше пишите кода, не связанного с проектом, но связанный со спрингом. В некотором смысле, спринг обязывает вас говнокодить. Код должен содержать бизнес логику, а не фабрики, интерфейсы, конверторы, дто и т д. В этом и есть «болезнь» джавы, потому что когда-то давно «умные» дяди придумали кучу стандартов под маркой Java EE, и все фреймворки начали под него подстраиваться. Ребят, задайте вопрос, «что делает спринг у меня на проекте»? Делает DI? А сколько у вас реализаций на интерфейс? Одна?? Так какой это нахрен DI? То есть вы юзаете спринг для того что бы создать ОДИН СРАНЫЙ СИНГЛТОН? Рилли??? Service/@Repository/@Controller и для этого всего-то спринг??? Так может вы просто не знаете как писать тестируемый код с синглтонами? Так почитайте! Опять таки. Спринг, даже со своей гибкостью кривой! И не покрывает некоторые простейшкие случаи! К примеру Spring-Data-Jpa. Простейший кейс. Почему нельзя было добавить слово limit в синтаксис spring-data??? Почему когда дело доходит до более-менее сложных операций (а не CRUD) постоянно приходится отходить от «идеалов» спринга, и постоянно что-то дописывать? Ребят, если вы говорите что спринг мега-крутой и хороший фреймвок, скорее всего вы просто не пробовали что-либо другое. Попробуйте пописать годик-два проект например на Play Framework-е, желательно на старом, что бы без DI. Попробуйте Vert.X с его реактивным программированием. Или попробуйте сами построить нужную вам архитектуру на простом веб-сервере, без сервлетов вообще. Попробуйте писать код БЕЗ JPA, продумайте архитектуру и тогда вы начнете мыслить по другом. А то у нас бл*ть не программист, а Senior Spring-Framework Developer, и если что-то не входит в спринг, не в силах решить проблему. А самое интересное, что отказавшись от спринга, вы хоть и напишите «маленький» велосипед в виде кастомной архитектуры. НО! Вы увидите, что ваш код стал намного чище и намного гибче, чем со спрингом. И вы имеет ПОЛНЫЙ контроль над своим кодом! Я пишу на джаве с 2010 года, за это время были совершенно разные проекты с соершенно разными подходами. И к огромному сожалению, я заметил, что мода «богатых дядек» на ентерпрайз только усугубляет вещи в джаве. «Типичные вещи» в джаве можно делать намного проще, чем вы можете себе представить. (PHP программисты наверное офигивают, когда видят, как на джаве пишутся веб приложения, потому что у них нету джава ЕЕ, спринга и т.д., и там всё гораздо чище и проще).
                                                                                        • 0
                                                                                          Так может вы просто не знаете как писать тестируемый код с синглтонами? Так почитайте!

                                                                                          дайте ссылки что ли
                                                                                          • +2
                                                                                            Как и любой другой код. Тем же JUnit + Mockito или powermock. Если вы будете писать код в стиле спринга — а именно, сохранять ссылки на синглтон в полях класса — не будет никаких проблем с тем что бы их замокать. + никто не запрещает вам, делать конструктор синглтона не приватным, а пекедж-протектеж, что бы Ваши моки могли без проблемно мокать. Кроме того, end-to-end/интегрейшн тесты никто не отменял. Да и уровень покрытия с ними намного лучше, чем с юнитами. + Автотесты от QA. Не вижу никаких проблем.
                                                                                            • –1
                                                                                              Если вы будете писать код в стиле спринга — а именно, сохранять ссылки на синглтон в полях класса — не будет никаких проблем с тем что бы их замокать.

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

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

                                                                                              Да и уровень покрытия с ними намного лучше, чем с юнитами.

                                                                                              Но они медленные
                                                                                              • 0
                                                                                                Есть класс EmailSender если я в тесте забуду замокать все методы

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

                                                                                                • 0
                                                                                                  Зачем сохранять ссылки на синглтон в полях класса, если это синглтоны? Их же можно вызвать прямо там где нужно.

                                                                                                  Чтобы ограничить разрастание макарон в коде.

                                                                                                • 0
                                                                                                  сохранять ссылки на синглтон в полях класса — не будет никаких проблем с тем что бы их замокать

                                                                                                  Инстанс вы в конструкторе получаете или ининциализируете поле?
                                                                                                  private EmailSender emailSender = EmailSender.getInstance();
                                                                                                  
                                                                                                  • 0
                                                                                                    Инициализирую прямо в поле. Конструкторами — тоже хорошая практика. Главное что бы было удобно, и понятно, каждый выбирает как ему удобнее. С конструкторами мне не очень нравится, потому что иногда синглтонов может быть много, и тогда конструктор становится большим и принимать много параметров, и это становится не удобным и не красивым кодом.
                                                                                                    • 0
                                                                                                      Конструкторы лучше. Так как легче тестить. Например, когда нужно замокать этот самый EmailSender. Но да, бывает, что конструктор очень сильно ростет. Я в таких случаях создаю объект Holder который содержит ссылки на все синглтоны.
                                                                                                      • 0
                                                                                                        Т.е. Вы сами создаете инстансы классов и передаете синглетоны? А если завтра надо будет использовать SmsSender вместо EmailSender, Вы перепишите весь код?
                                                                                                        • 0
                                                                                                          Т.е. Вы сами создаете инстансы классов и передаете синглетоны?


                                                                                                          Да. Вот пример. В нем как раз есть и имейл сендер и смс сендер и пуш сендер =).

                                                                                                          А если завтра надо будет использовать SmsSender вместо EmailSender


                                                                                                          Любая IDE это делает через 2 клика.
                                                                                                          • 0
                                                                                                            Любая IDE это делает через 2 клика.

                                                                                                            А как же принцип открытости/закрытости?
                                                                                                            • 0
                                                                                                              И как код выше противоречит этому принципу?
                                                                                                              • –1
                                                                                                                закрыты для изменения: в результате расширения поведения сущности, не должны вноситься изменения в код, который эти сущности использует.

                                                                                                                Вы не только добавляете новые сущности но и вносите изменения в код.
                                                                                                                • –1
                                                                                                                  Так смс это не расширение, а новое поведение, поэтому все честно.
                                                                                                                  • –1
                                                                                                                    А что тогда расширение?
                                                                                                                    • 0
                                                                                                                      Добавить в смс враппер еще один метод.
                                                                                                                      • 0

                                                                                                                        И это не будет новым поведением? От этого же могут изменится результаты

                                                                                                      • 0
                                                                                                        Инициализирую прямо в поле.

                                                                                                        А если завтра надо будет использовать SmsSender вместо EmailSender, Вы перепишите весь код?
                                                                                                        • +2
                                                                                                          class SmsSender implements ISender{...}
                                                                                                          class EmailSender implements ISender{...}
                                                                                                          
                                                                                                          public class Sender{
                                                                                                            private static final ISender smsSender = SmsSender.getInstance();
                                                                                                            private static final ISender emailSender = EmailSender.getInstance();
                                                                                                          
                                                                                                            public static ISender getInstance(){
                                                                                                              return condition ?  smsSender : emailSender;
                                                                                                            }
                                                                                                          ....
                                                                                                          }
                                                                                                          


                                                                                                          Не знаю как у вас, у меня ни разу не было случая, что бы это «когда-то» наступило. Закладывать в основу кода, то, что когда-то что-то может изменится, зачастую есть ошибочным, ибо это когда-то никогда не наступит. Но, конечно случаи бывают.
                                                                                                          • +1
                                                                                                            Опять же, ребят, я не пытаюсь вас убедить в том, что спринг полное говно и его нужно избегать. Нет. Я просто хочу донести до вас то, что жизнь без спринга существует, и иногда это даже намного лучше чем с ним. Конечно, всё очень индивидуально. Но! Просто перед тем как начинить новый проект, надо задать себе 3 вопроса:
                                                                                                            1. Что будет делать у меня на проекте спринг.
                                                                                                            2. Все ли сложные случаи он покроет, или надо будет писать костыли для него же.
                                                                                                            3. Какая есть альтернатива для решения этих задач.
                                                                                                            Посмотреть на эти альтернативы, возможно они намного лучше подойдут вам чем тот-же спринг.
                                                                                                            • +1
                                                                                                              Вот это и есть DI, это и делает Spring :)
                                                                                                              Sender у вас какбы контекст из Spring.
                                                                                                              • +1
                                                                                                                Уж лучше я в коде проверю кондишн и обращусь к нужной реализации, чем буду цеплять для этого спринг. Тем более что кондишены для получения реализации в рантайме там насколько ужасно и не очевидно сделаны, что приходится каждому новому разработчику объяснять как оно работает. А если это одноразовое изменение — это вообще не проблема. И ничего не надо переписывать, максимум — пару строчек кода. Да и за всё время таких случаев почти не было.
                                                                                                                • +1

                                                                                                                  но то DI от Spring, который какой-то магический, а тут свой, родной и понятный

                                                                                                                  • 0
                                                                                                                    Если у вас есть реальная потребность в DI — есть много других библиотек, которые нормально справляются с этой задачей. Тот же Google Guice.
                                                                                                              • 0
                                                                                                                С конструкторами мне не очень нравится, потому что иногда синглтонов может быть много, и тогда конструктор становится большим и принимать много параметров, и это становится не удобным и не красивым кодом.

                                                                                                                Тут как бы звоночек о том, что надо подумать над архитектурой класса, т.к. он стал брать на себя слишком много. Но не всегда, конечно, можно/нужно разбивать класс на несколько. Тогда может прийти на помощь Lombok, если все поля — инжекты бинов. Будет что-то вроде:
                                                                                                                @Service
                                                                                                                @AllArgsConstructor
                                                                                                                public class MyFatService {
                                                                                                                    private final SomeRepository someRepository;
                                                                                                                    private final SomeBean2 someBean1;
                                                                                                                	...
                                                                                                                    private final SomeBean10 someBean10;
                                                                                                                	
                                                                                                                    // Дальше код
                                                                                                                }
                                                                                                                

                                                                                                                В этом случае никаких @Autowired и никаких конструкторов не нужно.