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

Возращаясь к тебе legacy.
Давно хотел прочитать книжку Эффективная работа с унаследованным кодом. legacy в жизни разработчика есть всегда (если только он сознательно не ищет только greenfield проекты), поэтому тема полезная. Книга не новая, но судя по отзывам (и по факту как выяснилось) актуальная.

Небольшое введение в тему. Есть 2 способа бороться с легаси - я бы их назвал архитектурный и програмистский. Архитектурный - взять и сделать рядом новую систему, постеменно перетягивая туда функционал и используя такие паттерны как Strangler Application, API Gateway, Decorator, Facade...
Програмисткий - улучшать легаси изнутри, делить его на микросервисы по необходимости и т.д. Это конечно крайности, как правило используется смесь обоих подходов.

Так вот - книга про второй способ. Я ожидал найти там набор практик и паттернов по улучшению легаси. И более того - они там есть. Но главная мысль в книге другая, и она немного неожиданная. Сразу вспомнилась шутка: как только код написан - он уже стал легаси) И так может быть) Если мы даем такое определение легаси - много кода без тестов. Почему? В чем основная проблема легаси? Никто не знает досконально как оно работает, никто не хочет с этим кодом разбираться и, как следствие, его боятся менять. Очевидно, что если кода много и тестов нет - менять его страшно. Бинго. И собственно вся книга о том, как написать недостающие тесты даже если на первый взгляд это кажется очень сложным.

#legacy #book_review
March 7
Всем привет!

Продолжаю читать книгу "Эффективная работа с унаследованным кодом". Наткнулся на интересную мысль, на первый взгляд подтверждающую тезис: разработка - искусство компромиссов.

Мы все используем библиотеки. Когда нужно написать тест (а книга в основном про то, как упростить написание тестов для legacy) - часто в наш класс передаются библиотечные объекты. И тут могут быть две проблемы:
1) объект-синглтон
2) final объект или объект с методами, которые не возможно переопределить.
Эти две проблемы приводят к одному и тому же - мы не можем создать mock, приходится инициализировать для тестов реальный объект из библиотеки. А он может быть "тяжелым", превращающий модульный тест в интеграционный.

Как вариант решения этой проблемы предлагается:
1) для singleton создавать фасад, который разрешает замену объекта через setter, т.е. по сути нарушать суть паттерна singleton
2) для final методов и объектов - убрать final, объявляя их логическими final в документации.

Оба предложения по сути об одном - нарушаем принципы проектирования на уровне языка, зато делаем возможным тестирование кода.

В целом - "соль" в этом есть. Код без тестов опаснее кода, нарушающего принципы проектирования. Но я бы уточнил, что оба метода - это крайние меры. А по хорошему, если вы разрабатываете код, который кто-то когда-то будет тестировать - надо заранее озаботится о тестируемости, и именно:
1) не создавать singleton самому, использовать для этого IoC контейнер. Spring если библиотека внутренняя, и у вас используется Spring, или CDI аннотации в других случаях. Причем это актуально не только для разработчиков библиотек, а для всех.
2) создавать интерфейсы для классов, вынесенных в клиентское API. Есть интерфейс - всегда можно создать mock в тесте без всяких ухищрений. Я против создания интерфейсов всегда и везде https://t.me/javaKotlinDevOps/235, но Java API - это как раз подходящий случай. Одних интерфейсов конечно же мало, нужно еще и четкое разделение на модель и сервисы. Первые можно использоваться AS IS в тестах, вторые часто приходится мокать. Да, спроектировать все правильно не так-то легко, но как говорится - дорогу осилит идущий.

#book_review #ood #dev_compromises #libraries
March 10
Всем привет!

Вчера "прогремела" новость по AI агентов, которые через 3 месяца будут писать 90% кода https://habr.com/ru/news/889992/
Что я могу сказать.. галлюцинируют не только модели)))

Что нельзя не отметить:
1) модели в последнее время сильно эволюционировали в целом и в плане написания кода в частности
2) появляется все больше AI агентов, упрощающих внедрение написанного AI кода - убирают Copy-Paste из окна AI чата
3) объем контекста моделей растет, что позволяет загнать туда весь проект типового микросервиса
4) про AI говорят из каждого утюга, наверное скоро не останется разработчиков, которые не изучали AI агенты

Актуален ли вывод в статье учитывая вышесказанное? Конечно же нет.

Да, будут разработчики, возможно они есть и сейчас, 90% кода которых - плод работы AI. Кстати, есть такие среди читателей канала? Отпишитесь, плиз)

Но что не нужно недооценивать:
1) инерцию - новые технологии быстро не внедряются. Даже если это dev уровень - релизить AI помощника для разработки в ПРОМ не надо
2) цену в деньгах или времени - хороший AI стоит денег, или если это open source типа Deepseek - времени выбор подходящего и встраивание его в процесс разработки
3) галлюцинации. AI хорошо работает на типовых кейсах, хуже - на неизвестных. Т.е. галлюцинаций будет много на малоизвестных языках, фреймворках и внутренних платформах (!)
4) негативный эффект от первых попыток. Если AI был опробован год назад и сильно глючил - до следующей попытки внедрения пройдет время, и это не 3 месяца
5) меньший контроль - когда код пишешь сам, то ты его контролируешь полностью. Если, конечно, спать хотя бы 7 часов в день, и тебя не дергают каждые полчаса на встречи) За моделью нужно проверять, проверка - менее приятный процесс по сравнению с написанием, мозг склонен его оптимизировать, что приводит к меньшему контролю.

Вывод - CEO Anthropic плохо представляет реальную разработку, и грешит маркетинговым bullshit-ом((( Хотя он CEO, а не CIO, что немного его оправдывает)

#ai
March 13
Всем привет!

Минутка философии на канале. Если почитать идеологов DevOps, он не про инструменты, а про взаимодействие. Взаимодействие Dev и Ops. А отдельная команда DevOps, если и существует, то для разработки тех самых инструментов, которыми пользуются Dev и Ops. И тогда релизный процесс улучшается, скорость реакции на инциденты растёт.
Рассмотрим обратный случай — типичный, к слову. Есть команда DevOps, она настраивает стенды и пайплайны, которыми пользуются Ops. Какой будет эффект? Вообще говоря, разный, зависит от степени взаимодействия команд. Но вполне может быть, что с появлением команды DevOps процессы только замедлятся. Ops во всём надеются на DevOps. При любой проблеме Ops идёт к DevOps, Dev при этом получает информацию посредством испорченного телефона или вообще не получает. И наоборот, в случае с тестовыми стендами. Грусть, печаль, баги прома.

#devops
March 15
Всем привет!

Я уже писал про то, что не люблю код, в котором интерфейсы делаются ради интерфейсов. Самый яркий антипаттерн: интерфейс с единственной реализацией, лежащей рядом. Подозреваю, одной из причин такого проектирования является принцип Dependency Inversion - в модели должны быть интерфейсы, а в сервисном слое - их реализации. И они разнесены по разным слоям приложения. Тут вроде все сходится?
Как бы да, но я нашел интересное возражение: https://habr.com/ru/articles/888428/
Как всегда побуду в роли ChatGPT) Суть статьи, а точнее продвигаемого там принципа структурного дизайна в том, что вместо создания интерфейса, любой сложный сервис можно отрефакторить (или спроектировать), выделив 3 метода:

1) чтение - все интеграции по чтению из внешних источников
2) бизнес-логика - тут должны быть чистые классы модели, принимающие на вход только простые типы или коллекции, без побочных эффектов
3) запись результата во внешние источники

2-я часть - это ядро, все остальное - imperative shell. Методы ядра вызываются из imperative shell, зависимости направлены в одну сторону.

Потенциальная проблема - возможно, читать придется много, чтобы загрузить данные для всех условий в бизнес-логике. Решение - дробить бизнес-логику на более мелкие части.
Еще проблема - как отследить, что в метод с бизнес-логикой не передали "побочный эффект". Например, класс, делающий вызов к БД - JPA lazy initialized DTO. Или ссылку на синглтон - Spring bean. Навскидку - только ручное код-ревью. Формально описать проверку объекта на отсутствие побочных эффектов сложно.
Огромный плюс - бизнес-логика всегда легко тестируется, даже без mock-ов.
Еще плюс - код проще.

Вот пример такого рефакторинга: https://www.youtube.com/watch?v=wq9LBouRULs

До чтения статьи, по заголовку, "покушение" на основы чистой архитектуры я воспринял критически. Но после ее прочтения и дальнейших размышлений идея понравилась.

Очевидно, она применима не всегда. Можно описать такую эвристику:

Простой сервис:
1) используем структурный дизайн, четко разделяем чтение с записью от бизнес-логики. С интерфейсами не заморачиваемся.
2) нужна вторая реализация какого-то сервиса - для тестового mock-а, динамической замены в runtime - легко вводим интерфейс с помощью IDE там, где он нужен

Сложный сервис, например:
1) библиотека
2) система с плагинами
3) коробочный продукт с несколькими реализациями под разных клиентов
4) наличие ядра, которое нужно защитить от правок "не доверенными лицами" -
изначально проектируем с интерфейсами в модели и реализациями в сервисах и портах\адаптерах

Принципу KISS - соответствует. Dependency Inversion - как ни странно тоже, т.к. в точной формулировке он звучит так: ядро не должно зависеть от деталей реализации. А структурном дизайне в ядро передаются только простые типы данных и коллекции с ними.

#arch #clean_code #principles
March 17
Всем привет!

Как можно собрать Docker образ?
Есть плагины для Maven\Gradle, позволяющие использовать всю мощь соответствующих инструментов при сборке.
А есть собственно Docker и команда docker build, собирающая образ на основании Dockerfile. Ну и еще Docker Compose, позволяющий описать, собрать и запустить группу образов, полезный при локальной разработки или если нет k8s.

До какого-то момента возможности Docker по кастомизации процесса сборки были скажем так базовыми.
Но как вы уже догадываетесь - все поменялось.
Появился Docker Bake. Вот хорошая статья на Хабре https://habr.com/ru/articles/886938/

Команда для сборки: docker buildx bake
buildx - это расширенный вариант build, позволяющий выбрать движок для сборки образа.
В последние версии Docker функционал Bake включен по умолчанию.

Основные плюсы с примерами конфигураций:

1) функции

function "tag" {
params = [name, tag]
result = ["${name}:${tag}"]
}

2) группировка образов для сборки одной командой

group "default" {
targets = ["frontend", "api"]
}

target "frontend" {
...
target "api" {


2) наследование конфигурации

target "app-base" {
dockerfile = "Dockerfile"
args = {
BASE_IMAGE = "node:16-alpine"
}
}

target "app-dev" {
inherits = ["app-base"]
...
}

3) кросс-платформенная сборка

target "app-all" {
platforms = ["linux/amd64", "linux/arm64"]
}

4) профили сборки

variable "ENV" {
default = "dev"
}

group "default" {
targets = ["app-${ENV}"]
}

target "app-dev" {
...

target "app-stage" {
..

target "app-prod" {
...

и сборка командой

ENV=prod docker buildx bake

5) матричная сборка - сборка всех возможных комбинаций, указанных в матрице

target "app" {
matrix = {
platform = ["linux/amd64", "linux/arm64"]
version = ["1.0", "2.0"]
}

6) встроенное распараллеливание сборки

7) чтение переменных из файла

// Импорт переменных из JSON-файла
variable "settings" {
default = {}
}

target "app" {
dockerfile = "Dockerfile"
args = {
CONFIG = "${settings.app_config}"
}
}

Ну и главное - декларативность описания процесса сборки, описываем результат, а не действия. За исключением пользовательских функций, конечно)

Кажется, неплохая альтернатива плагинам и хороший апгрейд Docker. Важным плюсом видится встраивание в Docker. Тот же Scaffold - выполняющий другую функцию, но в т.ч. собирающий образы - нужно ставить отдельно, и в IDEA он тянет за собой кучу лишних фичей.

P.S. Docker Compose заменяет только в части сборки. И может с ним интегрироваться.

#docker #gradle #maven
March 19
Всем привет!

Я уже подымал тему готовых архитектурных решений, а точнее их отсутствия в большинстве случаев https://t.me/javaKotlinDevOps/134
Хочу развернуть тему с другой стороны.

Стоит ли тратить силы на поиск целевого архитектурного решения?

Написал эту фразу, и понял, что не всем она может быть понятна) Расшифрую. В больших компаниях ака "кровавый enterprise" есть некий список разрешенных технологий и архитектурных принципов. Оформленный в виде техрадара, карты технологических стеков и сборника архитектурных стандартов. Это и есть целевая архитектура.

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

Так вот - а надо ли его искать? Несмотря на то, что ответ вроде бы очевиден, хотел бы подсветить несколько потенциальных проблем.

Затрачивая время на поиск и согласование целевого решения мы взамен хотим получить уверенность, что решение с нами останется "на века". Так ли это? Нет, не так. Во-первых мир меняется очень сильно, бизнес задачи меняются вместе с ним. Во-вторых технологии меняются еще сильнее. В-третьих - "кассандр" среди нас мало, и если есть несколько разрешенных технологий - угадать правильную сложно.

К чему это приводит? Мы потратили время на выбор и реализацию "целевки", а через год нам говорят - переделывайте. Отрицание, гнев, фрустрация. Обида на архитекторов. Причем даже если архитектор признает ошибку (и вообще эта ошибка была) - вряд ли он поможет переписать код. Обида на менеджеров - да они издеваются что ли, вечно меняют правила игры, вечная миграция... Желание сменить компанию...

Поэтому видится, что есть более надежный подход.

1) смириться с тем, что все течет, все меняется, и миграции будут всегда

2) искать целевые решение, но всегда держать в уме, что это целевое решение на данный момент

3) разделить весь код на ядро и инфраструктурный код. Ядро стараться писать на чистой Java \ Kotlin, с минимальным использованием фреймворков. Особенно, внутренних, которые еще не доказали свою стабильность. Внешние интеграции закрывать - предохранительный слой (anticorruption layer), шлюзы (gateway), адаптеры.

4) очень важно - уметь и хотеть быстро выпускать релизы, разбивать любые доработки на небольшие инкременты. Это можно сделать как улучшением качества проектирования, увеличением покрытия тестами и автотестами, так и различного рода договоренностями со смежниками, (не забываем, что мы в "кровавом enterprise")

Если вам показывался знакомым последний пункт - то да, это Agile. Или то самое снижение Lead Time (LT), о котором любят говорить менеджеры. И не только говорить) Но в данном случае они правы.

Еще пример - фондовый рынок и диверсификация. Диверсификация считается основным принципом разумного инвестора, и означает, что нельзя "класть все яйца в одну корзину". Т.е. нужно покупать разные классы активов: акции, облигации, вклады, кэш, золото, недвижимость. Причина - сложно угадать, что именно "выстрелит". В случае кода сложно конечно реализовать диверсификацию прямолинейно: часть данных хранить в PostgreSQL, а часть - в Oracle. Да и не нужно. Но предусмотреть возможность замены поставщика - нужно.

#agile #arch #arch_compromisses
March 21
Всем привет!

Прочитал сегодня хороший пост (английский): 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
Тут мы включаем асинхронное выполнение событий. Операции выполняются в разных транзакциях и в разных потоках.

Все варианты имеют право на жизнь, главное не забывать как работает Spring Events. Ну и если у нас есть "дешевые" транзации на БД (дешевые по сравнению с распределенными транзакциями), то имеет смысл использовать их по максимуму.

P.S. Что интересно, статья с baeldung.com по запросу Spring Events ранжируется выше официальной документации.

#spring #transactions #event_driven
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