tgoop.com/java_fillthegaps/561
Create:
Last Update:
Last Update:
Новая фича Java 23: Derived Record
Внимательные читатели давно заметили, что я люблю разбирать джаву и разное API с точки зрения дизайна. Смотреть, как решается исходная проблема и насколько удобно и адекватно решение.
Сегодня сяду на любимого конька и расскажу о новом синтаксисе, который появится в java 23 — Derived Record.
Напомню, что records компилируются в final классы с final полями. Неизменяемые переменные — тренд последних лет. В этом подходе данные не меняются, а при модификации создаются новые объекты.
Недостаток очевиден — чтобы создать объект на основе предыдущего, надо написать довольно много кода. Возьмём простой пример — record Point с двумя полями: Х и Y:
record Point(int x, int y) { }
Point p1 = new Point(1,1);
Допустим, нам нужна точка p2, у которой Х в 2 раза больше, чем у p1:
Point p2 = new Point(p1.x()*2, p1.y());
Надо прочитать ВСЕ поля исходного объекта и передать их в конструктор с нужными модификациями. Даже в классе с двумя полями надо напрячь глаза, чтобы понять, какой параметр меняется. В реальной жизни полей больше, и получается максимально унылая простыня кода.
Вместо конструктора удобно использовать with методы:
Point p2 = p1.withX(p1.x()*2);
Сразу видно параметр, которым отличаются точки🔥
With методы — отличное решение, но не идеальное.
Возьмём случай, когда между полями должны соблюдаться некоторые соотношения. Например, Х всегда должен быть больше Y.
With методы работают только с одним полем и не знают про дальнейшие изменения. Поэтому сложная валидация в них затруднительна. После вызова
Point p3 = p1.withX(p1.x() - 5);
получаем объект со сломанным инвариантом. Мы не знаем, вызовет ли пользователь потом withY, и не можем это проконтролировать.
Новый JEP работает с такими случаями и предлагает создавать объекты так:
Point p4 = p1 with {
x *= 2;
y *= 2;
};
🔸 Названия полей p1 берутся в качестве локальных переменных с теми же именами
🔸 Выполняются преобразования в скобках
🔸 После выполнения блока вызывается канонический конструктор Point, где находится валидация полей
🔸 Полученный объект присваивается объекту p4
В целом всё неплохо, но возникает вопрос целесообразности. На моей практике рекордс обычно используют как контейнер данных, который редко меняется. Если всё же меняется, то обычно это простая логика, куда бы идеально вписались with методы. Если бы records превращались в классы с готовыми with методами — было бы супер удобно.
Я редко встречала в рекордах сложную валидацию и жёсткие отношения между полями. Мне кажется, добавлять новый синтаксис для таких случаев избыточно. Если нужна проверка инвариантов, можно написать свой метод.
Поэтому вердикт новой фиче — сомнительно, но окэй. Я бы потратила человеко-часы на что-нибудь другое🙂 К слову, это уже вторая фича java 23, которая не вызвала у меня восторга. Первой были Gatherers, почитать можно тут
А как вам новый синтаксис в рекордах?
🔥 - огонь, очень полезно
👍 - не вау, но пусть будет
❤️ - просто спасибо за пост:)
BY Java: fill the gaps
Share with your friend now:
tgoop.com/java_fillthegaps/561