Если не делать апгрейд инкрементально и копить большую кучу нерешённых проблем, то при появлении в старых версиях очередного Log4Shell внезапно можно приплыть.
Мы на проекте, чтобы избежать всего этого, включили sping-hibernate-query-utils в режиме exception, чтобы никаких N+1 не прошло. Сейчас надежда на тесты и QA, чтобы исключение не дошло до боя.
В хибернейте есть проперти, которая будет ещё другой исключение кидать при попытке пагинации в памяти, вот её тоже хотим включить скоро, и отловить эти вредные места.
Пока наше решение это одновременно и включённые батчи в пропертях глобально в режиме PADDING, и 2х запросы.
Терминатор, Чужой, Нечто ... какие классные статьи про съёмки фильмов выходят последнее время, не нарадоваться! Я только на днях пересмотрел после прочтения статьи все 4 части Чужих, видимо, сегодня перед сном накрываюсь одеялкой и включаю Нечто ))
Кстати, а мне и 2 часть понравилась. Снято вполне аутентично. Правда смотрел только один раз, когда вышла, сейчас гляну обе вместе.
"Ребят, ревьюю ваш код, у вас тут поиск по email, а на нём индекса нет..."
Похвалить автора, конечно, тоже есть за что, например, что юзает StopWatch, а не сам мерит nanoTime., докер использует. В каждом ревью должно быть что-то позитивное =)
Если кому-то интересно, отчитываюсь за прошедшую зиму:
Ни единой проблемы с эксплуатацией не возникло.
Температура поддерживалась как задано. Возможно, была ниже уставки, тут нужно ПИД добавить, но даже при нескольких кратковременных отключениях света не опустилась ниже нуля.
Внизу под палетой скапливалась влага. Есть желание в будущем под неё насыпать кошачий силиконовый наполнитель, чтобы впитывал.
Картошка сохранилась прекрасно за всё время, а морковка и свёкла после НГ начали подсыхать. Отдам этот садоводческий вопрос в будущем на аутсорс.
Ни одна лампочка не перегорела, ни один рептилический нагреватель не вышел из строя. Даже самый дешёвый USB вентилятор из DNS открутил всю зиму без остановки и вышел из ящика как новенький (так и напишу у него в отзыве).
Данные за всю осень-зиму-весну
На этот год запланировал вторую часть статьи с доработками как самого ящика, так и другой автоматизацией на приусадебном хозяйстве. Надеюсь, что выйдет по отношению к первой части как вторые части Терминатора или Чужого.
Поддерживаю написанное выше, на нашем проекте со временем пришли к тем же выводам. Дополню несколько интересных моментов.
Использовать Spring-контекст гарантированно один раз за прогон всех тестов помогает вот такая простая штука:
@Slf4j
public class FailFastContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private static final AtomicBoolean flag = new AtomicBoolean();
@SuppressFBWarnings("DM_EXIT")
@Override
public void initialize(@NonNull ConfigurableApplicationContext applicationContext) {
boolean error = flag.getAndSet(true);
if (error) {
// throw new IllegalStateException("Second application context start attempt.");
log.error("""
Second application context start attempt.
####################################################
# SECOND APPLICATION CONTEXT START ATTEMPT. #
# ----------------------------------------- #
# Please look upper for the reason why Spring is #
# trying to recreate test context. This can be #
# caused by adding an @Import/@MockBean and some #
# other annotations to the test class. #
# #
# This process will now exit immediately. #
####################################################
""");
System.exit(-1);
}
}
}
Нужно только подложить его в @ContextConfiguration(initializers={...}) на главном тестовом классе приложения BaseApplicationTest (от которого удобно наследовать все непосредственно тестовые классы).
Вызовы своего боевого API совершаем через честный http-клиент. Это даёт небольшие накладные расходы на сериализацию/десериализацию, зато дополнительно покрывает: конфигурацию Jackson (кто не ловил, что Instant сериализуется в массив чисел?), цепочку фильтров (особенно если подложены свои фильтры), настройки приложения (вкл/выкл OSiV?) и т.п. В общем, успешно пройденный тест даёт ещё больше гарантий, чем вызов напрямую контроллеров.
Иногда (в полной мере этого слова) — всё-таки приходится искать способы внедрить какие-то ассерты в кишки боевого кода. Для этого можно придумать отдельный интерфейс, похожий на обычные функциональные (Function, Consumer, Supplier, в зависимости от вашей ситуации), и инжектить в боевой код Optional<ThisInterface> и дёргать в нужном месте. Естественно, в боевом контексте не будет реализации и ничего выполняться не будет. В тестах подкладывать собственную реализацию этого интерфейса, инжектить в свой тестовый класс, использовать. Обычно внутри реализации прячется какой-нибудь Exchange, AtomicReference или какой-то такой примитив для обмена данными.
Не стесняйтесь в тестовом коде писать свои контроллеры, сервисы и даже репозитории. Все они могут помочь не строить костыли. Или можно написать просто класс-accessor для package-private данных в каком-то боевом пакете, просто расположив его в нём же и сделав публичным. Сделать какой-то боевой код (классы, методы) package-private вместо private — может быть приемлемым компромиссом в ряде случаев. Я тогда в комментариях так и пишу "Является package-private для целей тестирования".
Ну и самая пушка в нашем проекте — гарантия от тестовой инфраструктуры в сторону теста, что БД всегда чиста. Требует некоторое время для реализации, даёт некоторые накладные расходы, зато как приятно ощущать, что тест действительно изолирован от остальных. Очень радует и при написании новых, и при исправлении имеющихся.
В заключении хочется повторить Uncle Боба — относитесь к коду своих тестов также, как к боевому, и ни в коем случае не как к коду второго сорта.
Тут есть некий замкнутый круг, что бы понять, что best practice — вот он, нужно сначала узнать основы, в какой-то мере и плохие практики тоже нужно сначала увидеть.
Все эти номера версий с уже давно почившим временем жизни оставляют какую-то неприятную нотку. От 16 до 17 один релиз, критичного ничего не добавляли, зато отношение было бы куда лучше. ИМХО.
Они просто ногами дёргали ))
https://habr.com/ru/companies/getmatch/articles/693254/
Говорите, как адвентист :)
Никто не запрещает попробовать EAP / триалка ;)
Аналогично, не смог победить. Особенно проблема, если корневая помка в подпапке. Issue открыт несколько лет.
Вроде это обошёл новой фейковой помкой в корне, но столкнулся с отсутствием поддержки --enable-preview фич. Завел Issue.
Если не делать апгрейд инкрементально и копить большую кучу нерешённых проблем, то при появлении в старых версиях очередного Log4Shell внезапно можно приплыть.
Мы на проекте, чтобы избежать всего этого, включили sping-hibernate-query-utils в режиме exception, чтобы никаких N+1 не прошло. Сейчас надежда на тесты и QA, чтобы исключение не дошло до боя.
В хибернейте есть проперти, которая будет ещё другой исключение кидать при попытке пагинации в памяти, вот её тоже хотим включить скоро, и отловить эти вредные места.
Пока наше решение это одновременно и включённые батчи в пропертях глобально в режиме PADDING, и 2х запросы.
Эх, жаль, что для моего Asus wl-520gc нет новой прошивки :)
Проектов на Kotlin и Spring Data JPA не существует?!?
Терминатор, Чужой, Нечто ... какие классные статьи про съёмки фильмов выходят последнее время, не нарадоваться! Я только на днях пересмотрел после прочтения статьи все 4 части Чужих, видимо, сегодня перед сном накрываюсь одеялкой и включаю Нечто ))
Кстати, а мне и 2 часть понравилась. Снято вполне аутентично. Правда смотрел только один раз, когда вышла, сейчас гляну обе вместе.
Спасибо, продолжайте =)
О, господи, сколько всего собрано в одном месте! Я попробую самые крупные огрехи хотя бы указать:
Банальный вывод статьи. Делать много запросов дороже, чем один - это очень важное сообщение от КО.
Использовать System.out.println, когда уже есть логгер (
@Slf4jвисит над классом).Логирование 10к запросов в консоль, к слову, тоже влияет на результат ;)
Сразу же в application.yaml отключит OSiV.
На сущности висит Data, читать классическую статью https://thorben-janssen.com/lombok-hibernate-how-to-avoid-common-pitfalls/.
Можно побенчмаркать хотя бы JMeter-ом.
"Ребят, ревьюю ваш код, у вас тут поиск по email, а на нём индекса нет..."
Похвалить автора, конечно, тоже есть за что, например, что юзает StopWatch, а не сам мерит nanoTime., докер использует. В каждом ревью должно быть что-то позитивное =)
Если кому-то интересно, отчитываюсь за прошедшую зиму:
Ни единой проблемы с эксплуатацией не возникло.
Температура поддерживалась как задано. Возможно, была ниже уставки, тут нужно ПИД добавить, но даже при нескольких кратковременных отключениях света не опустилась ниже нуля.
Внизу под палетой скапливалась влага. Есть желание в будущем под неё насыпать кошачий силиконовый наполнитель, чтобы впитывал.
Картошка сохранилась прекрасно за всё время, а морковка и свёкла после НГ начали подсыхать. Отдам этот садоводческий вопрос в будущем на аутсорс.
Ни одна лампочка не перегорела, ни один рептилический нагреватель не вышел из строя. Даже самый дешёвый USB вентилятор из DNS открутил всю зиму без остановки и вышел из ящика как новенький (так и напишу у него в отзыве).
На этот год запланировал вторую часть статьи с доработками как самого ящика, так и другой автоматизацией на приусадебном хозяйстве. Надеюсь, что выйдет по отношению к первой части как вторые части Терминатора или Чужого.
Тоже за 2 недели раза три помог мне найти решение, над которым не хотелось ломать голову.
Ухи, ухи ...
Поддерживаю написанное выше, на нашем проекте со временем пришли к тем же выводам. Дополню несколько интересных моментов.
Использовать Spring-контекст гарантированно один раз за прогон всех тестов помогает вот такая простая штука:
Нужно только подложить его в
@ContextConfiguration(initializers={...})на главном тестовом классе приложения BaseApplicationTest (от которого удобно наследовать все непосредственно тестовые классы).Вызовы своего боевого API совершаем через честный http-клиент. Это даёт небольшие накладные расходы на сериализацию/десериализацию, зато дополнительно покрывает: конфигурацию Jackson (кто не ловил, что Instant сериализуется в массив чисел?), цепочку фильтров (особенно если подложены свои фильтры), настройки приложения (вкл/выкл OSiV?) и т.п. В общем, успешно пройденный тест даёт ещё больше гарантий, чем вызов напрямую контроллеров.
Иногда (в полной мере этого слова) — всё-таки приходится искать способы внедрить какие-то ассерты в кишки боевого кода. Для этого можно придумать отдельный интерфейс, похожий на обычные функциональные (Function, Consumer, Supplier, в зависимости от вашей ситуации), и инжектить в боевой код Optional<ThisInterface> и дёргать в нужном месте. Естественно, в боевом контексте не будет реализации и ничего выполняться не будет. В тестах подкладывать собственную реализацию этого интерфейса, инжектить в свой тестовый класс, использовать. Обычно внутри реализации прячется какой-нибудь Exchange, AtomicReference или какой-то такой примитив для обмена данными.
Не стесняйтесь в тестовом коде писать свои контроллеры, сервисы и даже репозитории. Все они могут помочь не строить костыли. Или можно написать просто класс-accessor для package-private данных в каком-то боевом пакете, просто расположив его в нём же и сделав публичным. Сделать какой-то боевой код (классы, методы) package-private вместо private — может быть приемлемым компромиссом в ряде случаев. Я тогда в комментариях так и пишу "Является package-private для целей тестирования".
Ну и самая пушка в нашем проекте — гарантия от тестовой инфраструктуры в сторону теста, что БД всегда чиста. Требует некоторое время для реализации, даёт некоторые накладные расходы, зато как приятно ощущать, что тест действительно изолирован от остальных. Очень радует и при написании новых, и при исправлении имеющихся.
В заключении хочется повторить Uncle Боба — относитесь к коду своих тестов также, как к боевому, и ни в коем случае не как к коду второго сорта.
Тут есть некий замкнутый круг, что бы понять, что best practice — вот он, нужно сначала узнать основы, в какой-то мере и плохие практики тоже нужно сначала увидеть.
Джава ускорилась, и JebBrains приходится больше сил тратить на её поддержку в IDEA, чем развивать Котлин :)
Здесь так много тех, кто любит минусовать и не аргументировать :)
Ждём, пока ломбок подтянется, и в прод!
Все эти номера версий с уже давно почившим временем жизни оставляют какую-то неприятную нотку. От 16 до 17 один релиз, критичного ничего не добавляли, зато отношение было бы куда лучше. ИМХО.