Информация об изменениях

Сообщение Re[14]: Догонит ли net java? от 05.12.2022 22:26

Изменено 05.12.2022 22:27 ·

Re[14]: Догонит ли net java?
Здравствуйте, Sinclair, Вы писали:

S>·>Там ещё могут быть простыни кода, ведь у нас 40 полей которые надо по всякому вычислять и проставлять. Если модификация p происходит очень сложно, то хочется это всё разрезать на мелкие кусочки по разным методам или даже классам, иногда даже реюзабельным из разных мест.

S>Ну, и в чём проблема? Любое поле — это всего лишь значение. Для его вычисления есть формула.
Это интересно в основном с академической точки зрения.
На практике вдруг выясняется, что некоторые поля удобнее вычислять сразу пачкой. Например, надо прописать цену, её тип, валюту цены и значение в долларах, притом значение цены в долларах идёт в какую-нибудь коллекцию дополнительных атрибутов другой части документа.
Или стадиями, когда появляются частично сконструированные промежуточные объекты. Например, вначале сформировали список трейдов из заказа, потом каждому трейду прописали вознаграждение таким образом, что первый трейд берёт всё значение, а у всех остальных прописать нули. А потом нужно распределить коммиссию по этому списку трейдов пропорционально их размеру, оставляя остаток от деления последнему трейду. У объекта "трейд" все значения обязательные. Поэтому создать список трейдов для первой стадии (без коммиссии и вознаграждения) ты те сможешь, нужен список билдеров или, если иммутабельно, каких-то других, частичных типов. А если вспомнить, что список трейдов это всего лишь поле в каком-то развесистом документе, который тоже надо иммутабельно копировать...
Теоретически, конечно, это можно всё переписать функционально, на иммутабельных структурах, добавляя ещё типы, выворачивая порядок исполнения, но в итоге код получается сложнее для всяких оптимизаторов, запутаннее для человека, и далёк от спеки, который выдаёт бизнес. С билдерами же всё пишется как слышится и код хоть даже юзерам показывать можно — всё ясно что куда и откуда и в каком порядке.

S>В иммутабельном мире есть одна проблема — если, к примеру, целиковое "изменение" объекта тривиально расписывается в стиле

S>l.Add(42); // ah-ah!
Верно. Так же можно и забыть p = при updateAAA(p). Хуже того, можно ошибиться в copy-paste и получится x = updateAAA(y). С билдерами такой проблемы нет в принципе, т.к. используется одна сущность.

S>и всё будет работать, то с отдельными свойствами композитных объектов так сделать не получится. Если у меня immutable record Point(int x, int y), то запись вроде p.x += 5 запрещена.

И таких проблем с билдером нет. Поля билдера можно использовать как аккумуляторы значений из разных мест кода. Особенно хорошо, когда они коллекции.

S>И вот для обхода этой проблемы предлагается конструкция with.

S>Она позволяет легко и очевидно перейти от мутабельного кода к иммутабельному:
S>ip = ip with X = 10;
Тоже так себе, т.к. "неожиданно" меняется тип выражения: print("new position {}", mp.x += 5);

S>>>Почему нельзя просто сделать тот же With? Ведь при присванивании "в себя же" ескейп-анализ уберёт всю лишнюю нагрузку на GC, в итоге имеем тот же перформанс, лаконичный синтаксис, и отсутствие необходимости для каждого DTO еще и цельный билдер расписывать.

На ea я бы не полагался, ведь в 40 полях, разбито всё по методам-классам, коллекции, етс, это уже всё заблудится и потеряется.

S>·> p = updateDDD(p);

S>Да, а почему нет?
Помимо уже упомянутых недостатков выше, неясно зачем вообще так делать. Ну да, объект типа иммутабельный, а переменная-то внезапно мутабельная... Та же ж, вид с боку.

S>·>как тут можнро сделать красивее?

S>Эмм, да всё что угодно тут будет красивее.
S> (o, i) = updateBBB(o, i);
А теперь авто-рефакторингом добавь в updateBBB по всему коду параметр p.
Код выглядит красивее, но мейнтейнить его, внезапно, сложнее.

S>·>Лично мне пока самым удобным показалось то, что генерирует Avro, как тут. (генерацию setters для самих dto можно запретить, оставить только у билдеров).

S>Ну, это тот самый способ со сменой сигнатуры у сеттера на возврат self. Так себе решение, по сравнению с with operator, кмк. Лучше, чем ничего, конечно.
Суть в том, что есть два типа — иммутабельный dto и мутабельный билдер. И их можно конвертить между собой и явно использовать в разных частях кода.
Re[14]: Догонит ли net java?
Здравствуйте, Sinclair, Вы писали:

S>·>Там ещё могут быть простыни кода, ведь у нас 40 полей которые надо по всякому вычислять и проставлять. Если модификация p происходит очень сложно, то хочется это всё разрезать на мелкие кусочки по разным методам или даже классам, иногда даже реюзабельным из разных мест.

S>Ну, и в чём проблема? Любое поле — это всего лишь значение. Для его вычисления есть формула.
Это интересно в основном с академической точки зрения.
На практике вдруг выясняется, что некоторые поля удобнее вычислять сразу пачкой. Например, надо прописать цену, её тип, валюту и значение в долларах, притом значение цены в долларах идёт в какую-нибудь коллекцию дополнительных атрибутов в другой части документа.
Или стадиями, когда появляются частично сконструированные промежуточные объекты. Например, вначале сформировали список трейдов из заказа, потом каждому трейду прописали вознаграждение таким образом, что первый трейд берёт всё значение, а у всех остальных прописать нули. А потом нужно распределить коммиссию по этому списку трейдов пропорционально их размеру, оставляя остаток от деления последнему трейду. У объекта "трейд" все значения обязательные. Поэтому создать список трейдов для первой стадии (без коммиссии и вознаграждения) ты те сможешь, нужен список билдеров или, если иммутабельно, каких-то других, частичных типов. А если вспомнить, что список трейдов это всего лишь поле в каком-то развесистом документе, который тоже надо иммутабельно копировать...
Теоретически, конечно, это можно всё переписать функционально, на иммутабельных структурах, добавляя ещё типы, выворачивая порядок исполнения, но в итоге код получается сложнее для всяких оптимизаторов, запутаннее для человека, и далёк от спеки, который выдаёт бизнес. С билдерами же всё пишется как слышится и код хоть даже юзерам показывать можно — всё ясно что куда и откуда и в каком порядке.

S>В иммутабельном мире есть одна проблема — если, к примеру, целиковое "изменение" объекта тривиально расписывается в стиле

S>l.Add(42); // ah-ah!
Верно. Так же можно и забыть p = при updateAAA(p). Хуже того, можно ошибиться в copy-paste и получится x = updateAAA(y). С билдерами такой проблемы нет в принципе, т.к. используется одна сущность.

S>и всё будет работать, то с отдельными свойствами композитных объектов так сделать не получится. Если у меня immutable record Point(int x, int y), то запись вроде p.x += 5 запрещена.

И таких проблем с билдером нет. Поля билдера можно использовать как аккумуляторы значений из разных мест кода. Особенно хорошо, когда они коллекции.

S>И вот для обхода этой проблемы предлагается конструкция with.

S>Она позволяет легко и очевидно перейти от мутабельного кода к иммутабельному:
S>ip = ip with X = 10;
Тоже так себе, т.к. "неожиданно" меняется тип выражения: print("new position {}", mp.x += 5);

S>>>Почему нельзя просто сделать тот же With? Ведь при присванивании "в себя же" ескейп-анализ уберёт всю лишнюю нагрузку на GC, в итоге имеем тот же перформанс, лаконичный синтаксис, и отсутствие необходимости для каждого DTO еще и цельный билдер расписывать.

На ea я бы не полагался, ведь в 40 полях, разбито всё по методам-классам, коллекции, етс, это уже всё заблудится и потеряется.

S>·> p = updateDDD(p);

S>Да, а почему нет?
Помимо уже упомянутых недостатков выше, неясно зачем вообще так делать. Ну да, объект типа иммутабельный, а переменная-то внезапно мутабельная... Та же ж, вид с боку.

S>·>как тут можнро сделать красивее?

S>Эмм, да всё что угодно тут будет красивее.
S> (o, i) = updateBBB(o, i);
А теперь авто-рефакторингом добавь в updateBBB по всему коду параметр p.
Код выглядит красивее, но мейнтейнить его, внезапно, сложнее.

S>·>Лично мне пока самым удобным показалось то, что генерирует Avro, как тут. (генерацию setters для самих dto можно запретить, оставить только у билдеров).

S>Ну, это тот самый способ со сменой сигнатуры у сеттера на возврат self. Так себе решение, по сравнению с with operator, кмк. Лучше, чем ничего, конечно.
Суть в том, что есть два типа — иммутабельный dto и мутабельный билдер. И их можно конвертить между собой и явно использовать в разных частях кода.