💡 SOLID: принцип подстановки Лисков (LSP) говорит:
🔁 объекты базового класса должны без проблем заменяться объектами его подклассов.
Если подкласс меняет поведение так, что код начинает ломаться — дизайн неправильный.
❌ Плохой пример
У нас есть Vehicle с методом startEngine().
Мы наследуем Bicycle, но… у велосипеда нет двигателя — и метод бросает исключение.
Такая иерархия:
Теперь любой тест, ожидающий, что любой Vehicle умеет завести двигатель, падает.
👉 Подкласс ведёт себя не так, как базовый — LSP нарушен.
✅ Как исправить
Разделяем ответственность на интерфейсы:
Теперь только те объекты, которым по смыслу нужен двигатель, реализуют Motorized.
🧠 Вывод
✔ Подклассы не должны ломать ожидания, заложенные в базовый класс.
✔ Лучше разделить поведение, чем «затыкать» методы исключениями.
✔ LSP делает код предсказуемым и безопасным для расширения.
#Java #JavaDev #SOLID #CleanCode
🔁 объекты базового класса должны без проблем заменяться объектами его подклассов.
Если подкласс меняет поведение так, что код начинает ломаться — дизайн неправильный.
❌ Плохой пример
У нас есть Vehicle с методом startEngine().
Мы наследуем Bicycle, но… у велосипеда нет двигателя — и метод бросает исключение.
Такая иерархия:
class Vehicle {
public void startEngine() { ... }
}
class Bicycle extends Vehicle {
@Override
public void startEngine() {
throw new UnsupportedOperationException("Bicycles don't have engines!");
}
}
Теперь любой тест, ожидающий, что любой Vehicle умеет завести двигатель, падает.
👉 Подкласс ведёт себя не так, как базовый — LSP нарушен.
✅ Как исправить
Разделяем ответственность на интерфейсы:
interface Vehicle {}
interface Motorized {
void startEngine();
}
class Car implements Vehicle, Motorized {
public void startEngine() { ... }
}
class Bicycle implements Vehicle {
// без двигателя — всё ок
}
Теперь только те объекты, которым по смыслу нужен двигатель, реализуют Motorized.
🧠 Вывод
✔ Подклассы не должны ломать ожидания, заложенные в базовый класс.
✔ Лучше разделить поведение, чем «затыкать» методы исключениями.
✔ LSP делает код предсказуемым и безопасным для расширения.
#Java #JavaDev #SOLID #CleanCode
❤13👍12🔥3
💡 Java совет: используй `Instant` и `Duration` для точных вычислений времени
Работа со временем через
В современном Java для точных измерений есть java.time API.
🔹
Поддерживает точность до наносекунд.
// твоя логика
Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);
📌 Почему это важно:
• Наноcекундная точность
• Читаемый и современный API
• Меньше багов, связанных с таймзонами и устаревшими классами
Используй правильные инструменты — и время в коде перестанет быть источником боли.
#Java #JavaDev #Backend #CleanCode
Работа со временем через
System.currentTimeMillis() — это прошлый век. В современном Java для точных измерений есть java.time API.
🔹
Instant - это конкретная точка времени в UTC Поддерживает точность до наносекунд.
Instant now = Instant.now();
🔹 Duration - это разница между двумя моментами времени
Идеально подходит для измерения времени выполнения кода.
Instant start = Instant.now();
// твоя логика
Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);
📌 Почему это важно:
• Наноcекундная точность
• Читаемый и современный API
• Меньше багов, связанных с таймзонами и устаревшими классами
Используй правильные инструменты — и время в коде перестанет быть источником боли.
#Java #JavaDev #Backend #CleanCode
👍9😁3❤1🔥1
📌 Magic numbers в Java - мелкая привычка, которая потом превращает поддержку кода в археологию.
Когда в коде встречается
Плохой вариант выглядит так:
Формально код работает. Но смысл спрятан внутри чисел.
Нормальный вариант:
Теперь намерение видно прямо в месте вызова. Не нужно угадывать, почему именно 7, что означает 5000 и можно ли безопасно поменять значение.
Это особенно важно в бизнес-логике, где числа редко бывают случайными. Лимиты, комиссии, таймауты, скидки, сроки жизни сессии, количество попыток - всё это правила продукта, а не просто цифры в коде.
Хорошее правило простое: если число несёт смысл, дай ему имя. Исключения вроде
Чистый код часто начинается не с архитектуры, а с таких скучных вещей: убрать загадочные числа и оставить будущему разработчику понятный контекст.
#java #cleancode
Когда в коде встречается
86400, 7, 1.21 или 5000, компилятору всё равно. Человеку - нет. Через месяц уже приходится вспоминать, что это было: секунд в дне, дней сессии, НДС или задержка перед повторной попыткой.Плохой вариант выглядит так:
if (sessionAgeSeconds > 86400 * 7)Формально код работает. Но смысл спрятан внутри чисел.
Нормальный вариант:
SECONDS_PER_DAYSESSION_DAYSVAT_RATERETRY_DELAY_MSТеперь намерение видно прямо в месте вызова. Не нужно угадывать, почему именно 7, что означает 5000 и можно ли безопасно поменять значение.
Это особенно важно в бизнес-логике, где числа редко бывают случайными. Лимиты, комиссии, таймауты, скидки, сроки жизни сессии, количество попыток - всё это правила продукта, а не просто цифры в коде.
Хорошее правило простое: если число несёт смысл, дай ему имя. Исключения вроде
0, 1, индексов и простых счётчиков можно не трогать.Чистый код часто начинается не с архитектуры, а с таких скучных вещей: убрать загадочные числа и оставить будущему разработчику понятный контекст.
#java #cleancode
👍14❤6🥰1