Java Portal | Программирование
11.8K subscribers
926 photos
68 videos
32 files
738 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика

Связь: @devmangx

РКН: https://clck.ru/3H4WUg
Download Telegram
Добавление логирования HTTP-запросов в Spring Boot API

Читать подробнее

👉 Java Portal | #cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
Базовые приёмы экономии памяти в Java

1. Ленивая инициализация "тяжёлых" полей

– Используйте lazy initialization, чтобы откладывать создание объекта до момента, когда он действительно понадобится.

2. Избегайте анонимных внутренних классов в циклах

– Каждое такое использование создаёт объект внутреннего класса — это скрытая нагрузка на память.

3. Используйте статические фабричные методы

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

4. Применяйте метод intern()

– Метод intern() класса String возвращает каноническое представление строки.
Используя intern(), можно гарантировать, что одна и та же строка будет представлена в памяти в виде единственного объекта, даже если она создаётся многократно.

String s1 = "hello";
String s2 = "hello".intern();


5. Используйте паттерн Flyweight для повторяющихся неизменяемых данных

– Экономит память за счёт разделения общих экземпляров (используется, например, в Integer.valueOf(), Boolean.TRUE и т.п.).

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Проектирование Backend-системы. Система уведомлений

Цель —> Разработать систему для доставки уведомлений пользователям через:

➣ Встроенные уведомления
➣ Push-уведомления (мобильные/веб)
➣ Email

С поддержкой:

✓Масштабируемости (миллионы пользователей)
✓Настраиваемых пользовательских предпочтений
✓Надежности, повторных попыток и дедупликации
✓Реального времени и пакетных оповещений

Пошаговый сквозной процесс

Шаг 1: Срабатывание события

✓ Приложение инициирует событие:

➣ Например, пользователь A лайкнул ваш пост
➣ Отправляется запрос POST на API /notify:

{
"event_type": "like",
"actor": "UserA",
"receiver": "UserB",
"object": "Post123"
}


Шаг 2: Добавление в очередь уведомлений

➣ API валидирует данные и помещает сообщение в очередь уведомлений (Kafka/RabbitMQ)

Шаг 3: Обработка воркером

✓ Воркер извлекает сообщение из очереди:

➣ Получает полную информацию о событии
➣ Обращается к сервису предпочтений:

- Подписан ли UserB на уведомления типа "like"?

- Хочет email или только in-app?

✓ Создает payload уведомления, например:

"UserA лайкнул ваш пост 'How to scale systems'"

Шаг 4: Рассылка по каналам

✓ На основе предпочтений воркер запускает соответствующие каналы:

➣ In-App Writer → сохраняет в БД (для отображения иконки колокольчика)
➣ Push-сервис → отправляет push (мобильный/веб) через FCM/APNs
➣ Email-сервис → ставит email в очередь (через SES/SendGrid)

Шаг 5: Отправка и повторные попытки

✓ Сервисы каналов:

➣ Декуплированы для изоляции отказов
➣ Повторяют попытки при сбоях (3–5 раз с экспоненциальной задержкой)
➣ Логируют статус (отправлено, ошибка, пропущено)

Шаг 6: Отображение in-app уведомлений

✓ UI вызывает /notifications?user=UserB
✓ Возвращаются N последних уведомлений из БД:

[
{ "text": "UserA лайкнул ваш пост", "read": false, ... }
]


Функции надежности

✓ Гарантированная доставка хотя бы один раз с идемпотентной записью
✓ Повторные попытки с экспоненциальной задержкой
✓ DLQ (Dead Letter Queue) для сообщений с ошибками
✓ Метрики: успех/неудача на сообщение
✓ Алерты при переполнении очереди или всплесках ошибок

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Хаки Java-кодинга, которые стоит знать разработчикам

✓ Используйте Map.ofEntries() для создания неизменяемых мап с несколькими парами
➣ Почему: короче, безопаснее, неизменяемо — снижает риск случайной мутации.

✓ Используйте Optional.map().orElse() вместо ручной обработки null
➣ Почему: устраняет проверки на null, читается лучше, легко комбинируется с другой логикой.

✓ Используйте Enum.valueOf() + name() для безопасного преобразования enum
➣ Почему: чище и удобнее для сериализации/десериализации enum'ов в API, БД или файлах.

✓ Используйте Comparator.comparing().thenComparing() вместо кастомной логики
➣ Почему: читаемо, понятно, без ошибок в условных сравнениях.

✓ Используйте Optional.ifPresentOrElse() вместо if-else с isPresent()
➣ Почему: выразительнее и чище — больше никаких ручных get() и нагромождений if-else

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Наблюдаемость Java-бэкенда с помощью OpenTelemetry

Читать подробнее

👉 Java Portal | #cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
Некоторые редкие, но ценные паттерны в Java

1. Null Object Pattern (Объект-Заглушка вместо null)

❯ Позволяет избежать проверок на null, возвращая объект с "пустым" поведением, реализующий ожидаемый интерфейс.
❯ Помогает держать код чистым, без множества if (obj != null) перед каждым вызовом метода.
❯ Используй, когда возврат null приводит к захламлению условными конструкциями.

2. Parameter Object Pattern (Объект параметров)

❯ Объединяет логически связанные параметры в один объект.
❯ Такой объект удобно прокидывать через разные уровни приложения, обеспечивая согласованность.
❯ Используй, когда у метода слишком много связанных аргументов.

3. Fluent Interface / Method Chaining (Флюент-интерфейс / Цепочка вызовов)

❯ Позволяет вызывать методы цепочкой, улучшая читаемость и выражая намерение кода (особенно в билдерах и конфигурациях).
❯ Используй в билдерах или для декларативной настройки.

4. Execute Around Method Pattern (Шаблон обёртки вокруг действия)

❯ Инкапсулирует логику подготовки и завершения вокруг основного действия.
❯ Гарантирует корректное освобождение ресурсов.
❯ Используй для управления ресурсами (файлы, БД и т.п.).

5. Initialization-on-Demand Holder (ленивый Singleton без synchronized)

❯ Безопасный, потокобезопасный и производительный способ ленивой инициализации Singleton'а без явной синхронизации.
❯ Используй, если нужен быстрый и потокобезопасный синглтон.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Разные подходы к структуре REST API:

1) Чистый CRUD-стиль

GET /users  
POST /users
PUT /users/{id}
DELETE /users/{id}


👍 Просто и предсказуемо
👎 Начинает хромать при действиях вне CRUD

2) Эндпоинты-действия

POST /users/{id}/deactivate  
POST /orders/{id}/cancel


👍 Ясное указание на сайд-эффекты
👎 Нарушает REST-идеи (глаголы в URL)

3) Вложенные ресурсы

GET /users/{id}/orders  
POST /users/{id}/addresses


👍 Удобно моделирует связи между сущностями
👎 Может вырасти в избыточную иерархию, тяжело поддерживать

4) Плоская структура + фильтры

GET /orders?userId=123  
GET /products?category=books&page=2


👍 Гибкие запросы
👎 Требует строгой валидации query-параметров

5) Версионирование API

GET /v1/users  
Accept: application/vnd.myapp.v2+json


👍 Безопасное развитие API
👎 Увеличивает накладные расходы на поддержку

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Плохие практики в коде, которые кажутся безобидными (но это не так)

1) Чрезмерное использование private-методов, скрывающее сложность

Когда private-методов слишком много, это ломает читаемость и разносит логику по коду. Визуально всё выглядит «чисто», но важные логические шаги оказываются скрытыми.

Когда это плохо:
Вы выносите код в private-методы просто ради самого факта выноса, а не потому что они переиспользуемы или несут отдельный смысл.

Как лучше:
Выделяйте разные зоны ответственности в отдельные классы или сервисы, которые сотрудничают между собой.

2) Автоматическое добавление private + геттеров/сеттеров по умолчанию

Бездумное добавление геттеров и сеттеров превращает ООП в просто «структуры с методами». Это нарушает инкапсуляцию, а не сохраняет её.

Вместо этого:

● Открывайте только те геттеры/сеттеры, которые реально нужны для бизнес-логики.
● Вместо сеттеров лучше использовать методы, которые выполняют осмысленные действия с валидацией.

3) Чрезмерное использование static-методов и переменных

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

Как лучше:
Используйте внедрение зависимостей или передавайте нужную конфигурацию явно туда, где она требуется.

4) Слишком большой класс (“God Object”)

Огромный класс, который делает всё подряд, превращается в чёрный ящик — его сложно тестировать, менять и понимать.

Как лучше:

● Применяйте принцип единственной ответственности (Single Responsibility Principle): у класса должна быть только одна причина для изменения.

● Разделяйте обязанности между меньшими по размеру классами или модулями.

5) Скрытие семантики null / Optional

Возврат null или скрытое использование Optional приводит к неожиданным ошибкам во время выполнения. Отсутствие или наличие значения должно быть выражено явно.

Как лучше:

● Используйте Optional<T> или другой задокументированный способ, чтобы показать, что результат может отсутствовать.

● Если это действительно ошибка — выбрасывайте чётко определённое исключение.

👉 Java Portal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM