Обновить
4
0

Software Engineer | Java / JS / Android / AEM

Отправить сообщение
Так вот ценность DI тут в том, что это просто механизм общения между нашим кодом и Spring Security. И простой заменой реализации DI на Guice не добиться, чтобы Spring Security тоже начал его использовать. А если в этом новом DI не будет интеграции со всеми библиотеками Spring-а, то и ценность его сильно падает.
Когда говорится про то, чтобы заменить Spring DI на тот же Guice обычно предполагается, что Spring полностью уйдет из проекта. Spring Security – это отличная штука, но часто она бывает избыточной. Особенно с появлением JWT и его популяризацией. Далеко не во многих проектах необходима система ролей и ограничение доступов прям на методах, часто достаточно просто сделать фильтрацию для URI.

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

Более того, создание интерфейса, если у него лишь одна реализация — считается плохой практикой.
Depends on… Если класс используется для внутренних целей – да, это плохая практика, но тут и DI становится не нужным. Но если он нужен для связывания отдельных модулей, то даже с единственной реализацией – это будет хорошая практика.

ps: Spring – это хороший фреймворк, но многие его возводят в «абсолют» и приравнивают Java == Spring, что в корне не верно. Да, на нем можно быстро собрать «шаблонное» приложение и оно будет работать вполне вменяемо по ресурсам и по производительности. Но есть задачи, которые требуют меньшего расхода ресурсов и большей производительности на выходе, в этом случае Spring не стоит использовать.
sBody.splice(0,1); //Удаляем хвост.

почему не pop / unshift (в зависимости от того, где у змеи голова)?

ps: можно же и не перерисовывать всю змейку (или весь экран) каждый раз, достаточно очистить хвост и дорисовать голову ;-)
Если смотреть на те проекты где я работал со spring boot, там есть польза. В проекте 50-100 файлов и все само в кучу собирается. Красиво и удобно, нету тонны кода для ручного создания всего кода.
ps: но это было удобно только потому, что нужно было получить результат быстро и не париться с веб-фреймворками.

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

У меня нету однозначного мнения на счет DI — это и хорошо и плохо одновременно.
Можно еще и 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.
это не магия спринга это магия DI.

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

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

Например Java Security Policy позволяет запретить рефлексию (но в этом случае, думаю, весь Spring не будет работать)
если погуглить немного: https://stackoverflow.com/questions/14639753/reflection-security

до релиза там будет все как было, так как они поломают кучу библиотек, а backward-compatibility это главная фишка Java.

С обратной совместимостью будет все хорошо — если запускать приложение «по-старому», все будет работать.
Но если запускать приложения как Модульные — то это уже будет новый функционал и тут уже можно внедрить новые правила, что успешно и сделали.
если погуглить немного: http://in.relation.to/2017/04/11/accessing-private-state-of-java-9-modules/

Не нужно, гуглить в сторону @InjectMocks и MockitoAnnotations.initMocks(this)

Mockito — это замечательная библиотека, не спорю. Именно Mockito и выступает в роли IoC контейнера в тестах. Или если это правильное Spring Boot приложение с тестами, — там будет свой Spring Boot IoC for Tests.
ps: Проблемы тестирования через Mockito достойны целой статьи.

И чем же это плохо? При setAccessible(true) у вас перформенс будет почти тот же, что и при сеттере.

Это замечательный вопрос!
Во-первых, в этом случае приватное поле становится публичным, а это уже минус для оптимизации.
Во-вторых, final поле прекращает быть final, а это в свою очередь значит, что оптимизации, которые связаны с final полями уже не будут работать, а так же, что объект не может быть по-нормальному расшарен между потоками и нужно делать синхронизации.
В-третьих, это нарушение целостности и безопасности, когда приватное поле, вдруг становится публичным в рантайме и используется не через публичный API класса.

К слову, добавлю еще один пункт:
6. Классы, которые используют инъекцию зависимостей в поля (@Inject, @Autowired, Resource etc.) нельзя будет переиспользовать без IoC контейнера. Это не самая большая проблема, но она тоже существует.
1. Инжект в приватное поле требует поставить field.setAccessible(true), которые не всегда возможен.
2. Начиная с Java 9 field.setAccessible(true) — будет не всегда доступен (если не будет выключен полностью).
3. Начиная с Java 10 — его собирались выключить полностью или еще больше ограничить.

4. Инжект в поле класса — это прямой путь в ад в мир, где ты не можешь работать с объектом без рефлексии и без контейнеров. Чтобы выполнить трифиальный тест — нужно подымать контейнер для того, чтобы заинжектить поле!!!

5. Инжект в поле класса не дает возможности сделать оптимизацию по кешированию конструкторов (см. метод референс) и заставляет всегда выполнять инжект только через рефлексию.
Для человека, который имеет опыт и багаж знаний — это действительно не сложно.
А вот для человека, который мало что знает, но хочет «войти в ИТ» и стоит на раздолье: C# | Java | PHP | JS | Python — это будет страшно и не понятно, в конечном случае, выберет то, что будет проще выучить ;-)

И плевать, что WAR и энтерпрайз сервера — это «просто». Новичек не захочет тратить полгода на изучение сервера и всех его внутренностей, чтобы написать свое первое простое приложение. Он захочет «тык-тык и в продакшен!». И он будет прав(((
Соответственно, в случаях, когда нужно прочитать, то, что только что записали — этот подход не очень хорош.

В этом случае нужно будет бороться с CQRS:
1. ждем, пока база синхронизируется (долгий/очень долгий запрос команды)
2. делаем «синхронизацию» руками (сложный и скользкий путь, с множеством проблем)

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

Правильно?
т.е. останется всего лишь решить «тривиальный» вопрос репликации WriteDB -> ReadDB, чтобы чтение всегда было консистентным?
Если я правильно понял автора, его цель была развеять миф, что Java for Web — это сложно.
Правда, текста сильно вышло. Можно было сделать короче на 20% — эффект был бы лучше, по-моему.
С другой стороны, если вероятность попадания в разные поколения низкая — тогда раскидывание по коду обнуления ссылок приводит к выполнению лишних инструкций.

К примеру для young generation проще скопировать малое количество живых объектов и «зачистить» всю область. Если не делать пуллинг — это должно быть дешевле (был на эту тему даже доклад).
Спасибо за статью, Вы всегда интересные темы освящаете, которых не так много на хабре.

ps: А что за игра на первой картинке? Есть ли возможность посмотреть на нее?
В интернете есть куча информации обо всем. Даже про java sockets.

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

При построении этой «картинки» все проблемные места всплывают сами по себе. Если схема получается сложной — значит в архитектуре есть проблемы, а в процессе объяснения схемы сразу всплывают все костыли («вот этот аппендикс нужен для...»).

Совет с картинками применим вообще к любому проектированию, а не только к данной статье.
Конструктив:
1. Все исходники следует перенести на GitHub (или подобный)
2. Сделать больше упор на Архитектуру с картинками, переходами и анализом каждого из вариантв, нежели на сам код.
3. Если хотите разобрать тему полностью, то следует сразу создать заготовку под серию статей:
3.1. Old IO (java.net) — ваши однопоточный и многопоточный серверы: синхронные с кучей потоков
3.2. New IO (java.nio) — асинхронный сервер
3.3. netty.io — рассмотреть архитектуру и показать пример

Сейчас Вы рассматриваете ту часть java network, которая уже морально устарела. Old IO следует рассматривать только в ознакомительных целях, а любые продакшн решения должны строиться на NIO.
Трансдьюсер, или как написать абстрактную фабрику абстрактных фабрик в функциональном стиле!

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

ps: в любом случае, прежде чем внедрять такой подход стоит лишний раз подумать, стоит ли так сильно усложнять систему (поддержку) и какой профит от этого будет?
Если в Firefox сборщик мусора достаточно неплохо справляется, то в Chrome он явно отлынивает от работы
И правильно делает!

Вы смотрите на график с точки зрения пользователя PC, который подключен к розетке и возможно страдает от нехватки RAM. В этом случае «оптимизация» GC выглядит круто!

Но с другой стороны, из-за вашего решения, пользователи смартфонов и ноутбуков начинают судорожно искать зарядное устройство и розетку, потому как вместо того, чтобы «отлынивать» браузер в панике пинает GC, чтобы тот освободил целых ~20 Мб памяти!

Не стоит забывать, что уже сейчас в вебе больше 50% — мобильные пользователи, и дальше эта цифра будет только рости. Возможно ваш плагин и работает для десктопных браузеров, но они так же запускаются на ноутбуках, которым важна автономность. Автономность 1-3 часа без розетки — это очень больно :-(
Посмотрел код, думаю, Вам будет полезно почитать вот такой туториал по SPI:
https://docs.oracle.com/javase/tutorial/ext/basics/spi.html «Система плагинов» из коробки =)

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

Кода будет меньше, код будет чище, плагины и модульность проекта из коробки.
А вас не смущает, что в пакете поставки JDK уже есть утилита JConsole, которая выполняет совершенно другую роль? Перед прочтением статьи, было мнение, что статья будет именно про эту утилиту.

Информация

В рейтинге
Не участвует
Откуда
Киев, Киевская обл., Украина
Зарегистрирован
Активность