(java || kotlin) && devOps
374 subscribers
6 photos
1 video
7 files
319 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
Всем привет!

Прочитал сегодня хороший пост (английский): https://korshakov.com/posts/death-of-best-practices

Чем же он хорош?
Иллюстрирует 2 мысли, про которые я топлю в своем блоге (и топлю в целом):

1) разработка - искусство компромиссов. Важно не абсолютное следование ... микросервисной архитектуре, принципам Single Responsibility или Dependency Inversion. Нет никакой магии в цифре 80% когда мы говорим о покрытии кода тестами. Денормализация таблиц из той же оперы. Важно выдавать результат, требуемый бизнесов. На код-ревью можно поспорить о принципах, но Pull Request должен быть влит в течение дня

2) быстрые, а следовательно частые релизы - наше все. Или по-менеджерски - Deployment Frequency и Lead Time (а это две грани одной и той же идеи). Это позволяет быстро править баги и уязвимости, адаптироваться к изменениям архитектуры и нормативным требованиям, проводить бета и A\B тестирование, соблюдать сроки выхода фичей.

Что спорно в посте - кликбейтный заголовок. Читать "Чистый код" или "Мифический человеко-месяц" - это не зло. Зло - следовать догматически отдельным идеям из этих книг, не разбираясь, что хотел сказать автор, и не адаптируя их к текущему проекту.

P.S. Тоже что ли кликбейтные заголовки начать делать)

#principles #dev_compomisses
March 24
Всем привет!

Нашел забавную статью о том, как Java превратить в BrainFuck https://ru.wikipedia.org/wiki/Brainfuck
Статья https://habr.com/ru/articles/886080/
Всегда было ощущение, что это на условном Perl можно написать не очень понятную строку кода, выглядящую прилично, а на самом деле форматирующую диск C:) Ну или на Scala на худой конец. А тут Java.

У меня только один вопрос по первому примеру - где код программы, которая подбирала эти магические числа?
А второй отлично показывает, чем может быть вредно Reflection API. Убирать его конечно не надо, но подумать о защите для системных классов стоило бы.

#java
March 25
Качественное ли у вас API? А чем докажете?)

Как мы проверяем код на качество? SonarQube, покрытие кода тестами. Если говорить о code style - CheckStyle-ом. Если говорить об уязвимостях - проверка по базам уязвимостей (разные тулы), Checkmarx.

А можно ли как-то проверить API на соответствие лучшим практикам? В частности, OpenAPI как самый типовой на данный момент вариант.
Да - для этого есть Spectral linter https://meta.stoplight.io/docs/spectral/a630feff97e3a-concepts

У него три основных достоинства:
1) это linter и его можно включить в CI pipeline

2) у него есть наборы предустановленных правил, в частности:
а) OpenAPI rules https://meta.stoplight.io/docs/spectral/4dec24461f3af-open-api-rules
б) URL rules https://apistylebook.stoplight.io/docs/url-guidelines - использование kebab-case, не использование get в URL...
в) OWASP rules https://apistylebook.stoplight.io/docs/owasp-top-10 - безопасность, например, использование uuid вместо чисел в идентификаторах
...

3) возможность добавлять свои правила https://meta.stoplight.io/docs/spectral/01baf06bdd05a-create-a-ruleset в том числе наследуясь от существующих

Ну и отдельно отмечу, что есть плагин для IDEA https://plugins.jetbrains.com/plugin/25989-spectral-linter

Итого - штука полезная, настоятельно рекомендую попробовать.

#api #arch #code_quality
March 27
С чем проще работать - Maven vs Gradle?

Как ни странно - ответ на этот вопрос не очевиден.

Если говорить о чтении глазами разработчиком - Gradle выглядит попроще т.к. там почти нет boilerplate кода. И тот, и другой инструмент придерживаются принципа convention over configuration, но Maven проигрывает из-за xml.

Но если проект начинает развиваться - что-то может пойти не так) Gradle позволяет легко выстрелить себе в ногу создав очень сложный скрипт деплоя. Причем много кода появляется там, где его не ожидаешь - в build скрипте. И этот код не на Java, т.е. может отличаться от кода проекта. А если добавить сюда multiproject - разбираться в этом становится сложно. Maven выносит весь императивный код в плагины, скрипты сборки чисто декларативные.

И можно глянуть с другой стороны - со стороны tooling, например, той же IDEA. Тут победа на стороне Maven - распарсить xml легко, а вот чтобы понять структуру Gradle проекта - нужно начать его исполнять. Это и дольше, и процесс подвержен ошибками, а в теории и уязвимостям.

Вывод - оба инструмента хороши, имеют свои плюсы и минусы. Рекомендую изучить оба. Я для себя не определился)

#buildtool #maven #gradle #conv_over_conf
March 30
Не Spring-ом единым...

Появилась еще одна библиотека для Java для работы с LLM, а точнее конкретно с OpenAI. Официальная, от OpenAI
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>0.22.0</version>
</dependency>

На что хотелось бы обратить внимание:
1) OpenAI наконец то "дошла" до Java разработчиков
2) Разработчики библиотеки очень любят method chaining (ссылка на статью с примерами в конце поста). Со стороны даже кажется, что череcчур, можно было бы и по-короче инициализировать библиотеку
3) есть поддержка web-поиска
4) есть неочевидное разделение на Completion API - простые вопросы к LLM, типа "как на Java получить список файлов в каталоге" и Assistants API - "напиши мне микросервис, возвращающий курсы акций на бирже". Почему неочевидное - в моделях я вижу обратную тенденцию к унификации, когда одна модель используется для всех типов задач.
5) Assistants API умеет в File Search и Code Interpreter

И небольшой каталог решений по работе с LLM на Java:

1) Spring AI - https://docs.spring.io/spring-ai/reference
Примеры использования:
hello world https://habr.com/ru/articles/784128/
Более сложные примеры
https://piotrminkowski.com/2025/01/28/getting-started-with-spring-ai-and-chat-model/
https://piotrminkowski.com/2025/01/30/getting-started-with-spring-ai-function-calling/
Telegram bot, OpenAI и Spring AI https://habr.com/ru/companies/dockhost/articles/884876/

2) langchain4j https://github.com/langchain4j/langchain4j Характерно, что проект сделан на основе одноименной Python библиотеки. Поддерживается в Quarkus https://www.baeldung.com/java-quarkus-langchain4j

3) прямая интеграция с OpenAI https://www.baeldung.com/java-openai-api-client

P.S. Возможно Assistants API "жрет" больше токенов, отсюда и разделение

#llm #openai #ai #spring
March 31
April 3
April 3
OpenAPI для асинхрона - а, пожалуйста

Я думаю все знают, как описать API для REST взаимодействия. OpenAPI давно уже стал стандартом.

Перечислю его основные плюсы:
1) широкое распространение
2) автоматическая генерация документации
3) онлайн редактор Swagger UI
4) генерация серверного и клиентского кода по схеме
5) стандарт покрывает не только собственно содержимое body сообщения, но и описывает всю схему взаимодействия: параметры URL, заголовки включая куки, коды ошибок. Даже адреса серверов, хотя как по мне - это спорный момент.

Но асинхронное взаимодействие, ака Event-Driven Architecture: Kafka, MQ.. - имеют свои особенности. Как минимум это:
1) нет понятия запрос-ответ, вместо этого обмен идет сообщениями
2) другой набор протоколов (хотя http есть и там, и там)
3) другая терминология - есть каналы (топик или очередь), у канала есть свои характеристики
4) в любом взаимодействии нужно описать 3 участников: producer, канал, consumer.

Поэтому появился AsyncAPI. Он достаточно сильно похож на OpenAPI:
1) тот же YAML,
2) похожи (с точностью до сказанного выше) основные блоки, из которых строится API - Info, Servers, Tags, Schemas...
Видно чем вдохновлялись авторы) Как сказано на официальном сайте: "Part of this content has been taken from the great work done by the folks at the OpenAPI Initiative."
И это хорошо.

Стандарт молодой, но уже стал стандартом ))) да, тавтология) Имеет все те же преимущества, что и OpenAPI - см. начало поста.
Вот неплохая статья с примером https://bigdataschool.ru/blog/asyncapi-specification-for-kafka-practical-example.html

Поэтому настоятельно рекомендую для использования.

#api #openapi #asyncapi
April 6
April 8
April 11
Kafka захватывает мир.

Я уже писал https://t.me/javaKotlinDevOps/411, что не умеет Kafka из-за заложенной в ней архитектуры. Если сформулировать одним словом - не реализует традиционную концепцию queue (а реализует - потоковой обработки данных, она же стриминг). Так вот, это уже не совсем так. В марте 2025 вышла Kafka 4.0 (пока даже без хотфиксов), где появилась новая фича - Kafka Queues https://cwiki.apache.org/confluence/display/KAFKA/KIP-932%3A+Queues+for+Kafka
Технически это сделано так: появились share groups - альтернатива обычным consumer groups, позволяющие всем членам группы вычитывать конкуренто сообщения из одной и той же партиции. С consumer groups это было невозможно, для независимой вычитки одной партиции нужны были разные consumer groups. С маршрутизацией все по старому, но первый шаг к очередям сделан. Где это можно применить - там где важно управлять конкурентной вычиткой на уровне consumer и не важен порядок вычитки сообщений. Причем у одного топика могут быть как consumer groups, так и share groups.

Возвращаясь к захвату мира. У БД есть такая концепция tiered storage. Переводится как многослойное хранение. Обычно слоев два - оперативная и архивная БД. Так вот, начиная с версии 3.6 Kafka умеет в tiered storage. Для хранения архивных данных можно подключать внешние хранилища, в частности облачные S3. Что важно - tiered storage включается настройками, т.е. не нужно писать никакого кода. Видится, что это хорошая заявка на использование Kafka как хранилища. Особенно, если у вас стриминговые данные, а-ля поток события, а-ля event sourcing.

P.S. Если говорить о других важных изменениях в последних версиях Kafka:
1) разработчики окончательно выпилили Zookeeper. Теперь за выборы лидера (master для каждой партиции) отвечает один из брокеров Kafka, имеющий роль Controller. И в случае его падения оставшиеся брокеры сами без внешней помощи могут выбрать новый Controller. Вот такое крафтовое (KRaft) решение. Это название протокола выбора лидера если что)

2) улучшен протокол ребалансировки - алгоритма сопоставления партиций топика и потребителей при изменении либо числа потребителей, либо партиций. https://cwiki.apache.org/confluence/display/KAFKA/KIP-848%3A+The+Next+Generation+of+the+Consumer+Rebalance+Protocol Как одна из целей заявлена "The protocol should support upgrading the consumers without downtime". Серьезная заявка, будем посмотреть.


#kafka #queue
April 13
И снова SOLID, и снова OCP

Я уже говорил, что означает Open Close Principe (OCP) https://t.me/javaKotlinDevOps/181. Но появилась еще одна мысль. Наверное самая лучшая реализация этого принципа - это система с плагинами. Там мы очень четко говорим - что open, что close. И само проектирование такой системы накладывает больше ответственности, а значит есть шанс, что разделение open - close будет более устойчивым со временем. Минус тут только один - проектировать такую систему долго, а нужна она далеко не всегда.

P.S. И еще одна мысль - раз у нас ООП язык, и для расширения мы задумываемся об использовании композиции или агрегации - очень похоже на то, что проектировщик ядра (библиотеки), которую мы расширяем, где-то ошибся.

P.P.S. И последняя - у проектировщика ядра и у пользователей этого ядра часто противоположные задачи. В ядре мы стремимся закрыть все лишнее (close), чтобы обеспечить устойчивость и соблюдение code quality. А когда мы используем ядро - в тестах или расширяя его функционал - нам часто хочется залезть во внутрь и что-то поменять. Или получить доступ к внутреннему состоянию (open). Надо искать баланс.

#solid
April 15
Типовые ошибки на собесах.

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

Часто на интервью есть либо задачки на live coding, либо задачки на подумать - не имеющие точного ответа.
И тут я сталкиваюсь с 2 типовыми ошибками:

1) кандидат боится ошибиться, т.к. не был готов к такому повороту собеса. Поэтому отвечает кратко, не объясняет свои решения, дополнительные вопросы его вводят в ступор. Все это производит негативное впечатление и сильно снижает шансы на найм. Правильное решение: не бояться - как бы это ни странно звучало - думать, размышлять, а главное - результаты проговаривать. Даже если четкого ответа нет. Именно этого интервьюер и ждет, добавив такую секцию на собесе - понять ход мыслей кандидата.

2) кандидат скажем так сильно прикипел к своей предметной области. Предположим, его типовые задачи - реализация новых REST методов, а способ - связка controller-service-repository. Он получает задачку на собесе и сразу начинает выполнять ее по той же схеме, как делал бы на текущем месте работы. Что тут плохого? Только то, что интервьюер возможно хотел проверить знания алгоритмов, паттернов надежности или чего-то еще. А вовсе не умение раскладывать код на по слоям controller-service-repository. И получается как в анекдоте: "Некогда думать, трясти надо". Правильное решение - уточнить, что хотел интервьюер. А потом еще раз уточнить) Важнее четкое понимание задачи и обсуждение путей ее решения, чем скорость написания кода. Да, это может занять столько же времени, сколько и написание кода. И это нормально. Есть компании с нормой решенных задач на собес, но в любом случае неверно решенная задача в зачет не идет.

P.S. Отдельный важный момент связан с live coding - и это тесты. Можно сколько угодно говорить, что "надо написать тесты, я обычно так делаю, но сейчас времени нет.." Но лучше их просто написать) Можно даже перед кодом, по TDD.

#interview #interview_fails
April 18
Почему SOLID?

Почему именно SOLID считается базовыми принципами разработки? Почему именно пять? Почему именно эти пять?

Я думаю, что за основной причиной нужно идти в словарь. Solid — крепкий, твёрдый, надёжный, серьёзный. Роберт Мартин хотел, чтобы принципы легко запоминались — у него это получилось)

Приведу пару аргументов.
I — interface segregation — принцип, конечно, полезный. Но технический по сути, а главное — является частным случаем S — single responsibility.
S, O, D — могут применяться как на уровне классов, так и на уровне модулей приложения.
L — это уровень классов, накладывает на них более строгие требования, чем обеспечивают «из коробки» ООП языки.

Есть ещё полезные принципы — DRY, KISS, которые сюда не попали.

Из всего вышесказанного никак не следует, что SOLID-принципы плохие. Я о том, что их на самом деле больше.

#solid
April 19
k8s HPA бесполезен? Или нет?)

Я уже писал о возможности масштабировать поды горизонтально через компонент HPA — Horizontal Pod Autoscaler. Он собирает метрики загрузки пода (границы можно настраивать) и меняет число реплик в заданных границах.

Круто? Да. Но есть одно «но». В namespace ресурсы часто прибиты гвоздями. Один namespace = один микросервис. Микросервис имеет некие бизнес-требования по нагрузке, проходит нагрузочное тестирование и получает некоторое количество ресурсов. Хуже того — кластер, в котором находится namespace, тоже имеет жёсткое ограничение по ресурсам. Это частное, небольшое по сравнению с cloud-провайдерами облако. Лишним node взяться неоткуда. Поэтому HPA в частном облаке бесполезен. Все ресурсы уже забронированы. От того, что часть из них уберут из балансировки, ни холодно ни жарко. Только замедление при старте пода.

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

Что можно сделать в частном облаке? Например, вот так: https://youtu.be/GWJ9rDrsBdQ?si=dx-VHMlIIYKo2g4q Кейс не универсальный, но если есть свой кластер и понятно, что в нём будут жить приложения с разными пиками нагрузки — потребление ресурсов можно оптимизировать. Как развитие идеи — автоматическая генерация рекомендаций по настройке кластера.

#k8s #optimization
April 22
live coding это все-таки кодинг

Недавно писал про то, что на сессии live coding на собесе не надо сразу браться за задачу, вначале стоит позадавать вопросы и продумать путь решения задачи.

Но есть и обратный кейс. Пусть у нас остается максимум полчаса времени собеса. Есть задача на live coding. И вообще то задачку можно сделать за 10 минут. И, естественно, это понимают люди, ведущие собес. Как они отнесутся, если кандидат потратит 10 минут на вопросы, 10 минут на рассуждения как лучше реализовывать и 10 минут на написание кода? И как всегда без тестов, по причине того, что тесты бы написать надо, но времени нет. Ответ - плохо отнесутся.

И тут мы приходим к понятию баланса. Соотношению между сложностью задачи (да, ее нужно уметь оценить, причем в экспресс режиме) и усилиями, затраченными на ее решение. В данном случае баланс сильно нарушен, хотя все действия вроде бы правильные. И что самое важное - интервью намекает, как такие задачи кандидат будет решать в реальной жизни. Lead Time говорит - ну да, ну да, пошел я ...

В общем не делайте так

#interview #interview_fails
April 25
code style бывает разный

Меня сложно чем-то удивить в области разработки. Но недавно, изучая разные code style, я решил посмотреть, какие бывают варианты расположения фигурной скобки. Изначально в моём понимании их два - на одной строке с управляющей конструкцией и с новой строки. Но жизнь оказалась богаче любых ожиданий:
https://en.m.wikipedia.org/wiki/Indentation_style
Девять! Девять, Карл!

Хотя в Java наиболее распространён один, пришедший из C, от Кернигана и Ричи.

Вывод будет такой. Не важно сколько разных code style существует, важно, чтобы в проекте использовался один. А это значит .editorconfig https://editorconfig.org/ и автоматическое форматирование в Actions on Save в IDEA.

#code_style #idea
May 1
May 8
May 13
PHP становится Java-ой?

Недавно посмотрел видео о перспективах PHP https://vkvideo.ru/video-224967259_456239053 Я на PHP писал мало, но т.к. он широко распространён - интересно, развивается ли он и как именно. Он развивается, и я этому не удивлён. Да, есть распространённое негативное мнение про PHP и его разработчиков. Любой простой язык привлекает непрофессионалов. Но ситуация сложнее, чем кажется, на это намекает официальный code style языка https://php-psr.ru/accepted/PSR-12-extended-coding-style-guide/ Обязательность строк разделителей, фиксированное число пробелов, регистр символов - все серьёзно. Небольшое отступление - к аббревиатуре PSR из статьи выше мы ещё вернёмся.

Так вот, PHP становится похожим на Java.

Чтобы понять как именно - стоит вспомнить, чем он характеризовался изначально?

1) динамическая типизация. От неё уходят, с костылями в виде объявления типов в комментариях и проверке статическим анализатором типа checkstyle. Причина - невозможно работать со сложным проектом и динамической типизацией. Если ты конечно не хочешь "гов..кодить".

2) интерпретация вместо компиляции. Тоже уходят, есть AOT и JIT компиляторы PHP. Также фреймворки, например, IoC контейнеры, могут предварительно сохранять конфигурацию на диске. По соображениям производительности

Да, в PHP тоже есть IoC контейнеры.

3) малоизвестный факт - исходно в PHP была т.наз умирающая модель процессов. После обработки запроса клиента контекст процесса полностью очищается. Такой true stateless. Причём очищались не просто клиентские данные, а все бины IoC контейнера, т.е. вообще все. Побочные эффекты такого подхода противоположные. Положительный: PHP компоненты инициализируются очень быстро, по другому никак. Отрицательный: на утечки памяти можно забить, т.е. "гов...кодим") Так вот, от этой модели тоже уходят. Снова по соображениям производительности

В общем язык развивается, т.к. наследие огромное.

P.S. Чтобы не было пренебрежительного отношения к PHP - поговорим про стандартизацию. В PHP есть такое понятие, как middleware. Вот его неплохое описание https://laravel.com/docs/12.x/middleware
Ключевой момент - компоненты middleware переиспользуются в различных фреймворках. Как это получается? Потому что многое стандартизируется, с помощью PSR. В Java тоже есть стандарты - JPA, JDBC,  http сервлеты и фильтры, но видится, что их меньше. Когда-то этим занимался проект Java EE, не смог, умер и воскрес, а за это время возникло несколько экосистем - Spring, Quarkus, Micronaut... И это я Kotlin не беру) Почему я назвал их экосистемами - каждая старается привязать к своим компонентам. Так что как ни странно - PHP выглядит более стандартизированным)

#java #PHP #lang
May 16