Терминатор, Чужой, Нечто ... какие классные статьи про съёмки фильмов выходят последнее время, не нарадоваться! Я только на днях пересмотрел после прочтения статьи все 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 один релиз, критичного ничего не добавляли, зато отношение было бы куда лучше. ИМХО.
Я вас понял. Что тут можно сказать ... одной такой ситуацией в стране больше, одной меньше. Да, с точки зрения закона преступление. По-хорошему, либо наказывать, но тогда кто-то должен это как-то проинициировать (но пока, похоже, это никому не интересно сделать), либо наоборот -- легализовать.
Аналогичных ситуаций в стране множество -- взять тех же застройщиков или ремонтников, что работают в черную, хотя должны платить налоги, или мб даже какие-то "серые программистские галеры". Нарушения закона, которые всеми соблюдаются и никак не наказываются, плюс время от времени появляются новые. Но, как я думаю, прокат спираченных фильмов -- это не самая большая проблема в стране, при появлении которой нужно тут же начинать с ней бороться, бросив всё.
При желании, вы можете сходить на такой фильм и написать заявление на незаконность происходящего.
Ну, самоопределение в маргиналы или не в них -- тоже дискуссионный вопрос. В каких-то странах могут смотреть только пиратское, в т.ч. и в кинотеатрах, в каких-то -- смотреть дома пиратку тоже будет зашкваром. Мир богат и разнообразен. Даже нахождение посередине будет восприниматься маргинальностью как со стороны одного края, так и со стороны другого.
Про "стандартное": скорее не так. Я не советую воровать. Меня тоже не очень радует ситуация, куда всё идёт. Но, оказавшись в какой-то не очень комфортной ситуации (или находясь в ней долгое время) не имеет смысла её отрицать, пытаться не видеть. А попытки указать на объективное её наличие -- её поддержкой.
Применительно к кинотеатрам. Год назад кинотеатры процветали, было много фильмов, зрителей, стало много и самих кинотеатров, и каких-то сопутствующих им вещей, та же продажа попкорна, условно. Рынок вырос и на нём были трудовые места. Сейчас всё упало, а людям надо платить зарплату. Или увольнять, увеличивая безработицу. Вот можем мы с вами гарантировано сказать, что все кинотеатры наживаются на пиратских показах, или все они делают это, чтобы поддержать оборот и людей на рабочих местах? Истина будет где-то посередине, но в обсуждениях обычно рассматриваются только крайности.
Детей обычно учат идеалам, так принято. По мере взросления обычно приходит понимание о неидеальности мира. Невозможно быть сильно правильнее других. Можно быть немного правильнее и подталкивать других в сторону правильности. Если все воруют, а вы нет -- долго не протянете. Если воруют немногие, то скорее всего можно жить не воруя. И в целом как система стремиться к постепенному уменьшению воровства и сведению его на нет.
Добавлю, что читать длинные строки трудно. Вместо того, чтобы читать код в плоскости высота+ширина (и тем более листать вправо), легче воспринимаются более вертикальные, одноразмерные конструкции. IMHO, в примере выше разбиение по строкам несколько помогает.
А вообще, тут ещё режет не длина, а отсутствие смысла. Смесь смысла и не-смысла. Если вместо абстрактных superLongVarNameWithAdditionalInfo и anotherOneLongVarName подставить бизнесовые смыслы, внезапно формула становится эмоционально приятнее.
Терминатор, Чужой, Нечто ... какие классные статьи про съёмки фильмов выходят последнее время, не нарадоваться! Я только на днях пересмотрел после прочтения статьи все 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 один релиз, критичного ничего не добавляли, зато отношение было бы куда лучше. ИМХО.
Ломбок прекрасная вещь :)
Пришлось читать примерно три дня :)
Классное время было :)
Я вас понял. Что тут можно сказать ... одной такой ситуацией в стране больше, одной меньше. Да, с точки зрения закона преступление. По-хорошему, либо наказывать, но тогда кто-то должен это как-то проинициировать (но пока, похоже, это никому не интересно сделать), либо наоборот -- легализовать.
Аналогичных ситуаций в стране множество -- взять тех же застройщиков или ремонтников, что работают в черную, хотя должны платить налоги, или мб даже какие-то "серые программистские галеры". Нарушения закона, которые всеми соблюдаются и никак не наказываются, плюс время от времени появляются новые. Но, как я думаю, прокат спираченных фильмов -- это не самая большая проблема в стране, при появлении которой нужно тут же начинать с ней бороться, бросив всё.
При желании, вы можете сходить на такой фильм и написать заявление на незаконность происходящего.
Ну, самоопределение в маргиналы или не в них -- тоже дискуссионный вопрос. В каких-то странах могут смотреть только пиратское, в т.ч. и в кинотеатрах, в каких-то -- смотреть дома пиратку тоже будет зашкваром. Мир богат и разнообразен. Даже нахождение посередине будет восприниматься маргинальностью как со стороны одного края, так и со стороны другого.
Про "стандартное": скорее не так. Я не советую воровать. Меня тоже не очень радует ситуация, куда всё идёт. Но, оказавшись в какой-то не очень комфортной ситуации (или находясь в ней долгое время) не имеет смысла её отрицать, пытаться не видеть. А попытки указать на объективное её наличие -- её поддержкой.
Применительно к кинотеатрам. Год назад кинотеатры процветали, было много фильмов, зрителей, стало много и самих кинотеатров, и каких-то сопутствующих им вещей, та же продажа попкорна, условно. Рынок вырос и на нём были трудовые места. Сейчас всё упало, а людям надо платить зарплату. Или увольнять, увеличивая безработицу. Вот можем мы с вами гарантировано сказать, что все кинотеатры наживаются на пиратских показах, или все они делают это, чтобы поддержать оборот и людей на рабочих местах? Истина будет где-то посередине, но в обсуждениях обычно рассматриваются только крайности.
Когда-нибудь дойдут до рефинансирования, интересно? Или если "успел" купить, всё, на крючке?
Детей обычно учат идеалам, так принято. По мере взросления обычно приходит понимание о неидеальности мира. Невозможно быть сильно правильнее других. Можно быть немного правильнее и подталкивать других в сторону правильности. Если все воруют, а вы нет -- долго не протянете. Если воруют немногие, то скорее всего можно жить не воруя. И в целом как система стремиться к постепенному уменьшению воровства и сведению его на нет.
Имхо :)
Добавлю, что читать длинные строки трудно. Вместо того, чтобы читать код в плоскости высота+ширина (и тем более листать вправо), легче воспринимаются более вертикальные, одноразмерные конструкции. IMHO, в примере выше разбиение по строкам несколько помогает.
А вообще, тут ещё режет не длина, а отсутствие смысла. Смесь смысла и не-смысла. Если вместо абстрактных superLongVarNameWithAdditionalInfo и anotherOneLongVarName подставить бизнесовые смыслы, внезапно формула становится эмоционально приятнее.
Но в целом, конечно, да. Короткие скоупы -- очень хорошо. Иногда и i имеет право на жизнь, хотя я стараюсь всё-таки писать orderId :)