Primitive Obsession - это ситуация, когда в коде слишком много важных бизнес-сущностей хранятся как обычные
String, int, long или BigDecimal.Например:
public void pay(BigDecimal amount, String currency, String email) {
// код
}На первый взгляд всё нормально. Но со временем такой код становится опасным.
Потому что BigDecimal сам по себе не говорит, что это именно деньги. String не говорит, что это валюта. А email можно случайно передать туда, где ожидался userId.
Пример ошибки:
pay(
new BigDecimal("100.00"),
"user@mail.com",
"USD"
);
Код компилируется, но логика уже сломана: email и currency перепутаны местами.
В реальных системах такое часто происходит с id, email, phone, currency, amount, status, role, countryCode и другими значимыми полями.
Корректный подход, выносить важные значения в отдельные value object:
public record Email(String value) {
public Email {
if (value == null || value.isBlank()) {
throw new IllegalArgumentException("Email is blank");
}
}
}Теперь метод становится понятнее:
public void pay(Money amount, CurrencyCode currency, Email email) {
// код
}Так сложнее случайно перепутать параметры, а валидация живёт рядом с самим значением.
Например, деньги тоже можно оформить отдельным типом:
public record Money(BigDecimal amount) {
public Money {
if (amount == null || amount.signum() < 0) {
throw new IllegalArgumentException("Invalid amount");
}
}
}Теперь отрицательная сумма не сможет незаметно пройти дальше по бизнес-логике.
Такой подход особенно полезен в доменной логике, платежах, заказах, авторизации, CRM, банковских системах и любых проектах, где ошибка в одном поле может стоить дорого.
👉 Java Ready | #практика