Записи, пожалуй, самая обсуждаемая фича, появившаяся в Java 14. В то же время вызывает много критики из-за их необъектно-ориентированного характера. Типичный аргумент гласит, что записи — это концепция процедурного программирования, и ей нет места в объектно-ориентированном языке.
Действительно ли записи поощряют процедурное, а не объектное мышление?

Ну да и нет. Я полностью согласен с тем, что записи не являются объектно-ориентированной функцией, с другой стороны, я считаю, что для них есть допустимые варианты использования даже в идеально объектно-ориентированных приложениях.
Причина в том, что нет настоящих объектов на границах. Рассмотрим, например, ресурс REST, объект базы данных или свойства конфигурации. Это всего лишь структуры данных, но они должны быть представлены в коде Java.
Эволюция рекордов
Конечно, у нас есть типы структур данных, такие как Map или Set в Java, и их достаточно для многих случаев. Однако иногда полезно иметь типизированную структуру данных — например, для декларативной проверки, маршалинга или отображения. Традиционно Объекты передачи данных (DTO) используются в таких сценариях:
class AccountData {
private String username;
private String password;
private String email;
public AccountData(
String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AccountData that = (AccountData) o;
return username.equals(that.username) &&
password.equals(that.password) &&
email.equals(that.email);
}
@Override
public int hashCode() {
return Objects.hash(
username, password, email);
}
}
Ну, это действительно много стандартного кода для такой простой вещи. Его можно ненавидеть, можно любить, но Ломбок довольно элегантно восполняет именно этот пробел:
@Data
class AccountData {
private String username;
private String password;
private String email;
}
Lombok основан на манипуляциях с кодом, которые можно рассматривать как неадекватную «черную магию», которую многие разработчики не хотят иметь в своих кодовых базах. Java 14 решает эту проблему с помощью записей:
record AccountData (
String username, String password, String email) {}
Любое сходство с классами данных Kotlin чисто случайно:
data class AccountData (
var username: String, var password: String, var email: String)
Проблема с DTO
Итак, в чем здесь проблема? Записи Java, похоже, представляют DTO как языковую функцию. В чем проблема с DTO? "О" есть. Объекты передачи данных вообще не являются объектами! DTO — это просто типизированная структура данных.
Код должен быть как можно более явным, а структуры данных не должны называться объектами. Это заблуждение приводит к плохому проектированию объектов, обычно к печально известной анемичной модели предметной области.
С другой стороны, у записей (и даже у ломбокской аннотации @Data) нет объекта в имени. Записи делают это явным: данные рассматриваются как данные.
Вывод
Записи Java — это новая функция, которая добавляет в язык дополнительный тип структуры данных. В отличие от DTO, записи делают структуры данных в коде явными. Это правильные инструменты для правильных целей. При неправильном использовании они становятся злыми слугами, как и все остальное.
Я не думаю, что записи могут вызвать какой-либо сдвиг мышления от объектно-ориентированного дизайна к процедурному, потому что хороший объектно-ориентированный дизайн не рассматривает DTO как объекты, и записи не могут этого изменить. Простота использования сравнима с Lombok, но без магии; это означает, что искушение использовать записи не должно быть больше. Поскольку анемичное моделирование с DTO никогда не было хорошим объектно-ориентированным дизайном, я считаю, что записи не сделают его намного хуже.
В Java есть гораздо более опасные общие практики, такие как нулевые ссылки, статические методы и глобальные константы, но это совсем другая история…
Первоначально опубликовано в моем блоге.