Как управлять неизменяемыми объектами (в частности, записями Java)

Как управлять неизменяемыми объектами (в частности, записями Java)
Как управлять неизменяемыми объектами (в частности, записями Java) - mfrazi @ Unsplash

Поскольку Java record являются неизменяемыми, я не знаю, как правильно использовать их в контексте чего-то вроде CRUD-приложения.

Если мы возьмем очень простой пример "Организация" record:

public record Organization(String id, String name){}

Это выглядит хорошо, это неизменяемо и имеет все хорошие вещи, встроенные в него.

Теперь, допустим, я хочу обновить значение name, я делаю следующее:

public record Organization(@Id String id, String name){
    public static Organization withNewName(
            final String name, 
            Organization organization
    ) {
        return new Organization(organization.id, name);
    }
}

Это нормально, я создаю новое record с обновленным именем, которое мне нужно. Я могу использовать это в других местах моего кода:

Organization renamedOrganization = Organization.withNewName("Fancy company", organization);

Но это выходит из-под контроля, как только мы получаем пример из реального мира, где record может иметь 10 или даже 100 различных свойств. Ситуация становится еще более безумной, так как записи не имеют значений по умолчанию, поэтому при работе со списками, которые при инициализации имеют значение null.

Я использовал MapStruct для обработки базовой перестановки, но даже это кажется излишеством.

Каков правильный шаблон проектирования для работы с неизменяемыми объектами, когда их нужно обновить, чтобы они могли быть помещены в базу данных, должен ли я просто использовать классы и Lombok для сущностей базы данных?

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

Mutable хорош, когда вы работаете в одном потоке и не заботитесь ни о чем подобном.

Важно знать, зачем существуют те или иные вещи, чтобы использовать их, когда они полезны, а не просто потому, что они есть.

Тем не менее, использование правильного стиля для работы может облегчить вам жизнь. Я не думаю, что статичный стиль - это то, что нужно. Если вы собираетесь делать .withFoo() вещь, то делайте это бегло:

ProductViewModel updatedPVM = oldPVM
    .withId("1")
    .withName("Dohicky")
    .withDescription("A thingamabob")
;

Это обновляет несколько полей с помощью разумного выражения. Но это все еще Java, так что вам все еще нужен код с кодовой таблицей.

public record ProductViewModel(
        String id,
        String name, 
        String description,
        int price
) {

    public ProductViewModel withId(String id) {
        return new ProductViewModel(id, name(), description(), price());
    }

    public ProductViewModel withName(String name) {
        return new ProductViewModel(id(), name, description(), price());
    }

    public ProductViewModel withDescription(String description) {
        return new ProductViewModel(id(), name(), description, price());
    }

    public ProductViewModel withPrice(int price) {
        return new ProductViewModel(id(), name(), description(), price);
    }
} 

См: Установить значение одного из свойств в записи Java 15

Самый ли это быстрый способ создать новую неизменяемую запись из старой? Нет. Позволяет ли он избежать создания изменяемого класса, который является дубликатом записи? Да.

Так что да, Lomboks @builder на классе может сэкономить вам немного клавиатурного набора здесь. Код на плитах - это не весело. Но я не вижу причин, по которым однажды вы не сможете бросить @builder и на запись.

I know price was originally a float in the linked code but I just can't perpetuate that in a world of base 10 money .

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


LetsCodeIt, 7 февраля 2023 г., 00:33

Похожие посты