Всем привет!
Иногда возникает необходимость создать ветку в репозитории Git никак не связанную с уже существующими ветками.
Первым делом при такой потребности я хочу процитировать наверное самый популярный ответ на StackOverflow - а вам точно нужно это делать?) В данном случае он справедлив, т.к. не стоит хранить в одном репозитории слабосвязанный код:
а) приложение и его библиотеки
б) код и API\документацию\настройки\скрипты БД если их создают члены команды с разными ролями и разным подходом к код-ревью и слиянию - к примеру разработчики и аналитики
в) наоборот, если API\документацию\настройки\скрипты БД создают одни и те же люди - не стоит их разносить по разным веткам.
Но бывают кейсы, требующие нескольких несвязанных между собой веток. Например, две сильно различающиеся версии приложения.
Есть три способа решить эту задачу.
1) очевидный и неправильный - создать новую ветку на основе существующей, удалить все файлы и залить новые
2) изначально завести ветку c readme.md, от которой можно будет создавать новые чистые ветки
3) выполнить вот такие команды
git checkout --orphan newbranch
git rm -rf .
и далее как обычно.
#git
Иногда возникает необходимость создать ветку в репозитории Git никак не связанную с уже существующими ветками.
Первым делом при такой потребности я хочу процитировать наверное самый популярный ответ на StackOverflow - а вам точно нужно это делать?) В данном случае он справедлив, т.к. не стоит хранить в одном репозитории слабосвязанный код:
а) приложение и его библиотеки
б) код и API\документацию\настройки\скрипты БД если их создают члены команды с разными ролями и разным подходом к код-ревью и слиянию - к примеру разработчики и аналитики
в) наоборот, если API\документацию\настройки\скрипты БД создают одни и те же люди - не стоит их разносить по разным веткам.
Но бывают кейсы, требующие нескольких несвязанных между собой веток. Например, две сильно различающиеся версии приложения.
Есть три способа решить эту задачу.
1) очевидный и неправильный - создать новую ветку на основе существующей, удалить все файлы и залить новые
2) изначально завести ветку c readme.md, от которой можно будет создавать новые чистые ветки
3) выполнить вот такие команды
git checkout --orphan newbranch
git rm -rf .
и далее как обычно.
#git
Всем привет!
Уже говорил про переиспользование кода в общих библиотеках https://t.me/javaKotlinDevOps/137
Поднимемся на уровень выше: возьмем набор библиотек с общим кодом, добавим туда реализацию обязательных архитектурных стандартов, требований сопровождения и безопасности - и получим платформу.
Какой должна быть хорошая платформа? Первый напрашивающийся ответ - смотри на Spring Framework. Но попытаюсь конкретизировать.
1) модульность и минимум зависимостей между модулей. Наверняка есть какое-то ядро, которое часто именно так и называется, обязательное в любом случае. Но подключение остальных модулей должно быть опциональным, пользователь должен понимать зачем ему нужен тот или иной модуль.
2) хорошая документация, cookbook, отвечающий на вопросы: зачем использовать? как подключить? особенности реализации, антипаттерны?
3) работающее синтетическое приложение, каркас, позволяющее в коде увидеть ответы на вопросы из предыдущего пункта. С одной стороны получается дублирование, но учитывая что мы пытаемся "продать" не библиотеку, а целую платформу - код первичен, но одного кода недостаточно, не все можно показать в коде.
4) код и документация должны быть актуальными. Скорее всего на это потребуются отдельные люди, возможно даже отдельная команда. Т.к. разработка платформы скорее всего разделена на команды, команды заточены под свои локальные цели и не смотрят на платформу в целом, в особенности не видят проблем как пользователи.
5) self-service - у бизнес-команды должна быть возможность самостоятельно выполнять любые задачи, не связанные с исправлением багов и доработками компонента платформы. Пример таких задач - регистрация нового потребителя, метаданные для компонентов платформы, валидация скриптов. Самостоятельно - т.е. без тикетов на платформу, без согласований в почте, без встреч с платформенной командой. В идеале - кладем нужные нам стройке в git, далее DevOps pipeline их обрабатывает и результат отражается как результат выполнения джоба. Если есть возможность доработать код платформы самостоятельно - через механизм Inner Source - вообще отлично!)
6) должны быть четко очерчены сроки поддержки старых версий платформы. Естественно, сроки должны соблюдаться
7) API платформенных компонент должен быть единообразным. Хороший пример из Spring - многочисленные xxxTemplate. Или использование application.yml как централизованное место для настроек. За этим должен следить архитектор(ы) и команда, отвечающая за cookbook и синтетическое приложение.
8) платформенные компоненты должны предоставлять заглушки для возможности локальной отладки, информация о них должна быть в cookbook
9) convention over configuration = минимум настроек, которые разработчики должны прописать руками. Как пример - Spring Boot, хотя надо сказать сам Spring пришел к этому не сразу) Конечно каждая бизнес-задача уникальна, но по моему опыту в большинстве случаев достаточно типовой конфигурации с небольшими доработками. Рассмотрим альтернативу: если для поднятия минимального каркаса нужны сотни настроек - никто не будет в них разбираться, все их просто будут копировать. И хорошо, если из последней проверенной версии синтетического приложения.
10) платформа должна своевременно выпускать фиксы уязвимостей. Вроде очевидно, но важно.
11) у платформенной команды есть свой team lead, свой бэклог и главное - свое видение продукта. И это правильно. Но фокус в развитии продукта должен быть на потребителях. Всех потребителях - сопровождение, ИБ и конечно же бизнес-команды. Лично знаю случаи, когда разработчики платформы уходили в бизнес-команды и говорили - да, что-то я не думал, что нашей платформой так сложно пользоваться) Еще кейс - в бизнес-командах изобретено несколько похожих друг на друга "велосипедов", которые по хорошему должны быть в платформе изначально.
#arch #conv_over_conf
Уже говорил про переиспользование кода в общих библиотеках https://t.me/javaKotlinDevOps/137
Поднимемся на уровень выше: возьмем набор библиотек с общим кодом, добавим туда реализацию обязательных архитектурных стандартов, требований сопровождения и безопасности - и получим платформу.
Какой должна быть хорошая платформа? Первый напрашивающийся ответ - смотри на Spring Framework. Но попытаюсь конкретизировать.
1) модульность и минимум зависимостей между модулей. Наверняка есть какое-то ядро, которое часто именно так и называется, обязательное в любом случае. Но подключение остальных модулей должно быть опциональным, пользователь должен понимать зачем ему нужен тот или иной модуль.
2) хорошая документация, cookbook, отвечающий на вопросы: зачем использовать? как подключить? особенности реализации, антипаттерны?
3) работающее синтетическое приложение, каркас, позволяющее в коде увидеть ответы на вопросы из предыдущего пункта. С одной стороны получается дублирование, но учитывая что мы пытаемся "продать" не библиотеку, а целую платформу - код первичен, но одного кода недостаточно, не все можно показать в коде.
4) код и документация должны быть актуальными. Скорее всего на это потребуются отдельные люди, возможно даже отдельная команда. Т.к. разработка платформы скорее всего разделена на команды, команды заточены под свои локальные цели и не смотрят на платформу в целом, в особенности не видят проблем как пользователи.
5) self-service - у бизнес-команды должна быть возможность самостоятельно выполнять любые задачи, не связанные с исправлением багов и доработками компонента платформы. Пример таких задач - регистрация нового потребителя, метаданные для компонентов платформы, валидация скриптов. Самостоятельно - т.е. без тикетов на платформу, без согласований в почте, без встреч с платформенной командой. В идеале - кладем нужные нам стройке в git, далее DevOps pipeline их обрабатывает и результат отражается как результат выполнения джоба. Если есть возможность доработать код платформы самостоятельно - через механизм Inner Source - вообще отлично!)
6) должны быть четко очерчены сроки поддержки старых версий платформы. Естественно, сроки должны соблюдаться
7) API платформенных компонент должен быть единообразным. Хороший пример из Spring - многочисленные xxxTemplate. Или использование application.yml как централизованное место для настроек. За этим должен следить архитектор(ы) и команда, отвечающая за cookbook и синтетическое приложение.
8) платформенные компоненты должны предоставлять заглушки для возможности локальной отладки, информация о них должна быть в cookbook
9) convention over configuration = минимум настроек, которые разработчики должны прописать руками. Как пример - Spring Boot, хотя надо сказать сам Spring пришел к этому не сразу) Конечно каждая бизнес-задача уникальна, но по моему опыту в большинстве случаев достаточно типовой конфигурации с небольшими доработками. Рассмотрим альтернативу: если для поднятия минимального каркаса нужны сотни настроек - никто не будет в них разбираться, все их просто будут копировать. И хорошо, если из последней проверенной версии синтетического приложения.
10) платформа должна своевременно выпускать фиксы уязвимостей. Вроде очевидно, но важно.
11) у платформенной команды есть свой team lead, свой бэклог и главное - свое видение продукта. И это правильно. Но фокус в развитии продукта должен быть на потребителях. Всех потребителях - сопровождение, ИБ и конечно же бизнес-команды. Лично знаю случаи, когда разработчики платформы уходили в бизнес-команды и говорили - да, что-то я не думал, что нашей платформой так сложно пользоваться) Еще кейс - в бизнес-командах изобретено несколько похожих друг на друга "велосипедов", которые по хорошему должны быть в платформе изначально.
#arch #conv_over_conf
Telegram
(java || kotlin) && devOps
Всем привет!
В развитие темы про готовые решения и переиспользование знаний хочу поговорить про переиспользование кода.
Ясно, что все разработчики переиспользуют готовые решения - Spring Framework, Apache Commons да и вообще любые подключаемые к проекту…
В развитие темы про готовые решения и переиспользование знаний хочу поговорить про переиспользование кода.
Ясно, что все разработчики переиспользуют готовые решения - Spring Framework, Apache Commons да и вообще любые подключаемые к проекту…
Всем привет!
Минигайд по кодировкам в Maven.
Для начала - главное, что нужно знать про кодировки в целом:
1) UTF-8 рулит)
2) нужно явно указывать кодировку.
Как это сделать в Maven?
1)
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Работает практически везде, за исключением пунктов 2) и 3) ниже.
2)
<properties>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
Работает для отчетных плагинов. Чтобы не выяснять для каких именно - проще установить и забыть)
3) Переменная среды JAVA_TOOL_OPTIONS равная -Dfile.encoding=UTF8
Работает тогда, когда Maven запускает отдельный Java процесс, в частности при запуске unit тестов из Maven. Причина падения тестов на Win, до этого успешно работающих на Mac\Lin. Падают из-за другой кодировки по умолчанию в Win.
4) Возможна точечная установка или переопределение кодировки для нужного плагина, например:
а) unit тесты
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>
б) компиляция
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
Как видно из примеров - формат настроек у разных плагинов различается.
#maven
Минигайд по кодировкам в Maven.
Для начала - главное, что нужно знать про кодировки в целом:
1) UTF-8 рулит)
2) нужно явно указывать кодировку.
Как это сделать в Maven?
1)
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Работает практически везде, за исключением пунктов 2) и 3) ниже.
2)
<properties>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
Работает для отчетных плагинов. Чтобы не выяснять для каких именно - проще установить и забыть)
3) Переменная среды JAVA_TOOL_OPTIONS равная -Dfile.encoding=UTF8
Работает тогда, когда Maven запускает отдельный Java процесс, в частности при запуске unit тестов из Maven. Причина падения тестов на Win, до этого успешно работающих на Mac\Lin. Падают из-за другой кодировки по умолчанию в Win.
4) Возможна точечная установка или переопределение кодировки для нужного плагина, например:
а) unit тесты
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>
б) компиляция
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
Как видно из примеров - формат настроек у разных плагинов различается.
#maven
Всем привет!
Еще немного про Maven. Есть несколько способов настроить версию Java в Maven, все они описаны в этой статье - https://www.baeldung.com/maven-java-version
Оптимальным начиная с Java 9 выглядит вариант с указанием
<properties>
<maven.compiler.release>9</maven.compiler.release>
</properties>
т.к. данное свойство заменяет собой три: source, target и bootclasspath. Последнее означает, что начиная с Java 9 все JDK умеют притворяться более ранними версиями с точностью до classpath, т.е. до предоставляемого API. А это важно при переходе на 11-ю и 17-ю Java - в первой выпилили Java EE модули, типа SOAP, во второй - закрыли internal пакеты.
Но это не все, что нужно знать про настройки версии JDK.
Если в проекте есть Kotlin - надежнее явно указать ему версию JDK. Для справки - старые версии Kotlin поддерживали только JDK 6 как target bytecode, потом был период JDK 8, сейчас поддерживается все версии https://kotlinlang.org/docs/maven.html
Настраивается так:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<configuration>
<jvmTarget>1.9</jvmTarget>
По хорошему плагин Kotlin должен переиспользовать maven.compiler.release, но я не нашел подтверждающей это информации.
Второй тонкий момент связан с IDEA. IDEA смотрит на maven.compiler.release, в результате правильно проставляет:
а) Source language level для корневого и дочерних модулей Maven - это можно увидеть в Project Structure -> Modules
б) Target bytecode для всех модулей - Double Shift, далее вбиваем "java compiler".
Но есть еще одна важная опция Project Structure -> Project -> SDK. Она определяет версию JDK, на которой будет собираться проект. Повторюсь, из-за сильных изменений в структуре JDK как минимум в 11 и 17 версиях сборка на более новой JDK может сломаться. Причем из логов причина ошибки будет не ясна(
Так вот, IDEA в данном кейсе игнорирует настройки Maven. Прямого решения у проблемы я не нашел, судя по всему, ребята из IntelliJ считают, что корневой модуль в проекте Maven и проект IDEA это не одно и тоже. И это фича, а не баг)
Но есть обходной путь. Если все или большинство ваших проектов живут на определенной версии JDK, то ее можно выставить в IDEA по умолчанию. Настраивается вот здесь: Double Shift, далее вбиваем "structure for new projects"
#maven #java #kotlin
Еще немного про Maven. Есть несколько способов настроить версию Java в Maven, все они описаны в этой статье - https://www.baeldung.com/maven-java-version
Оптимальным начиная с Java 9 выглядит вариант с указанием
<properties>
<maven.compiler.release>9</maven.compiler.release>
</properties>
т.к. данное свойство заменяет собой три: source, target и bootclasspath. Последнее означает, что начиная с Java 9 все JDK умеют притворяться более ранними версиями с точностью до classpath, т.е. до предоставляемого API. А это важно при переходе на 11-ю и 17-ю Java - в первой выпилили Java EE модули, типа SOAP, во второй - закрыли internal пакеты.
Но это не все, что нужно знать про настройки версии JDK.
Если в проекте есть Kotlin - надежнее явно указать ему версию JDK. Для справки - старые версии Kotlin поддерживали только JDK 6 как target bytecode, потом был период JDK 8, сейчас поддерживается все версии https://kotlinlang.org/docs/maven.html
Настраивается так:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<configuration>
<jvmTarget>1.9</jvmTarget>
По хорошему плагин Kotlin должен переиспользовать maven.compiler.release, но я не нашел подтверждающей это информации.
Второй тонкий момент связан с IDEA. IDEA смотрит на maven.compiler.release, в результате правильно проставляет:
а) Source language level для корневого и дочерних модулей Maven - это можно увидеть в Project Structure -> Modules
б) Target bytecode для всех модулей - Double Shift, далее вбиваем "java compiler".
Но есть еще одна важная опция Project Structure -> Project -> SDK. Она определяет версию JDK, на которой будет собираться проект. Повторюсь, из-за сильных изменений в структуре JDK как минимум в 11 и 17 версиях сборка на более новой JDK может сломаться. Причем из логов причина ошибки будет не ясна(
Так вот, IDEA в данном кейсе игнорирует настройки Maven. Прямого решения у проблемы я не нашел, судя по всему, ребята из IntelliJ считают, что корневой модуль в проекте Maven и проект IDEA это не одно и тоже. И это фича, а не баг)
Но есть обходной путь. Если все или большинство ваших проектов живут на определенной версии JDK, то ее можно выставить в IDEA по умолчанию. Настраивается вот здесь: Double Shift, далее вбиваем "structure for new projects"
#maven #java #kotlin
Baeldung
Setting the Java Version in Maven | Baeldung
Learn about different ways to set the Java version for your Maven project
Всем привет!
Когда-то давно - год назад - у меня была заметка, чем хорош k8s: https://t.me/javaKotlinDevOps/6
Там был упомянут Docker, пришло время подробнее раскрыть, что же дают нам контейнеры. Вообще говоря контейнеры и Docker не одно и тоже, но в данном случае различием можно пренебречь.
1) идентичное окружение на dev, test и prod. Да, JRE уже дает нам уровень абстракции от ОС и железа, и это большой плюс в плане запуска Java в разных ОС. Но есть проблемы:
а) разные версии JDK
б) разные сервера приложений\контейнеры сервлетов
в) разный classpath, часто как следствие предыдущего пункта
г) разные переменные среды
д) разное состояние файловой системы
Все это можно решить, но часто решение дорогое - сложные CD pipeline, долгое время деплоя, сложность поднятия prod-like среды на машине разработчика.
C Docker-ом мы получаем immutable infrastructure - набор ПО, настроек и состояние файловой системы зафиксированы на dev и остаются неизменными дальше.
2) легковесная изоляция сервисов. Контейнеризация обеспечивает изоляцию файловой системы, процессов, сетевых интерфейсов и резервирование ресурсов для каждого запущенного на сервере контейнера. Используются механизмы ядра Linux, подробнее см. https://habr.com/ru/articles/659049/
Ключевой момент тут - легковесная, т.к. технологии изоляции в виде виртуальных машин известны давно. Но виртуальная машина эмулирует железо, что сложно, см. стоимость лицензии VMware, к тому же приводит к достаточно высоким накладным расходам по CPU, памяти и диску. Плюс поверх виртуалки нужна гостевая операционная система, а значит запуск виртуалки - это долго.
3) легкость установки. Т.к в Docker сейчас упаковывается почти все (https://hub.docker.com/search, нужна регистрация), то появляется возможность быстро и без ущерба для компьютера разработчика развернуть необходимое серверное ПО - СУБД, Kafka, кэши, мониторинг... А если данные сервисы нужны для тестов - на помощь приходит Testсontainers https://java.testcontainers.org/ Все это работает на Linux, MacOS и Windows, например, с помощью Docker Desktop https://www.docker.com/products/docker-desktop/ Может возникнуть вопрос - откуда на Windows появились механизмы ядра Linux? Ответ: благодаря технологии WSL - https://learn.microsoft.com/ru-ru/windows/wsl/.
Аналогично на серверах - установка образа проще и стабильнее установки классического серверного ПО.
Если говорить именно о Docker - то в общем то это все, остальные преимущества раскрываются в связке с k8s и Service Mesh.
#docker #k8s
Когда-то давно - год назад - у меня была заметка, чем хорош k8s: https://t.me/javaKotlinDevOps/6
Там был упомянут Docker, пришло время подробнее раскрыть, что же дают нам контейнеры. Вообще говоря контейнеры и Docker не одно и тоже, но в данном случае различием можно пренебречь.
1) идентичное окружение на dev, test и prod. Да, JRE уже дает нам уровень абстракции от ОС и железа, и это большой плюс в плане запуска Java в разных ОС. Но есть проблемы:
а) разные версии JDK
б) разные сервера приложений\контейнеры сервлетов
в) разный classpath, часто как следствие предыдущего пункта
г) разные переменные среды
д) разное состояние файловой системы
Все это можно решить, но часто решение дорогое - сложные CD pipeline, долгое время деплоя, сложность поднятия prod-like среды на машине разработчика.
C Docker-ом мы получаем immutable infrastructure - набор ПО, настроек и состояние файловой системы зафиксированы на dev и остаются неизменными дальше.
2) легковесная изоляция сервисов. Контейнеризация обеспечивает изоляцию файловой системы, процессов, сетевых интерфейсов и резервирование ресурсов для каждого запущенного на сервере контейнера. Используются механизмы ядра Linux, подробнее см. https://habr.com/ru/articles/659049/
Ключевой момент тут - легковесная, т.к. технологии изоляции в виде виртуальных машин известны давно. Но виртуальная машина эмулирует железо, что сложно, см. стоимость лицензии VMware, к тому же приводит к достаточно высоким накладным расходам по CPU, памяти и диску. Плюс поверх виртуалки нужна гостевая операционная система, а значит запуск виртуалки - это долго.
3) легкость установки. Т.к в Docker сейчас упаковывается почти все (https://hub.docker.com/search, нужна регистрация), то появляется возможность быстро и без ущерба для компьютера разработчика развернуть необходимое серверное ПО - СУБД, Kafka, кэши, мониторинг... А если данные сервисы нужны для тестов - на помощь приходит Testсontainers https://java.testcontainers.org/ Все это работает на Linux, MacOS и Windows, например, с помощью Docker Desktop https://www.docker.com/products/docker-desktop/ Может возникнуть вопрос - откуда на Windows появились механизмы ядра Linux? Ответ: благодаря технологии WSL - https://learn.microsoft.com/ru-ru/windows/wsl/.
Аналогично на серверах - установка образа проще и стабильнее установки классического серверного ПО.
Если говорить именно о Docker - то в общем то это все, остальные преимущества раскрываются в связке с k8s и Service Mesh.
#docker #k8s
Telegram
(java || kotlin) && devOps
Чем kubernetes, он же k8s лучше контейнера сервлетов или сервера приложений.
Во-первых под капотом k8s лежит Docker, а значит мы получаем все его плюшки. Не зря k8s называют оркестратором контейнеров. Чем занимается оркестратор?
1) планированиеи ресурсов.…
Во-первых под капотом k8s лежит Docker, а значит мы получаем все его плюшки. Не зря k8s называют оркестратором контейнеров. Чем занимается оркестратор?
1) планированиеи ресурсов.…
Всем привет!
Один из самых больших плюсов Java - ее экосистема. Что я под этим словом понимаю - библиотеки, фреймворки, инструменты для сборки, CI инструменты, клиенты для различных БД, очередей, систем мониторинга и т.д.
Приведу пример.
Есть такая штука Lombok.
У него одна из фичей - аннотация @Value, которая по сути добавляет поддержку records в Java до 14 версии. Еще аналогичная фича - data class в Kotlin. Другими словами, решаем задачу: без boiler plate кода получить иммутабельный класс, служащий только для хранения данных. Для использования как DTO к примеру.
Так вот. Недавно выяснил, что есть еще 2 специализированные библиотеки: AutoValue и Immutables - также решающие данную задачу)
Вот статья со сравнением https://dzone.com/articles/lombok-autovalue-and-immutables
Сравнивай, выбирай. Экосистема.
P.S. В самой статье, к слову поднимается один интересный вопрос - если Lombok получает целевой класс путем генерации байткода, то две другие библиотеки - путем генерации исходного кода. Второй подход на первый взгляд более прозрачный и надежный - сразу видно, что получается в итоге. А с Lombok - получаем "магию" и возможность посмотреть, что получилось под капотом, с помощью опции DeLombok. С другой строны код, который приходится писать самому, в случае Lombok проще.
#java
Один из самых больших плюсов Java - ее экосистема. Что я под этим словом понимаю - библиотеки, фреймворки, инструменты для сборки, CI инструменты, клиенты для различных БД, очередей, систем мониторинга и т.д.
Приведу пример.
Есть такая штука Lombok.
У него одна из фичей - аннотация @Value, которая по сути добавляет поддержку records в Java до 14 версии. Еще аналогичная фича - data class в Kotlin. Другими словами, решаем задачу: без boiler plate кода получить иммутабельный класс, служащий только для хранения данных. Для использования как DTO к примеру.
Так вот. Недавно выяснил, что есть еще 2 специализированные библиотеки: AutoValue и Immutables - также решающие данную задачу)
Вот статья со сравнением https://dzone.com/articles/lombok-autovalue-and-immutables
Сравнивай, выбирай. Экосистема.
P.S. В самой статье, к слову поднимается один интересный вопрос - если Lombok получает целевой класс путем генерации байткода, то две другие библиотеки - путем генерации исходного кода. Второй подход на первый взгляд более прозрачный и надежный - сразу видно, что получается в итоге. А с Lombok - получаем "магию" и возможность посмотреть, что получилось под капотом, с помощью опции DeLombok. С другой строны код, который приходится писать самому, в случае Lombok проще.
#java
DZone
Lombok, AutoValue, and Immutables
I liked Brandon's suggestion of a blog post comparing Project Lombok, AutoValue, and Immutables and this is a post that attempts to do that. I have covered Project Lombok, AutoValue, and Immutables individually with brief overviews, but this post is different…
Всем привет!
Три лайфхака по работе с Maven:
1) чтобы заработала отладка в IDEA при запуске через Maven к примеру unit тестов:
для версий surefire плагина >= 2.14: use -DforkCount=0
http://maven.apache.org/plugins/maven-surefire-plugin/examples/debugging.html
2) запустить цель (goal) на дочернем модуле и всех его детях: maven --projects artifactId --also-make-dependents
Полезно на больших многомодульных проектах. Подбробнее https://maven.apache.org/guides/mini/guide-multiple-modules-4.html
Запускать цель напрямую но дочернем проекте нельзя, т.к в таком случае не применятся настройки из корневого проекта - как Maven, так и к примеру Lombok.
Еще важно - перед тем, как отлаживать дочерний проект нужно проинсталлировать в локальный Maven репозиторий те модули, от которых он зависит. Я про maven install.
3) по умолчанию maven следует принципу fail fast и это правильно) Но если нужно понять, в каком состоянии проект - можно запустить полную сборку игнорирую промежуточные ошибки до окончания сборки: maven --fail-at-end
#maven #java
Три лайфхака по работе с Maven:
1) чтобы заработала отладка в IDEA при запуске через Maven к примеру unit тестов:
для версий surefire плагина >= 2.14: use -DforkCount=0
http://maven.apache.org/plugins/maven-surefire-plugin/examples/debugging.html
2) запустить цель (goal) на дочернем модуле и всех его детях: maven --projects artifactId --also-make-dependents
Полезно на больших многомодульных проектах. Подбробнее https://maven.apache.org/guides/mini/guide-multiple-modules-4.html
Запускать цель напрямую но дочернем проекте нельзя, т.к в таком случае не применятся настройки из корневого проекта - как Maven, так и к примеру Lombok.
Еще важно - перед тем, как отлаживать дочерний проект нужно проинсталлировать в локальный Maven репозиторий те модули, от которых он зависит. Я про maven install.
3) по умолчанию maven следует принципу fail fast и это правильно) Но если нужно понять, в каком состоянии проект - можно запустить полную сборку игнорирую промежуточные ошибки до окончания сборки: maven --fail-at-end
#maven #java
maven.apache.org
Maven Surefire Plugin – Debugging Tests
Всем привет!
В последние годы стала "модной" тема null safety. Суть в том, что не нужно хранить и передавать null значения, чтобы не напороться на Null Pointer Exception. В том же Kotlin null safety встроена в язык - все типы по умолчанию не могут содержать null.
И на самом деле это правильный подход. Но есть нюансы)
Рассмотрим такой случай - мы идем куда-то за данными, данные по бизнес-процессу там обязаны быть. Например, мы прихранили id записи где-то в пользовательском контексте в начале процесса и идем за данными в конце процесса. Но данных нет. Следуя null safety можно просто создать пустой объект - например, с помощью конструктора. Как вариант, часть полей этого объекта будет проинициализирована значениями по умолчанию.
Так вот - в случае, когда данных нет из-за какой-то нештатной редко воспроизводимой ситуации: неверные тестовые данные, на сервис идет атака с перебором всех возможных значений, в процессе операции данные некорректно мигрировали, кривая архитектура - лучше просто "упасть", т.е. выбросить исключение. Есть такой принцип - fail fast. Т.к. создавая пустой объект, мы во-первых надеемся что он будет корректно обработан выше, а это может быть не так. А во-вторых - а зачем передавать управление дальше?
P.S. Как всегда - напомню каждую ситуацию нужно рассматривать индивидуально, чтобы различать отсутствие данных как часть бизнес-процесса и нештатную ситуацию.
#kotlin #code #patterns #principles #nullsafety #fail_fast
В последние годы стала "модной" тема null safety. Суть в том, что не нужно хранить и передавать null значения, чтобы не напороться на Null Pointer Exception. В том же Kotlin null safety встроена в язык - все типы по умолчанию не могут содержать null.
И на самом деле это правильный подход. Но есть нюансы)
Рассмотрим такой случай - мы идем куда-то за данными, данные по бизнес-процессу там обязаны быть. Например, мы прихранили id записи где-то в пользовательском контексте в начале процесса и идем за данными в конце процесса. Но данных нет. Следуя null safety можно просто создать пустой объект - например, с помощью конструктора. Как вариант, часть полей этого объекта будет проинициализирована значениями по умолчанию.
Так вот - в случае, когда данных нет из-за какой-то нештатной редко воспроизводимой ситуации: неверные тестовые данные, на сервис идет атака с перебором всех возможных значений, в процессе операции данные некорректно мигрировали, кривая архитектура - лучше просто "упасть", т.е. выбросить исключение. Есть такой принцип - fail fast. Т.к. создавая пустой объект, мы во-первых надеемся что он будет корректно обработан выше, а это может быть не так. А во-вторых - а зачем передавать управление дальше?
P.S. Как всегда - напомню каждую ситуацию нужно рассматривать индивидуально, чтобы различать отсутствие данных как часть бизнес-процесса и нештатную ситуацию.
#kotlin #code #patterns #principles #nullsafety #fail_fast
Всем привет.
Вопрос знатокам IDEA - что это за фича? Я знаю есть quick fix - и у некоторых из них есть опция - исправить во всем файле. Но тут я даже ничего не сделал) Т.е. IDEA сама нашла нужный enum и сделала import.
P.S. За пыль на экране извиняюсь)
#idea
Вопрос знатокам IDEA - что это за фича? Я знаю есть quick fix - и у некоторых из них есть опция - исправить во всем файле. Но тут я даже ничего не сделал) Т.е. IDEA сама нашла нужный enum и сделала import.
P.S. За пыль на экране извиняюсь)
#idea
Всем привет!
В продолжение темы функциональности IDEA и подготовки кода к code review, см. https://t.me/javaKotlinDevOps/148
Некоторые проверки и исправления можно подвесить на одно из двух событий:
1) на сохранение файла: Alt-Alt - Actions on Save. Рекомендую включить Reformat code и Optimize import.
2) перед commit на Git сервер - открыть окно Commit (Ctrl-K) и нажать там шестеренку. Рекомендую включить Analyze code, Check TODO и если выполнение тестов занимает приемлемое время - то еще и прогон тестов.
Легко заметить, что набор опций в обоих случаях похож, но на сохранении можно включить только те, где фиксы применяются без участия человека. В частности и Cleanup, и Analyze выполняют правила из набора инспекций (Inspections), только в первом случае включаются только те правила, где есть quick fixes, которые можно применить автоматически.
Насчет Cleanup - IMHO его вполне можно включить на commit, главное перепроверить набор активных правил: Shift-Shift - Inspections, а там включить фильтр Cleanup only. К слову - там еще есть профили с набором правил, можно добавить свой.
И еще важный момент - инспекции из IDEA можно запустить из командной строки, и т.об. включить в CI процесс: https://www.jetbrains.com/help/idea/command-line-code-inspector.html
Они частично повторяют проверки SonarQube, но не идентичны им.
#idea #code_review #clean_code #git
В продолжение темы функциональности IDEA и подготовки кода к code review, см. https://t.me/javaKotlinDevOps/148
Некоторые проверки и исправления можно подвесить на одно из двух событий:
1) на сохранение файла: Alt-Alt - Actions on Save. Рекомендую включить Reformat code и Optimize import.
2) перед commit на Git сервер - открыть окно Commit (Ctrl-K) и нажать там шестеренку. Рекомендую включить Analyze code, Check TODO и если выполнение тестов занимает приемлемое время - то еще и прогон тестов.
Легко заметить, что набор опций в обоих случаях похож, но на сохранении можно включить только те, где фиксы применяются без участия человека. В частности и Cleanup, и Analyze выполняют правила из набора инспекций (Inspections), только в первом случае включаются только те правила, где есть quick fixes, которые можно применить автоматически.
Насчет Cleanup - IMHO его вполне можно включить на commit, главное перепроверить набор активных правил: Shift-Shift - Inspections, а там включить фильтр Cleanup only. К слову - там еще есть профили с набором правил, можно добавить свой.
И еще важный момент - инспекции из IDEA можно запустить из командной строки, и т.об. включить в CI процесс: https://www.jetbrains.com/help/idea/command-line-code-inspector.html
Они частично повторяют проверки SonarQube, но не идентичны им.
#idea #code_review #clean_code #git
Telegram
(java || kotlin) && devOps
Всем привет!
Теперь перейдем к рекомендациям для авторов Pull Request (PR), они же Merge Request.
1) не нужно тратить время ревьювера на то, что могут сделать роботы) Я про чистку import и форматирование кода. Рекомендую поставить эти действия на автовыполнение…
Теперь перейдем к рекомендациям для авторов Pull Request (PR), они же Merge Request.
1) не нужно тратить время ревьювера на то, что могут сделать роботы) Я про чистку import и форматирование кода. Рекомендую поставить эти действия на автовыполнение…
Всем привет!
Когда-то давным-давно все, ну или почти все, использовали сборку JDK от Oracle. Хочу рассказать что же изменилось и что можно использовать сейчас.
В 2019 году Oracle изменила лицензионную политику и использовать JDK, а также JRE, бесплатно можно лишь для личных нужд. Версия, которую можно так использовать, получила название OpenJDK. Для коммерческих целей нужно приобретать лицензию, вне зависимости от того, нужна вам поддержка Oracle или нет. Эта версия - Oracle JDK. Кроме лицензионных условий сейчас эти сборки ничем не отличаются. Закон обратной силы не имеет, поэтому все предыдущие сборки можно использовать бесплатно, но любой hotfix JDK после 2019 года попадет под новые условия.
Это была первая проблема. Но кроме нее есть еще одна. Каждая версия OpenJDK от Oracle - это важно, что от Oracle - распространяется только полгода, потом идет переход на новую версию. И патчи выходят только для самой последней версии. Это касается и LTS - версий с долговременной поддержкой. Т.е Oracle OpenJDK 17 патчилась и распространялась полгода, потом стала доступна OpenJDK 18. Для тех, кто всегда готов к обновлениям - гуд) Но это не только лишь все)
Подробнее про это все можно почитать тут https://habr.com/ru/articles/448632/
Что же можно выбрать взамен? Есть довольно много компаний и opensource сообществ, которые берут исходники от Oracle OpenJDK, добавляют туда необходимые патчи, компилируют все это под определенные ОС и процессоры и выпускают для свободного скачивания. Отличаются они по следующим характеристикам:
1) набор версий Java. Как правило у всех есть 3 последние LTS - 8, 11, 17. У большинства есть последняя версия не LTS версия. У некоторых - даже 6-я и 7-я Java! А наличие 6-й Java означает не просто доступность ее для скачивания, но и обратное портирование туда критических патчей.
2) набор поддерживаемых ОС - Linux, Windows, MacOS
3) набор поддерживаемых процессорных архитектур - x64, x86 (32 бита), ARM
4) поддержка из коробки native image https://www.graalvm.org/native-image/
5) поддержка из коробки минималистичного образа Linux - Alpine. Я писал об различиях Docker образов тут https://t.me/javaKotlinDevOps/131
6) формат дистрибутива - инсталлятор, Docker образ. А если говорить про Дinux - поддержка разных менеджеров пакетов - rpm, deb...
7) формат поддержки - как правило он всегда доступен за деньги, но в некоторых случаях - JDK от ИТ гигантов - SAP, Microsoft, Amazon - поддержка доступна только вместе с продуктами этих компаний. Т.е. по сути эти JDK не для всех, а для тех кто использует соответствующее облако или продукт.
Неплохая статья со сравнением - https://bell-sw.com/blog/oracle-java-alternatives-comparison-of-openjdk-distributions
В конце статьи - сравнительная таблица.
Я бы особо выделил Temurin - JDK от Opensource сообщества и Liberica - JDK от российских разработчиков, который по перечисленным выше 7 пунктам обгоняет всех конкурентов.
P.S. Еще один интересный факт: IntelliJ также выпускает свою версию JDK - с доработками для отрисовки IDE UI.
#jdk #java
Когда-то давным-давно все, ну или почти все, использовали сборку JDK от Oracle. Хочу рассказать что же изменилось и что можно использовать сейчас.
В 2019 году Oracle изменила лицензионную политику и использовать JDK, а также JRE, бесплатно можно лишь для личных нужд. Версия, которую можно так использовать, получила название OpenJDK. Для коммерческих целей нужно приобретать лицензию, вне зависимости от того, нужна вам поддержка Oracle или нет. Эта версия - Oracle JDK. Кроме лицензионных условий сейчас эти сборки ничем не отличаются. Закон обратной силы не имеет, поэтому все предыдущие сборки можно использовать бесплатно, но любой hotfix JDK после 2019 года попадет под новые условия.
Это была первая проблема. Но кроме нее есть еще одна. Каждая версия OpenJDK от Oracle - это важно, что от Oracle - распространяется только полгода, потом идет переход на новую версию. И патчи выходят только для самой последней версии. Это касается и LTS - версий с долговременной поддержкой. Т.е Oracle OpenJDK 17 патчилась и распространялась полгода, потом стала доступна OpenJDK 18. Для тех, кто всегда готов к обновлениям - гуд) Но это не только лишь все)
Подробнее про это все можно почитать тут https://habr.com/ru/articles/448632/
Что же можно выбрать взамен? Есть довольно много компаний и opensource сообществ, которые берут исходники от Oracle OpenJDK, добавляют туда необходимые патчи, компилируют все это под определенные ОС и процессоры и выпускают для свободного скачивания. Отличаются они по следующим характеристикам:
1) набор версий Java. Как правило у всех есть 3 последние LTS - 8, 11, 17. У большинства есть последняя версия не LTS версия. У некоторых - даже 6-я и 7-я Java! А наличие 6-й Java означает не просто доступность ее для скачивания, но и обратное портирование туда критических патчей.
2) набор поддерживаемых ОС - Linux, Windows, MacOS
3) набор поддерживаемых процессорных архитектур - x64, x86 (32 бита), ARM
4) поддержка из коробки native image https://www.graalvm.org/native-image/
5) поддержка из коробки минималистичного образа Linux - Alpine. Я писал об различиях Docker образов тут https://t.me/javaKotlinDevOps/131
6) формат дистрибутива - инсталлятор, Docker образ. А если говорить про Дinux - поддержка разных менеджеров пакетов - rpm, deb...
7) формат поддержки - как правило он всегда доступен за деньги, но в некоторых случаях - JDK от ИТ гигантов - SAP, Microsoft, Amazon - поддержка доступна только вместе с продуктами этих компаний. Т.е. по сути эти JDK не для всех, а для тех кто использует соответствующее облако или продукт.
Неплохая статья со сравнением - https://bell-sw.com/blog/oracle-java-alternatives-comparison-of-openjdk-distributions
В конце статьи - сравнительная таблица.
Я бы особо выделил Temurin - JDK от Opensource сообщества и Liberica - JDK от российских разработчиков, который по перечисленным выше 7 пунктам обгоняет всех конкурентов.
P.S. Еще один интересный факт: IntelliJ также выпускает свою версию JDK - с доработками для отрисовки IDE UI.
#jdk #java
Хабр
Java теперь платная? Развенчиваем слухи (или нет?)
Уже 2 дня как вступили в силу изменения лицензионной политики Oracle на распространение сборок Java SE . В среде разработчиков-слоупоков (я тоже в их числе) начали носиться кошмарные слухи. Что...
Всем привет!
Я уже писал про паттерны https://t.me/javaKotlinDevOps/52 и их важность. Но есть штука поважнее паттернов - базовые принципы разработки. Чтобы стало понятнее приведу пример - SOLID.
Почему принципы важнее паттернов? Паттерн - это решение частной задачи. Лично я знаю больше паттернов, чем применял на практике) А в разработке я давно. Принципы же применимы практически к любой задачи.
Тот же S из SOLID - Single Responsibility: дорабатываешь какой-то метода - применим, создаешь новый класс - тоже, делишь код по модулям - аналогично, проектируешь набор микросервисов...
Я не люблю повторять то, что уже хорошо описано в интернете, поэтому вот статья с неплохим описанием - https://skillbox.ru/media/code/eto-klassika-eto-znat-nado-dry-kiss-solid-yagni-i-drugie-poleznye-sokrashcheniya/
Оффтопик - не ожидал от skillbox, обычно все ссылки у меня на Хабр или baeldung.
Что бы я добавил к описанным в статье принципам:
1) null safety. Плюсы: не получишь NullPointerException, не нужен код с проверкой на null, не нужно думать - так, на уровень выше я уже на null проверяю, тут вроде не нужно.. но если в будущем этот метод будет вызываться откуда-то еще. Жаль в Java ее достичь сложно, есть куча библиотек с аннотациями @Null\@NotNull, действуют они по разному, на эту тему можно отдельную статью написать. Важно то, что простого решения в Java нет. Зато есть в Kotlin)
2) иммутабельность. Главный плюс - большая устойчивость к ошибкам. Приведу пример: объект - это ссылка на область в памяти. Где еще в сервисе используется объект - часто быстро определить сложно. Вывод - меняя что-то в переданном в метод объекте можно поломать программу в неожиданном месте. Также неожиданным плюсом может быть большая производительность. Самый очевидный пример - иммутабельность строк. Еще - если у вас есть List и нужно убрать из него лишнее - возможно (возможно, надо проводить тесты!) оптимальнее будет создать новый список с нужными объектами, т.к. каждая модификация существующего - это перемещения в heap. Главное чтобы памяти было много и использовался современный сборщик мусора. Еще плюс - если объект иммутабельный, то его можно спокойно использовать в многопоточной программе. Изменения состояния нет, синхронизация доступа не нужна. Ну и бонусом - иммутабельный объект можно использовать как ключ, в том же HashSet\HashMap. В Java для иммутабельности есть records и final, в Kotlin - data class.
3) понятные наименования - я про переменные, методы, классы. Часто вижу две ошибки. Первая - злоупотребление сокращениями. Вторая - ситуативные названия. Т.е. при реализации конкретной фичи название кажется очевидным для автора кода. Но вот приходит новый разработчик. Он знает только о сервисе в целом, никакую старую аналитику он читать не будет, сразу полезет в код - в итоге многие названия покажутся ему непонятными. Общий принцип - называйте так, чтобы назначение кода было понятно новому разработчику. А любые более менее сложные условия выносите в методы с говорящими названиями. За подробностями - снова порекомендую книгу "Чистый код" Мартина.
#arch #patterns #solid
Я уже писал про паттерны https://t.me/javaKotlinDevOps/52 и их важность. Но есть штука поважнее паттернов - базовые принципы разработки. Чтобы стало понятнее приведу пример - SOLID.
Почему принципы важнее паттернов? Паттерн - это решение частной задачи. Лично я знаю больше паттернов, чем применял на практике) А в разработке я давно. Принципы же применимы практически к любой задачи.
Тот же S из SOLID - Single Responsibility: дорабатываешь какой-то метода - применим, создаешь новый класс - тоже, делишь код по модулям - аналогично, проектируешь набор микросервисов...
Я не люблю повторять то, что уже хорошо описано в интернете, поэтому вот статья с неплохим описанием - https://skillbox.ru/media/code/eto-klassika-eto-znat-nado-dry-kiss-solid-yagni-i-drugie-poleznye-sokrashcheniya/
Оффтопик - не ожидал от skillbox, обычно все ссылки у меня на Хабр или baeldung.
Что бы я добавил к описанным в статье принципам:
1) null safety. Плюсы: не получишь NullPointerException, не нужен код с проверкой на null, не нужно думать - так, на уровень выше я уже на null проверяю, тут вроде не нужно.. но если в будущем этот метод будет вызываться откуда-то еще. Жаль в Java ее достичь сложно, есть куча библиотек с аннотациями @Null\@NotNull, действуют они по разному, на эту тему можно отдельную статью написать. Важно то, что простого решения в Java нет. Зато есть в Kotlin)
2) иммутабельность. Главный плюс - большая устойчивость к ошибкам. Приведу пример: объект - это ссылка на область в памяти. Где еще в сервисе используется объект - часто быстро определить сложно. Вывод - меняя что-то в переданном в метод объекте можно поломать программу в неожиданном месте. Также неожиданным плюсом может быть большая производительность. Самый очевидный пример - иммутабельность строк. Еще - если у вас есть List и нужно убрать из него лишнее - возможно (возможно, надо проводить тесты!) оптимальнее будет создать новый список с нужными объектами, т.к. каждая модификация существующего - это перемещения в heap. Главное чтобы памяти было много и использовался современный сборщик мусора. Еще плюс - если объект иммутабельный, то его можно спокойно использовать в многопоточной программе. Изменения состояния нет, синхронизация доступа не нужна. Ну и бонусом - иммутабельный объект можно использовать как ключ, в том же HashSet\HashMap. В Java для иммутабельности есть records и final, в Kotlin - data class.
3) понятные наименования - я про переменные, методы, классы. Часто вижу две ошибки. Первая - злоупотребление сокращениями. Вторая - ситуативные названия. Т.е. при реализации конкретной фичи название кажется очевидным для автора кода. Но вот приходит новый разработчик. Он знает только о сервисе в целом, никакую старую аналитику он читать не будет, сразу полезет в код - в итоге многие названия покажутся ему непонятными. Общий принцип - называйте так, чтобы назначение кода было понятно новому разработчику. А любые более менее сложные условия выносите в методы с говорящими названиями. За подробностями - снова порекомендую книгу "Чистый код" Мартина.
#arch #patterns #solid
Telegram
(java || kotlin) && devOps
Всем привет!
Давно хотел написать про паттерны/шаблоны программирования. Основной вопрос, возникающий при разговоре про паттерны - какая от них польза? Ведь главное - умеет человек кодить или нет.
С одной стороны паттерны - это лишь часть арсенала программиста.…
Давно хотел написать про паттерны/шаблоны программирования. Основной вопрос, возникающий при разговоре про паттерны - какая от них польза? Ведь главное - умеет человек кодить или нет.
С одной стороны паттерны - это лишь часть арсенала программиста.…
Всем привет!
Сегодня пост про очередной типичный вопрос на собеседовании.
Звучит он так: расскажите про жизненный цикл сборки Maven, он же build lifecycle.
Я вкратце уже писал про это https://t.me/javaKotlinDevOps/10. Но т.к. типичный ответ на собеседовании - перечисление циклов и фаз сборки, то хочется раскрыть тему. На самом деле вопрос про другое - в чем суть цикла сборки?
1) набор фаз сборки JVM проекта уже придуман и зафиксирован умными людьми) из команды Maven в виде Default Lifecycle https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference Т.е. считается, что список покрывает все потребности сборки. Как пример продуманности могу привести фазы pre-integration-test и post-integration-test, которые нужны для того, чтобы поднять и опустить контейнер сервлетов, менеджер очередей или БД до и после фазы интеграционных тестов (integration-test). Для обычных тестов (test) таких вспомогательных фаз нет.
2) последовательность фаз также зафиксирована, порядок менять нельзя да и нет смысла
3) большинство фаз являются опциональными, запускаются только если к фазе подключен хоть один плагин и либо в проекте присутствуют определенные файлы, либо есть настройки плагина, указывающие что ему делать - например, generate-sources или компиляция Kotlin
4) на одной фазе могут работать несколько целей (goal) из разных плагинов - например, компиляция Java и Kotlin на фазе compile или несколько тестовых фреймворков на фазе test
5) запуская определенный шаг сборки - mvn install - вы запускаете все предыдущие шаги цикла. И в большинстве случаев это правильно. Если такое поведение не требуется - нужно запустить конкретную цель у конкретного плагина, для моего примера это mvn install:install (плагин:цель). Т.е. тут совпадают название фазы сборки, плагина и цели. Так бывает не всегда, например, для фазы test-compile цель выглядит так compiler:testCompile
Итого: цель жизненного цикла сборки - стандартизировать процесс сборки.
Да и в принципе стандартизация - конек Maven. Тут и типовой набор папок https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html, и цикл сборки, и сложность написания своего кода для сборки, и достаточно богатый набор стандартных плагинов, для подключения которых ничего не надо делать (если быть точным - неплохо бы зафиксировать версию в pom), и архетипы, и конвенция по наименованию артефактов, и наконец центральный репозиторий - https://mvnrepository.com/repos/central
#maven #interview_question
Сегодня пост про очередной типичный вопрос на собеседовании.
Звучит он так: расскажите про жизненный цикл сборки Maven, он же build lifecycle.
Я вкратце уже писал про это https://t.me/javaKotlinDevOps/10. Но т.к. типичный ответ на собеседовании - перечисление циклов и фаз сборки, то хочется раскрыть тему. На самом деле вопрос про другое - в чем суть цикла сборки?
1) набор фаз сборки JVM проекта уже придуман и зафиксирован умными людьми) из команды Maven в виде Default Lifecycle https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference Т.е. считается, что список покрывает все потребности сборки. Как пример продуманности могу привести фазы pre-integration-test и post-integration-test, которые нужны для того, чтобы поднять и опустить контейнер сервлетов, менеджер очередей или БД до и после фазы интеграционных тестов (integration-test). Для обычных тестов (test) таких вспомогательных фаз нет.
2) последовательность фаз также зафиксирована, порядок менять нельзя да и нет смысла
3) большинство фаз являются опциональными, запускаются только если к фазе подключен хоть один плагин и либо в проекте присутствуют определенные файлы, либо есть настройки плагина, указывающие что ему делать - например, generate-sources или компиляция Kotlin
4) на одной фазе могут работать несколько целей (goal) из разных плагинов - например, компиляция Java и Kotlin на фазе compile или несколько тестовых фреймворков на фазе test
5) запуская определенный шаг сборки - mvn install - вы запускаете все предыдущие шаги цикла. И в большинстве случаев это правильно. Если такое поведение не требуется - нужно запустить конкретную цель у конкретного плагина, для моего примера это mvn install:install (плагин:цель). Т.е. тут совпадают название фазы сборки, плагина и цели. Так бывает не всегда, например, для фазы test-compile цель выглядит так compiler:testCompile
Итого: цель жизненного цикла сборки - стандартизировать процесс сборки.
Да и в принципе стандартизация - конек Maven. Тут и типовой набор папок https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html, и цикл сборки, и сложность написания своего кода для сборки, и достаточно богатый набор стандартных плагинов, для подключения которых ничего не надо делать (если быть точным - неплохо бы зафиксировать версию в pom), и архетипы, и конвенция по наименованию артефактов, и наконец центральный репозиторий - https://mvnrepository.com/repos/central
#maven #interview_question
Telegram
(java || kotlin) && devOps
Всем привет!
Хочу рассказать собрать в одном посте несколько мало и среднеизвестных фичей Maven.
Поехали!
Для начала немного теории. Жизненный цикл сборки = фиксированная последовательность фаз сборки. К фазе сборки можно подключить плагин(ы), а точнее…
Хочу рассказать собрать в одном посте несколько мало и среднеизвестных фичей Maven.
Поехали!
Для начала немного теории. Жизненный цикл сборки = фиксированная последовательность фаз сборки. К фазе сборки можно подключить плагин(ы), а точнее…
Всем привет!
Сегодня пост с картинками, поэтому ловите https://telegra.ph/Urovni-izolyacii-sovremennogo-Java-prilozheniya-07-29
#java #jvm #docker #performance
Сегодня пост с картинками, поэтому ловите https://telegra.ph/Urovni-izolyacii-sovremennogo-Java-prilozheniya-07-29
#java #jvm #docker #performance
Telegraph
Уровни изоляции современного Java приложения
Всем привет! Уже писал про плюсы Docker - https://t.me/javaKotlinDevOps/165 Но все ли так безоблачно?) Обычно, когда сравнивают Docker с виртуальной машиной (VM) приводят такую схему Из нее видно, что Docker - более легковесное решение по сравнению с VM.…
Всем привет!
Нашёл отличное сравнение скорости конкатенации строк разными методами, от + до StringBuffer, StringBuilder и StringJoiner. И даже есть такая экзотика как String.format со стримами.
Для затравки три интересных факта.
1) StringBuffer даже с синхронизацией существенно быстрее обычной конкатенации.
2) String.format очень(!) медленный.
3) скорость обычной конкатенации с увеличением числа строк растёт экспоненциально.
Подробнее тут https://www.baeldung.com/java-string-concatenation-methods
#java #performance #string
Нашёл отличное сравнение скорости конкатенации строк разными методами, от + до StringBuffer, StringBuilder и StringJoiner. И даже есть такая экзотика как String.format со стримами.
Для затравки три интересных факта.
1) StringBuffer даже с синхронизацией существенно быстрее обычной конкатенации.
2) String.format очень(!) медленный.
3) скорость обычной конкатенации с увеличением числа строк растёт экспоненциально.
Подробнее тут https://www.baeldung.com/java-string-concatenation-methods
#java #performance #string
Baeldung
Performance Comparison Between Different Java String Concatenation Methods | Baeldung
Explore different string concatenation methods in Java and evaluate their performance using JMH.
Всем привет!
Про DI и DI.
Аббревиатура DI может расшифровываться на Dependency Inversion, а может как Dependency Injection.
Dependency Inversion - это буква D из SOLID - базовых принципов разработки.
Означает, что высокоуровневые классы не должны зависеть от конкретных реализации, и в Java API любых классов лучше использовать интерфейсы везде, где это возможно. Почему такая ремарка: интерфейс с единственной реализацией - очень странная штука) Но я отвлекся) Следование принципу облегчает тестирование и расширение функциональности системы, т.к. позволяет легко заменить любую реализацию.
Dependency Injection - это механизм внедрения зависимостей, важнейшая особенность которого - собственно внедрение зависимостей отдается на откуп внешнему модулю. Самые известный пример - Spring c его IoC контейнером, но есть и другие заточенные конкретно на эту задачу и поэтому более шустрые альтернативы.
Если подходить формально - это два разных понятия, кроме аббревиатуры никак не связанные. Но с другой стороны Dependency Injection по сути - это инструмент, сильно облегчающий реализацию принципа Dependency Inversion. А хороший инструмент помогает писать правильный код. Важное замечание - Spring IoC не обеспечит за вас реализацию инверсии зависимостей. Если метод API завязывается на конкретную реализацию или уровни приложения связаны циклически - Spring тут не поможет. Поможет предварительное проектирование на уровне кода и TDD.
#code_architecture #interview_question #arch #patterns #solid
Про DI и DI.
Аббревиатура DI может расшифровываться на Dependency Inversion, а может как Dependency Injection.
Dependency Inversion - это буква D из SOLID - базовых принципов разработки.
Означает, что высокоуровневые классы не должны зависеть от конкретных реализации, и в Java API любых классов лучше использовать интерфейсы везде, где это возможно. Почему такая ремарка: интерфейс с единственной реализацией - очень странная штука) Но я отвлекся) Следование принципу облегчает тестирование и расширение функциональности системы, т.к. позволяет легко заменить любую реализацию.
Dependency Injection - это механизм внедрения зависимостей, важнейшая особенность которого - собственно внедрение зависимостей отдается на откуп внешнему модулю. Самые известный пример - Spring c его IoC контейнером, но есть и другие заточенные конкретно на эту задачу и поэтому более шустрые альтернативы.
Если подходить формально - это два разных понятия, кроме аббревиатуры никак не связанные. Но с другой стороны Dependency Injection по сути - это инструмент, сильно облегчающий реализацию принципа Dependency Inversion. А хороший инструмент помогает писать правильный код. Важное замечание - Spring IoC не обеспечит за вас реализацию инверсии зависимостей. Если метод API завязывается на конкретную реализацию или уровни приложения связаны циклически - Spring тут не поможет. Поможет предварительное проектирование на уровне кода и TDD.
#code_architecture #interview_question #arch #patterns #solid
Всем привет!
Есть такой принцип - "безобразно, но единообразно". Если верить интернету, он появился в армии. Но может ли он быть применим к исходному коду и архитектуре?
Ответ - да.
Начну издалека - любой код и архитектура устаревает.
Но это не так страшно если выполняются три условия:
1) хорошо спроектированная гибкая архитектура. Я здесь про архитектуру уровня сервиса\АС. Маленькая ремарка - по отношению к коду термин архитектура плох тем, что в здании архитектуру изменить очень сложно. А в коде - можно.
2) высокое покрытие тестами. Тут все очевидно: много тестов - можно спокойно рефакторить
3) наличие времени для рефакторинга, т.е. другими словами - отсутствие вечного "это надо было сделать еще вчера"
В этом случае сервис можно отрефакторить для адаптации архитектуры к новым требованиям.
И делать это лучше сразу для всего приложения. Чтобы было "единообразно".
Почему так - я уже много об этом писал: изучать код - сложная задача. Один из способов облегчить ее - единообразие архитектуры, в т.ч. наименований, практики применения паттернов, разделения на уровни и модули.
Особенно сильно тяжесть изучения кода бьет по новичкам, но и для "старичков" спустя полгода-год код можно забыть.
В этом плане переделывать выглядящий "безобразно" код в отдельном методе или классе в рамках реализации текущей фичи - плохая идея, т.к. это ухудшит читаемость кода приложения в целом.
Лучше поговорить с бизнесом о рисках, зафиксировать техдолг, выделить на него отдельный технический релиз, согласовать время и все отрефакторить за раз.
Если вам кажется этот вариант фантастическим - понимаю, да, увы, такое бывает.
В этом случае предлагаю рефакторить максимально крупные куски кода вместе с бизнес-фичами. Ну например - модуль в терминах Maven или Gradle. Или набор модулей, относящийся к одному бизнес-процессу, если вы построили маленький монолитик. Или большой)
С монолитами, кстати, хуже всего - именно из-за устаревшей архитектуры, поменять которую разом невозможно, они зачастую и умирают.
При этом неплохо бы где-то рядом с кодом зафиксировать все архитектурные проблемы и план рефакторинга. В файлике типа todo.md в корне проекта. Точно не в wiki или в тикете, т.к. большинство разработчиков в wiki не пойдут.
Также подойдет JavaDoc. Часто он бывает тривиален и не несет ценности. Здесь же ситуация обратная.
Ну и конечно при ползучем рефакторинге поможет расстановка @Deprecated. На них ругается IDEA, SonarQube, они будут мозолить глаза. Это не гарантия того, что код будет поправлен, но уже что-то.
А лучший вариант - технический релиз. И не поосторожнее с монолитами)
P.S. Кстати, сложность рефакторинга является одним из возможных сигналов для разделения монолита на части
#arch #техдолг #refactoring #unittests
Есть такой принцип - "безобразно, но единообразно". Если верить интернету, он появился в армии. Но может ли он быть применим к исходному коду и архитектуре?
Ответ - да.
Начну издалека - любой код и архитектура устаревает.
Но это не так страшно если выполняются три условия:
1) хорошо спроектированная гибкая архитектура. Я здесь про архитектуру уровня сервиса\АС. Маленькая ремарка - по отношению к коду термин архитектура плох тем, что в здании архитектуру изменить очень сложно. А в коде - можно.
2) высокое покрытие тестами. Тут все очевидно: много тестов - можно спокойно рефакторить
3) наличие времени для рефакторинга, т.е. другими словами - отсутствие вечного "это надо было сделать еще вчера"
В этом случае сервис можно отрефакторить для адаптации архитектуры к новым требованиям.
И делать это лучше сразу для всего приложения. Чтобы было "единообразно".
Почему так - я уже много об этом писал: изучать код - сложная задача. Один из способов облегчить ее - единообразие архитектуры, в т.ч. наименований, практики применения паттернов, разделения на уровни и модули.
Особенно сильно тяжесть изучения кода бьет по новичкам, но и для "старичков" спустя полгода-год код можно забыть.
В этом плане переделывать выглядящий "безобразно" код в отдельном методе или классе в рамках реализации текущей фичи - плохая идея, т.к. это ухудшит читаемость кода приложения в целом.
Лучше поговорить с бизнесом о рисках, зафиксировать техдолг, выделить на него отдельный технический релиз, согласовать время и все отрефакторить за раз.
Если вам кажется этот вариант фантастическим - понимаю, да, увы, такое бывает.
В этом случае предлагаю рефакторить максимально крупные куски кода вместе с бизнес-фичами. Ну например - модуль в терминах Maven или Gradle. Или набор модулей, относящийся к одному бизнес-процессу, если вы построили маленький монолитик. Или большой)
С монолитами, кстати, хуже всего - именно из-за устаревшей архитектуры, поменять которую разом невозможно, они зачастую и умирают.
При этом неплохо бы где-то рядом с кодом зафиксировать все архитектурные проблемы и план рефакторинга. В файлике типа todo.md в корне проекта. Точно не в wiki или в тикете, т.к. большинство разработчиков в wiki не пойдут.
Также подойдет JavaDoc. Часто он бывает тривиален и не несет ценности. Здесь же ситуация обратная.
Ну и конечно при ползучем рефакторинге поможет расстановка @Deprecated. На них ругается IDEA, SonarQube, они будут мозолить глаза. Это не гарантия того, что код будет поправлен, но уже что-то.
А лучший вариант - технический релиз. И не поосторожнее с монолитами)
P.S. Кстати, сложность рефакторинга является одним из возможных сигналов для разделения монолита на части
#arch #техдолг #refactoring #unittests