Обновить
24
3
Константин Шибков@sendelust

Пользователь

Отправить сообщение

Уже есть поддержка, вот что пришло в первую очередь:

  • Kotlin имеет inline value classes — это лёгкие обёртки над примитивами с инвариантами, без overhead на runtime. Пример:value class Weight(private val grams: Long) , компилятор “инлайнит” его как long, но даёт типобезопасность и методы.

  • Rust использует newtype pattern:  pub struct Weight(pub u64);  — zero-cost абстракция, где компилятор оптимизирует до голого числа, но с отдельным типом для предотвращения ошибок.

Также примеры на C# тоже укладываются в «есть прямо сейчас», а Java ждёт проекта Valhalla. На Хабре писали про это Project Valhalla: эпичный квест Java за перфомансом)

красиво и синтаксис понятный)

Вы сделали разные типы? И каждый выводит TPoint? Интересно узнать, что тут значит равнозначные.

Отличие есть, крато:

  • Newtype это только про типовую безопасность. Обернули String → получили другой тип. Не получили overhead, а компилятор не обманешь.

Думаю с учетом примера на Rust его дока и подходит. Rust Design Patterns – Newtype

  • ValueObject пошире, это можно сказать "усложненный" newtype, включающий инварианты и может содержать не одно поле при необходимости.

😁 И всё это придумали не джависты, не во всем они виноваты)

Спасибо за поддержку! Я бы сказал, что это очень смело на Хабре высказываться за автора! Жму руку)

Не-а, не кажется 🙂
Я не предлагаю всем срочно делать VO и что без этого у нас всё развалится. Нет, это просто подход, который может решить некоторые проблемы.

P.S. на коммент ответил :)

где-то должно быть написано, что Left - это ошибка, а Right - это значение

В доке библиотеки написано) By convention the success case is Right and the failure is Left. Это как с assertEquals(a , b) в JUnit, что первое, а что второе. Благо AssertJ упрощает и уже на надо запомнить это соглашение о порядке элементов. И использование внешней библиотеки или подхода должно быть не внезапным событием для ревьювера, а заранее спланированных событием.

Чтобы это не создавало когнитивную нагрузку, то всегда можно сузить возможности для разработчика и отдать это компилятору:

Either<DomainError, T>

В данном случае накосячить с правой стороной сложно, а с левой - "а давайте для случаев, когда нужно возвращать VIP статус, будем там возвращать строчку "VIP", а если не "VIP" - то сообщение об ошибке.

Ок, если рассматривать текст статьи как бездумный копипаст и использовать String, то да. Полностью прав с вашим комментом, но у нас есть же объекты. Вы можете возвращать, то что вам удобно. Можно сделать sealed класс с исключениями DomainError, а там используйте что удобно и готовый текст или код ошибки для дальнейшей локализации ответа. По сути вы это и описали во второй части комментария – делаем систему возвратов строго типизированной. И я разделяю этот подход.

А возможно я тут и сам попал в Primitive Obsession силки 😁 кто знает)

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

Это псевдокод) там нет new если мы говорим о Java синтаксисе. И подразумевает, что объекты созданы на основе одинаковых значений.

Но мне нравится это замечание и я верну синтаксис Java, чтобы не было вопросов и затыков при чтении)

Коммент для треда "ваша джава творит дичь" :)

В Java тоже обычно используют BigDecimal для точности. Но есть бесячая проблемка. Если в C# при сравнении decimal "созданной с разной точностью" сравнения происходят без проблем:

decimal a = 1.1m;
decimal b = 1.10m;

Console.WriteLine(a == b);  // true
Console.WriteLine(a.Equals(b));  // true

То в Java разная точность и надо сравнивать через compare, так как через equals не будет true. Поэтому связываться с этим в бизнес логики совсем неинтересно:

var a = new BigDecimal("1.10"); //scale = 2
var b = new BigDecimal("1.1"); //scale = 1

System.out.println(a.equals(b)); //false
System.out.println(a.compareTo(b) == 0); //true
System.out.println(a.setScale(2).equals(b.setScale(2))); //true

Строки взяты для быстрой настройки scale и для точности.

Конечно есть, в Java есть стандарт JSR 385 (Units of Measurement API 2.0) и популярная реализация это библиотека Indriya. Мы его используем, особенно востребована библиотека в "международных" сервисах, когда величины разные и зависят от страны.

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

Для денег тоже есть устоявшаяся библиотека JSR 354 RI Moneta. И я бы ее рекомендовал для работы с деньгами по умолчанию.

Да, вы правы, окрулять не надо если у нас и так целые значения и храним в long.

Мне хотелось этим показать, что можно упаковать в метод правила округления.

Думаю вариант с аргументов double лучше демонстрирует идею:

public static DiscountRate ofFraction(double raw) {
    var bd = BigDecimal.valueOf(raw);              
    var normalized = bd.setScale(2, RoundingMode.HALF_UP);
    return new DiscountRate(normalized);
}

Хотя если копать дальше, я бы предпочёл округлять и нормализовать scale именно в конструкторе в итоге, тогда точно будет одна точка подготовки данных.

Да, они вечером этого же дня отменили бронь)

Никаких открыток! Никакого праздника! Только деньги вернули) И еще сказали «В конце описания же было написано, что тестовая квартира»

По сути, где это будет не так важно, это может быть даже Tilda, DokuWiki и прочее. Для селлера достаточно ссылку иметь по которой всегда будет актуально. Я не очень люблю PDF, так как они устаревают и надо как-то всех уведомить "Скачайте новое" или сделать рассылку, чтобы этот PDF все получили.

Думаю генерить PDF при изменении доки и предлагать этот вариант это хорошее дополнение, кто любит твёрдый формат в виде файла у себя локально)

Ох, уж эти тестовые лоты) Как-то забронировал квартиру посуточно в другом городе – а она оказалась тестовая 😆

👍 Отличный гайд - все в одном месте! Интересно, как быстро он устареет?

Кстати отличная идея, пак сделать несложно, накидываешь в конфиг файлик нового расширения другие расширения и получаешь свой vsix файл. Согласен,а то по ссылкам бегать и одинаковые кнопки жать хоть и надо один раз - но муторно. У меня даже есть заготовка, надо дожать и будет проще получить готовую альтернативную среду.

Ну тут автоимпортам приходится пока еще поработать, не у всех же разом работу отнимать)

Интересно, до devcontainers не добрался еще. По поводу локального запуска приложения, тут считаю на старте надо сделать однокнопочный запуск, типа ./run.sh , а рядом ./run-tests.sh и тд. Там внутри использую docker-compose/skaffold или что необходимо другое. Из плюсов - не важно IDE, каждый может запускать и писать где хочет - запуск не зависит от IDE. Из минусов, страдают только те, кто использует голый Windows для разработки, поэтому упоминал WSL2 как хороший универсальный вариант.

DevContainers может мне заменить этот ворох скриптов?

1

Информация

В рейтинге
1 029-й
Зарегистрирован
Активность

Специализация

Бэкенд разработчик
Старший
Java
Базы данных
Java Spring Framework
Docker
Linux
Git