Найти в Дзене
Java и инкапсуляция без магии
Публичные поля выглядят удобно ровно до первого бага. account.balance = new BigDecimal("-100"); Код скомпилировался, объект изменился, бизнес-правило сломалось. Никакой проверки, никакого контроля, никакой гарантии, что BankAccount остаётся в корректном состоянии. Поэтому поле баланса не должно быть частью публичного API. Наружу можно отдать чтение, а изменение проводить через методы, где явно описаны правила: private BigDecimal balance = BigDecimal.ZERO; public BigDecimal getBalance() { return balance; } public void withdraw(BigDecimal amount) { if (amount...
4 часа назад
⚡️ Бинарный поиск, который вы выучили, скорее всего, был неправильным
Джон Бентли опубликовал реализацию бинарного поиска в *Programming Pearls* после того, как доказал её корректность и протестировал. Баг прожил почти 20 лет. Позже Джошуа Блох нашёл точно такую же ошибку в реализации бинарного поиска, которую сам написал для JDK. Исследование 1988 года показало: корректный бинарный поиск был только в 5 из 20 учебников. Ошибка проявляется только на массивах размером 2^30 элементов и больше. Проблема возникает...
4 дня назад
🖥 Java постепенно закручивает гайки вокруг мутации final-полей через reflection
В JDK 26 появятся предупреждения, если код меняет final-поля через Reflection API. Это часть движения к тому, чтобы final снова означал реальную неизменяемость, а не «почти immutable, пока кто-то не сделал setAccessible(true)». Проблема старая: фреймворки, сериализация, DI и cloning часто создавали «пустой» объект, а потом дописывали поля напрямую. Для final это ломает саму идею конструктора, инвариантов и безопасной инициализации. Что предлагает Java-команда вместо этого: - использовать constructor...
6 дней назад
Java-совет, который кажется мелочью, пока кто-то не сломает вам состояние объекта
Не возвращайте наружу изменяемые внутренние коллекции. Плохой вариант: ```java public List<String> getMembers() { return members; } Так вызывающий код получает прямой доступ к вашему внутреннему списку. После этого он может сделать: team.getMembers().clear(); И внезапно вся команда исчезла. Не через метод доменной модели, не через проверку прав, не через бизнес-логику, а просто потому что геттер отдал наружу ссылку на mutable state. Нормальный вариант: public List<String> getMembers() { return Collections...
6 дней назад
💡 Java: вложенные if-else быстро превращают код в лабиринт
Когда вся логика уходит в глубокую вложенность, читать метод становится больно: основной сценарий спрятан где-то внизу, а перед ним несколько уровней проверок. Проще использовать guard clauses - ранние проверки с выходом из метода. Было: - проверяем user - внутри проверяем active - внутри проверяем order - внутри проверяем paid - только потом выполняем основное действие Стало:...
1 неделю назад
📌 Magic numbers в Java - мелкая привычка, которая потом превращает поддержку кода в археологию
Когда в коде встречается 86400, 7, 1.21 или 5000, компилятору всё равно. Человеку - нет. Через месяц уже приходится вспоминать, что это было: секунд в дне, дней сессии, НДС или задержка перед повторной попыткой. Плохой вариант выглядит так: if (sessionAgeSeconds > 86400 * 7) Формально код работает. Но смысл спрятан внутри чисел. Нормальный вариант: SECONDS_PER_DAY SESSION_DAYS VAT_RATE RETRY_DELAY_MS Теперь намерение видно прямо в месте вызова. Не нужно угадывать, почему именно 7, что означает 5000 и можно ли безопасно поменять значение...
1 неделю назад
🖥 Java наконец начал подстраховывать разработчика там, где раньше легко прятались баги
В switch expression начиная с Java 14+ компилятор проверяет, что обработаны все возможные значения. Если у вас enum и вы забыли один из вариантов, код просто не соберётся. Это даёт сразу несколько плюсов: - меньше скрытых багов после рефакторинга - безопаснее расширять enum - компилятор...
2 недели назад
Spring Boot: когда нужно контролировать HTTP-ответ полностью
Если обычного return user уже мало, в Spring Boot есть ResponseEntity<T>. Он позволяет явно управлять всем ответом: • статусом HTTP • заголовками • телом ответа • обработкой ошибок • поведением API в нестандартных сценариях Пример: пользователь найден - возвращаем 200 OK, тело ответа и кастомный header. Пользователь не найден - возвращаем 404 NOT FOUND без лишней магии...
2 недели назад
Java-ошибка, которую лучше ловить на компиляции, а не в проде
В Java @Override - это не украшение над методом, а простая защита от глупых ошибок. Представь базовый класс: class Report { void print() { // ... } } Ты хочешь переопределить метод, но случайно пишешь prnt() вместо print(): class PDFReport extends Report { void prnt() { // ... } } Код скомпилируется. Но метод print() не переопределён. Ты просто создал новый метод с опечаткой, а старое поведение осталось на месте...
2 недели назад
🚀 Request ID в Spring Boot - мелочь, которая спасает часы дебага
Когда API начинает сыпаться ошибками, главный вопрос не «что сломалось», а «где именно сломалось». Request ID решает эту боль просто: каждому входящему запросу выдаётся уникальный идентификатор, который потом проходит через логи, заголовки и внутренние вызовы. В итоге можно быстро найти весь путь конкретного запроса: • где он пришёл • какой сервис его обработал • на каком шаге появилась...
2 недели назад
Spring Boot: уберите try/catch из контроллеров
В Spring Boot не нужно размазывать обработку ошибок по каждому endpoint через бесконечные try/catch. Для этого есть @RestControllerAdvice. Идея простая: вы выносите обработку исключений в один глобальный класс, а контроллеры оставляете чистыми. Например: @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<?> handleNotFound(ResourceNotFoundException ex) { return ResponseEntity .status(HttpStatus.NOT_FOUND) .body(new ErrorResponse("NOT_FOUND", ex...
3 недели назад
Spring Boot магия, которая на самом деле просто проверка classpath
@ConditionalOnClass - одна из тех аннотаций, из-за которых Spring Boot кажется умным. Она говорит фреймворку: «Включи этот bean или конфигурацию только если нужный класс реально есть в проекте». Простой пример: @Configuration @ConditionalOnClass(DataSource.class) public class DataSourceAutoConfiguration { // загружается только если доступен javax.sql.DataSource } То есть Spring Boot не пытается настраивать всё подряд. Он смотрит: • есть ли нужная библиотека в зависимостях...
3 недели назад