Джавист Роман ☕️ @romankh3 Channel on Telegram

Джавист Роман ☕️

@romankh3


Авторский канал Java, Kotlin разработчика с более, чем 9-летним опытом.

GitHub: https://github.com/romankh3
Библиотека: https://t.me/romankh3books
Чат: https://t.me/romankh3_chat

Джавист Роман ☕️ (Russian)

Добро пожаловать на авторский канал Java, Kotlin разработчика романа с более чем 9-летним опытом - Джавист Роман ☕️! Здесь вы найдете множество полезной информации, советов и рекомендаций от опытного специалиста в области разработки. Подписывайтесь, чтобы быть в курсе всех последних новостей и тенденций в мире Java и Kotlin. nnНе забудьте также заглянуть в нашу библиотеку, где вы найдете рекомендации по книгам и ресурсам по Java и Kotlin: https://t.me/romankh3books. А если у вас есть вопросы или просто хотите пообщаться с единомышленниками, присоединяйтесь к нашему чату: https://t.me/romankh3_chat. Будем рады видеть вас в нашем сообществе! 🚀

Джавист Роман ☕️

01 Dec, 13:36


Почему писать бизнес-логику в SQL-запросах — плохая идея?

Давеча был разговор с бекендером, почему не стоит писать бизнес-логику в SQL запросах. Последние лет 5 для меня это аксиома, которую не нужно было повторять и я не сразу смог сформулировать емко. Посидел, подумал и решил, что лучше всего будет написать заметку на эту тему и потом возвращаться к ней каждый раз, поэтому сегодня поговорим с вами, почему же писать бизнес-логику идея плохая.. Но не всегда 😁

Добавление бизнес-логики непосредственно в SQL-запросы может выглядеть как удобный выход из положения, но в долгосрочной перспективе такой подход чреват множеством проблем.

Вот 5 основных причин, почему это не рекомендуется:

1️⃣ Сложность поддержки и отладки

SQL-запросы, содержащие сложную логику, становятся трудно читаемыми и практически невозможно разобраться, что где работает неправильно. Чем больше там логики, тем сложнее её тестировать и исправлять ошибки.

2️⃣ Нет повторного использования кода

SQL, как правило, плохо подходит для повторного использования кода. Если логику нужно применить или изменить в другом месте, её придется копировать, что создаёт избыточность и увеличивает количество «точек отказа».

3️⃣ Перенос сложности в неподходящий слой

SQL-запросы должны использоваться для манипуляции с данными, тогда как бизнес-логика должна быть на уровне приложения, где существуют инструменты для её структурирования и управления.

4️⃣ Сложности масштабирования

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

5️⃣ Трудности работы с несколькими хранилищами данных

Если ваша система использует не одну базу данных (например, SQL + NoSQL), размещение логики в SQL усложняет интеграцию и синхронизацию данных между разными система.

Когда можно писать бизнес-логику в SQL?

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

Пишите код грамотно и помните: бизнес-логика должна быть там, где ей место — в приложении. 😉

#аксиомаПрограммирования #sql

Джавист Роман ☕️

12 Oct, 12:31


Начало 👆👆

## Расположение
Тесты должны располагаться в отдельной папке, обычно это src/test/java в проектах Maven или Gradle.
Структура директорий должна дублировать структуру основного кода, чтобы было легко найти тесты, соответствующие классу.

UPDATE: спасибо подписчику, указал на несомненно более важную причину: в таком расположении будут доступны package-private классы, методы и переменные. Без этого будет значительно сложнее писать тесты.

## Советы, как делать

### Принцип по написанию тестов FIRST
Принципы написания тестов, известные под акронимом FIRST, помогают разработчикам создавать качественные и эффективные тесты. FIRST расшифровывается как:

#### Fast (Быстрые)
Тесты должны выполняться быстро, чтобы их можно было запускать часто и без значительных затрат времени.
Это позволяет разработчикам получать обратную связь об изменениях кода как можно быстрее.
Если тесты будут идти долго, то время деливери продукта будет сильно сдвинуто.

#### Isolated (Изолированные)
Каждый тест должен быть независимым от других. Это значит, что результаты одного теста не должны зависеть от результатов другого. Изолированные
тесты проще отлаживать и поддерживать, так как проблемы можно точно локализовать. Другими словами, связанный тест - это неправильно
написанный тест, который создаст намного больше хлопот, чем пользы, для которой разработчик решит связать тесты.

#### Repeatable (Повторяемые)
Тесты должны давать одинаковые результаты при каждом запуске при одинаковых условиях.
Это значит, что тесты нужно писать так, чтобы они были предсказуемыми и не зависели от состояния системы или внешних факторов.
Игнорирование этого принципа ведет к созданию плавающих тестов, которые будут ломать сборку от случая к случаю.
Хороший пример такого плохого теста - это неправильная работа с часовыми поясами может привести к проблемам при запуске в разнах часовых зонах.

#### Self-Validating (Автоматически проверяемые)
Тесты должны иметь четкие результаты: либо проходят, либо нет. Это упрощает процесс проверки,
так как разработчики не должны вникать в результаты тестов — они просто видят, прошел ли тест или нет.

#### Timely (Своевременные)
Тесты должны писаться как можно раньше в процессе разработки, желательно сразу после написания кода или даже до него(в практике тестируемого
разработки, например, TDD — тестирование перед разработкой). Это помогает предотвратить ошибки и обеспечивает более высокое качество кода.

Соблюдение этих принципов помогает создавать эффективные тесты, которые способствуют улучшению качества программного обеспечения и
упрощают процесс разработки.

### А также

- Пишите короткие и понятные тесты, проверяющие одну вещь. Это повысит их читаемость и простоту в отладке.
- Используйте методы для общих проверок (assertEquals, assertTrue и т. д.) из библиотеки утверждений.
- Не забывайте покрывать крайние случаи и исключения.
- Используйте моки для интеграции с зависимыми компонентами (например, Mockito).

## Вместо вывода
Написание тестов это такая неотъемлемая часть разработки, как и написание бизнес логики. Стоимость поиска дефекта на этапе разработки
через тесты, написанные разработчиком на порядок дешевле от стоимости решения дефекта, который нашли в продакшене.

Всем добра и мирного неба над головой

Джавист Роман ☕️

12 Oct, 12:30


Начало 👆👆

## Именование
В тестах для разработки есть два вида тестов - интеграционных и модульные. Как их именовать?

### Классы
Возьмем к примеру класс PluggableAppAdministrationApi, для него могут быть как интеграционные, так и модульные тесты.
Для интеграционного теста к названию класса нам нужно добавить суффикс IT, для модульного просто Test:

- PluggableAppAdministrationApi -> PluggableAppAdministrationApiIT - интеграционный тест
- PluggableAppAdministrationApi -> PluggableAppAdministrationApiTest- модульный тест

### Методы
Название теста должно быть понятным и отражать его суть.
Используйте название метода, который тестируется, в сочетании с ожидаемым результатом или поведением.

Например: shouldReturnTrueWhenInputIsValid.

## Структура (предлагаемая) для написания тестов
В рамках структуры могут быть разные подходы и описанная здесь не должна быть догматична для всех. Тем не менее, предлагаемый подход ниже
поможет сделать тесты более понятными и читаемые.

Структура тестов через BDD (Behavior Driven Development) позволяет разработчикам, тестировщикам и другим заинтересованным сторонам легко
понимать требования и сценарии поведения системы. Вот основные компоненты, которые помогут разработчикам правильно писать тесты в формате BDD:

- Сценарий - это название теста, каждому сценарию должно быть дано четкое название, описывающее его цель.
- Given (Дано): Устанавливает предысторию и состояние системы. Определяет, из какого состояния начинается тест.
- When (Когда): Описывает действие или событие, которое инициирует поведение системы.
- Then (То): Определяет, какое поведение ожидается от системы после выполнения действия. Это описание ожидаемого результата.
- And (И): Используется для добавления дополнительных условий или шагов для более сложных сценариев.

Пример такого теста из одной библиотеки:

    @DisplayName("The most important test. Shown, that the changes in algorithm, "
+ "don't break the main behaviour and result as expected")
@Test
public void shouldProperlyExecuteComparing() {
//given
BufferedImage expectedResultImage = readImageFromResources("result.png");

File file = new File("build/test-images/result.png");

//when
ImageComparison imageComparison = new ImageComparison("expected.png", "actual.png");
ImageComparisonResult imageComparisonResult = imageComparison.compareImages().writeResultTo(file);

//then
assertNotNull(imageComparison.getActual());
assertNotNull(imageComparison.getExpected());
assertEquals(MISMATCH, imageComparisonResult.getImageComparisonState());
assertImagesEqual(expectedResultImage, imageComparisonResult.getResult());
}


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

Продолжение 👇👇👇

Джавист Роман ☕️

12 Oct, 12:30


🚀 Мысли о том, как писать тесты разработчику 🚀

Всем привет, будущие senior java developers! Давно мы с вами не виделись.

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

Заранее спасибо вам)

Ну, не буду дальше тянуть, поехали!

Далее 👇👇

Джавист Роман ☕️

30 Nov, 09:59


Сколько должен длиться онбоардинг

Джавист Роман ☕️

30 Nov, 09:55


Как правильно сделать онбоардинг

Джавист Роман ☕️

30 Nov, 09:50


Тезисы по проведению 1-2-1

Джавист Роман ☕️

30 Nov, 08:21


Как стать эффективным менеджером

Джавист Роман ☕️

28 Oct, 12:46


Друзья, нужна помощь!

Есть кто разбирается как правильно решить задачу по организации локальной сети в частном доме?

Дано:
0. на входе будет оптоволокно с преобразованием в обычную витую пару
1. есть 10 проводов езернета, которые расходятся в разные части дома под свои нужды
2. есть два этажа в доме и нужен стабильный wifi сигнал, совсем уж хорошо будет если wifi будет бесшовный

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


Что имею в логове?

1. нужен коммунатор, который бы связал бы это вместе
2. нужно несколько роутеров для wifi
3. нужны вполне себе нормальные настройки локальной сети, чтобы можно было ограничивать ресурсы определенные, выставлять наружу static ip для сервера наружу

Не понимаю, какой лучше брать коммутатор. Смотрю сейчас на TP-link, отзывы не лучшие на них и на роутеры.
Куда должен заходить интернет: в роутер вначале или в коммутатор, а потом дальше? Тоже не очень понятно. Хотелось бы в коммутатор и его держать как общую систему настройки всего. Но тогда не понятно что будет с ip-адресами в роутерах, что будут подключаться к коммутатору.

UPDATE:
cовсем забыл, что еще здесь будет система по видеонаблюдению. 4-5 камер, так что еще и POE нужны

Как-то сумбурно вышло, но вот что есть, заранее спасибо)

Джавист Роман | Подписаться

Джавист Роман ☕️

14 Oct, 10:40


Примета джуна #1 "С шашкой наголо"

На фоне вопроса какая разница между джуном и мидлом пришла в голову идея пойти несколько другим путем - описать то, что в моем понимании есть признаки джуна. То есть те вещи, которые характеризуют джуна и могут быть маркерами как для тех, кто оценивает сотрудником так и для тех, кто хотел вырасти из джуна. Чтобы собрать их воедино - добавляю тег #примета_джуна. По нему можно будет все их собрать.

Рассмотрим обычную историю: есть некий проект, который уже вышел в прод. Проект частично можно уже назвать легаси, так как некоторые модули от греха подальше не не лезут ибо "и так рабоает".

На проект берут нового инженера с горящими глазами сделать мир лучше. Ему назначают задачу: нужно добавить еще один атрибут в одну из базовых сущностей.

Задача в общем то не очень сложная, можно сказать даже идеальная для вхождения в проект - потому что придется пройти весь путь от добавления нового поля в таблицу до показа этого поля наружу через РЕСТ АПИ.

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

И казалось бы молодец, ведь проект после этого стал лучше и чище. Или нет?

И вот здесь, прежде чем читать дальше, я предлагаю вам подумать самим. Хорошо ли сделал новый инженер или нет?

....

Чтобы создать место между вопросом и ответом предлагаю вам подписаться на группу дискуссий к этому каналу: @romankh3_chat . Мы там всегда обсуждаем темы разработки.
И, также подписывайтесь на мою библиотеку: @romankh3books Я там выкладываю свои купленные книги и другие, что попадаются мне и интересны.

....

Думаю у всех уже было время подумать.

Мой ответ НЕТ, человек не справился со своей задачей. Почему? Потому что вместо того, чтобы сделать только то, что ему говорят, он полез заниматься еще чем-то. Потратил лишнее время. А быть может эта новая функциональность уже ждет на ПРОДЕ и самодеятельность инженера оттягивает ее сдачу.

Причем скорее всего этот рефакторинг будет носить локальный характер и не решит проблему целостно, а лишь только поверхностно.

Очень сложно проводить код-ревью в таких случаях, так как нужно найти именно те изменения, что решают поставленную задачу.

Выше я предположил идеальную ситуацию к рассмотрению, что дополнительная активность была по делу и ничего не ломала, а ведь это зачастую не так. А это значит, нужно еще больше тратить время на код-ревью, чтобы еще понять, что остальные изменения не сломают ничего и мы в следующем релизе не выстрелим себе в ногу на ПРОДе.

А это все значит, что нужно будет проводить более детальную регрессию по тестированию, что опять таки нагружает команду без необходимости.

Даже больше скажу, вполне возможно, что те улучшения не нужны были вовсе. Такое бывает сплошь и рядом. А работа произведена.

Здесь конечно можно сказать, ну ты ж критикуешь, так предложил что можно сделать!
Согласен полностью, такие вещи стоит обсуждать с командой и если в улучшениях есть необходимость, то нужно заводить отдельные задачи для этого и вести их в ракурсе работы с техдолгом.

Оценили техдолг, отсортировали его по приоритетам и берем поэтапно в следующие спринты.

Разумеется коллеги, жду ваше мнение в комментариях)

Джавист Роман | Подписаться

Джавист Роман ☕️

11 Oct, 20:41


Всем привет!
Вы часто меня спрашиваете, куда я пропала (нет) 🤣
В прошлый раз вернуться я не смогла, потом оказалось, что у меня выгорание и пришлось из него выходить)) Про стадии выгорания, и что помогло мне из него выйти я обязательно напишу пост, а сейчас о другом)

Коллега посоветовал классную книгу, «Фундаментальный подход к программной архитектуре» (обложку покажу в каментах), в ней описаны различные подходы к проектированию архитектуры, паттерны, антипаттерны и приёмы, виды архитектуры и др.
Одна из глав книги посвящена такому понятию как записи архитектурных решений (Architecture Decision Record, ADR). Это созвучно с тем, что мы сейчас реализуем у себя в команде разработки, поэтому очень хочу рассказать)

Architecture Decision Record - это текстовый файл, который создаётся для описания конкретного архитектурного решения. Мы у себя используем .md файлы и храним их в Git. Есть и другие инструменты и форматы, например, страница в вики вашей компании.
Файл должен быть лаконичным, и содержать разделы, о которых я расскажу ниже.

1️⃣ Название - короткое описание архитектурного решения, должно быть информативным и понятным, чтобы быстро ориентироваться, о чём эта запись
2️⃣ Статуc ADR - на какой стадии находится данное арх. решение: принято, или ещё обсуждается (Request For Comments, RFC), а может заменено новым ADR
3️⃣ Контекст - ситуация, которая привела к созданию ADR и принятию решения
4️⃣ Решение - сама суть архитектурного решения и его полное обоснование. Важно уделить особое внимание именно обоснованию решения, ответить на вопрос «почему». Этот момент является ключевым и самым полезным (имхо) в документировании архитектуры
5️⃣ Последствия - описание того, что влечёт за собой принятое архитектурное решение. Какие плюсы и минусы у него есть, их анализ
6️⃣⭐️ Альтернативы - опциональный раздел, в котором сосредоточены альтернативные решения указанной проблемы, и причины, по которым эти решения не были приняты командой
7️⃣ ⭐️ Комплаенс - в книге рекомендуется включать этот раздел в свои ADR. Это описание, каким образом контролировать соблюдение требований данного арх. решения, должно ли это контролироваться вручную или можно автоматизировать. У нас пока такого раздела нет
8️⃣⭐️ Примечания - также опциональный раздел для указания автора, дат утверждения и замены, лиц, участвующих в принятии и утверждении данного решнеия и т. д.
9️⃣
🔟 Вы великолепны 🤪😂

Вы спросите меня, зачем всё это нужно? И я вам отвечу)))

🌟 Это эффективный способ документировать архитектуру - всё в одном месте, можно наблюдать инкремент, описаны альтарнативы, + и -
🌟 Не приходится проводить повторные R&D, потому что результаты предыдущих архитектурных дилемм записаны, оформлены, подведены итоги
🌟 Чуть полегче онбордить новых разработчиков/внедрять иннерсорс, когда приходят с «а почему», можно прислать ссылку на «а потому» и вопрос исчерпан (но естественно пересмотр архитектуры и принятых решений должен быть)
🌟 Можно унифицировать подход к архитектуре микросервисов и тем самым снизить эксплуатационные издержки на поддержку

Приземлю на конкретику. Если вы приходите в сервисы и не понимаете

🟢 почему условный Вася воткнул тут кафку, а не обошёлся рестом
🟣 почему решили использовать gRPC, а не десериализовать json’ы до талого))
🔵 почему используется именно эта библиотека для генерации PDF
🟡 зачем тут Camunda прости господи)))
🟢 почему эту интеграцию реализовали из г… теми ресурсами, которые были доступны на тот момент 🥲
🟣 почему все сервисы развёрнуты в k8s, а один стоит на виндовой тачке в другом контуре

Как я уже упомянула, мы у себя потихоньку начали внедрять практику написания ADR. Пока описано не всё, но уже сейчас удобно вспомнить какие решения мы приняли и почему решили именно так.

Расскажите, знаете про такой инструмент? Практикуете?

Джавист Роман ☕️

09 Oct, 13:07


Покрытие тестами и/или Как добавить JaCoCo в проект Gradle

Чтобы спокойно спать по ночам разработчикам нужно писать тесты. Много тестов. И один из способов проверять себя - это следить за процентным покрытием тестами кода.

В нормальном проекте, в котором есть время на их написание, обычно планка идет от 80% и выше, но не больше чем 95%. Здесь не нужно упарываться и доводить эту планку до 100%.

Да, я знаю, что даже 100% покрытие тестов не гарантирует, что наш код оттестирован полностью. Но это и не цель - цель понимать, какое кол-во кода ВООБЩЕ НЕ ТЕСТИРУЕТСЯ. Это очень важный пункт и его нужно понимать. То есть если у нас покрытие 49%, то это значит, что в 51% кода тесты вообще не бывали и как там оно работает одному богу известно. А это в свою очередь гарантирует, что могут быть тривиальные дефекты, проблемы с рефакторингом и прочие "радости" побочки при отсутствии тестов.

Самый быстрый и простой способ следить за этим - это добавить JaCoCo (Java Code Coverage) плагин. Он поможет нам в этом деле.

Покажу на примере работы с gradle, благо там все просто. Нужно добавить следующую кодовую часть в build.gradle:

В секцию плагинов добавить плагин JaCoCo:

plugins {
...
id 'jacoco'
...
}

Далее еще настройки, коих по началу хватит с головой, чтобы решить эту проблему:

jacoco {
toolVersion = "0.8.7"
}

test {
finalizedBy jacocoTestReport
}

jacocoTestReport {
reports {
xml.enabled true
html.enabled true
csv.enabled false
}
}

jacocoTestCoverageVerification {
violationRules {
rule {
limit {
// минимальное покрытие тестами в процентах
minimum = 0.50
}
}
}
}

check.dependsOn jacocoTestCoverageVerification

И все, теперь при запуске билда gradle clean build если покрытие будет меньше 50%, то выйдет ошибка такая:

* What went wrong:
Execution failed for task ':your-project:jacocoTestCoverageVerification'.
> Rule violated for bundle your-project: instructions covered ratio is 0.49, but expected minimum is 0.50

И все, дело в шляпе. Далее дело уже за вами.

Разумеется всех желающих сказать свое мнение приглашаю в коменты)

Джавист Роман | Подписаться