LINUX.ORG.RU

Меня печалит жава

 ,


0

4

Наткнулся на такой код в спринге:

PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
map.from(settings::readTimeout).asInt(Duration::toMillis).to(this::setReadTimeout);
map.from(settings::connectTimeout).asInt(Duration::toMillis).to(this::setConnectTimeout);

Пришлось его скопипастить, потому, что при всей его гибкости как-то не очень он гибкий оказался там, где мне надо. Долго вкуривал, что тут написано, в итоге переписал по-простому:

if (settings.readTimeout() != null) {
  setReadTimeout(settings.readTimeout());
}
if (settings.connectTimeout() != null) {
  setConnectTimeout(settings.connectTimeout());
}

Да, я понимаю, что тут два раза вызывается геттер settings.xxx и это чисто теоретически может привести к багу… Но по-моему это мелочь. А то, что код нечитаемый получился сверху, это вообще не мелочь.

Что за моду притащили в жаву? Никогда же такого не было, писали просто и понятно. Кому это надо? Вы тоже выпендриваетесь, пытаясь в одну строчку засунуть побольше токенов?

★★★★

У вас в жаве так нельзя?

if ((var flag = settings.readTimeout()) != null) {
  setReadTimeout(flag);
}

Что за моду притащили в жаву? Никогда же такого не было, писали просто и понятно. Кому это надо?

Просто и понятно это не про жаву.

MOPKOBKA ★★★★★
()
Ответ на: комментарий от vbr

Ну так точно можно, как я понял это и избавит тебя от двойного чтения settings.

Flag flag;
if ((flag = settings.readTimeout()) != null) {
  setReadTimeout(flag);
}

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

map, filter, reduce это лучше чем их ручное изображение в цикле, я думаю дед именно этим и занимается...

Я думаю тебе стоит рассмотреть 1С, язык довольно простой, там таких приколов наверное никто не устраивает.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA
if (getData() instanceof String data) {
  setData(data);
}

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

vbr ★★★★
() автор топика
Последнее исправление: vbr (всего исправлений: 1)

Вы тоже выпендриваетесь, пытаясь в одну строчку засунуть побольше токенов?

Иногда я так делал, да. Казалось, что так код «красивше» что ли. А потом через какое-то время сам не понял, что написал, поэтому стараюсь теперь писать в несколько строк, но более понятно.

Zhbert ★★★★★
()
Ответ на: комментарий от vbr

Кажется, что в данном случае оно как раз помогло бы:

if (settings.readTimeout() instanceof Duration duration) {
    setReadTimeout(duration.toMillis());
}

if (settings.connectTimeout() instanceof Duration duration) {
    setConnectTimeout(duration.toMillis());
}
static_lab ★★★★★
()
Ответ на: комментарий от static_lab

Кажется, что в данном случае оно как раз помогло бы

если бы ТС вместо куска кода «из Спринг» дал бы ссылку на место в коде спринг где он это нашел, был бы повод для дискуссии. А так, пример выглядит тщательно очищеным от контекста и потому нерелевантным

FishHook
()
Ответ на: комментарий от FishHook

Не совсем этот пример, но похожий: https://github.com/spring-projects/spring-boot/blob/04c919b94ebee42dbe9d54a7e14d5ae3d8796797/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/task/ThreadPoolTaskSchedulerBuilder.java#L197

А так в Спринге часто этот паттерн встречается: https://github.com/search?q=org%3Aspring-projects+PropertyMapper+map+%3D+PropertyMapper.get%28%29.alwaysApplyingWhenNonNull%28%29&type=code&p=1

Похоже, что они стремятся сократить число строк при копировании параметров конфигурации, потому что параметров может быть много, избежать создания промежуточных переменных и унифицировать «тупо копирующий» код с «преобразующим».

static_lab ★★★★★
()
Последнее исправление: static_lab (всего исправлений: 1)
Ответ на: комментарий от vbr

Гуд, спасибо. Глянул в код вот сюда https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/PropertyMapper.java#L106

вижу, что propertyMapper::from делает кое-что больше чем делает ваш улучшенный вариант кода, в котором вы избавились от вызова map.from, то есть ваш код не выполняет вот этого

if (this.sourceOperator != null) {
   source = this.sourceOperator.apply(source);
}

подозреваю, что здесь происходить нечто важное

FishHook
()

А в чём проблема? Всё просто и понятно, если регулярно джавой пользоваться. А если не пользоваться, то в любом языке можно найти какие-то непонятные конструкции. И джава явно тут не чемпионом будет по этому показателю.

Ghostwolf ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Хз. Мне было понятно с первого взгляда, хотя PropertyMapper никогда не использовал.

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

WatchCat ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Это вы просто с непривычки, лапши не покушавши. Наверняка там откуда вырвали этот кусок кода очень большая вложенность, вот её и убирали, потому как конструкции вида

do()
{
    if()
    {
        foreach()
        {
            switch()
            {
                case:
                    for()
                        {
                            if()
                            {
                                do_something_usefull
                            }
                        }
            }
        }
    }
}
while()
ещё более нечитаемы, но иногда подобная лапша бывает нужна, например, когда вариантов того что надо делать слишком много. Уверен такой лапшой (возможно в замаскированном виде когда её разбивают на функции/методы для читабельности полнится код любого браузера). Можно конечно сделать 100500 простых функций в которые попрятать от глаз сложные условия, да так и делают, но тогда теряется наглядность всего происходящего ужаса.

peregrine ★★★★★
()
Ответ на: комментарий от FishHook

Само собой PropertyMapper — более универсальное решение, но здесь (и в других подобных местах) он используется для инициализации ненулевыми значениями. Поэтому реализация ТСа — это более простое для понимания решение для частного случая. Обобщать ему здесь ничего не требуется, но логику оригинального кода он не упустил, т.е. код работает точно так же.

static_lab ★★★★★
()
Ответ на: комментарий от static_lab

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

FishHook
()
Ответ на: комментарий от FishHook

ведь ТСу пришлось смотреть в код маппера, чтобы понять, что там есть сайд-эффект

Зачем? Из названия метода alwaysApplyingWhenNonNull() уже понятно, что маппинг отработает при ненулевом значении. А если не очень понятно, то есть документация, где написано: «Return a new PropertyMapper instance that applies whenNonNull to every source». В свою очередь, whenNonNull описывается как «Return a filtered version of the source that won’t map non-null values or suppliers that throw a NullPointerException». Да и нельзя назвать подобное поведение «сайд-эффектом».

static_lab ★★★★★
()

PropertyMapper

Я в спринге не шарю, но то что сверху очевидно более понятно - читаются настройки, какие не нуль, а потом устанавливаются.

А у тебя какая-то херабора нарисована: нужен цикл, какой-то хз какой длинны.

setReadTimeout(settings.readTimeout());

Это вообще рофл, как мне догадаться что ты нам передаёшь в статический метод, int, short, long, double. А что принимается, там переполнения не случится?

Короче не видя то что сверху, то что ты написал я точно не понял бы. А чтобы это было понятно, ты напишешь раза в три больше кода.

Ygor ★★★★★
()
Ответ на: комментарий от masterOf

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

peregrine ★★★★★
()

Технически этот вариант лучше чем второй. В поддержке, обобщении итд.

Проблема, конечно, в том, что в Java нет возможностей для синтаксической абстракции, т.к. это говно с принципами из 70х.

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

lovesan ★★★
()
Ответ на: комментарий от lovesan

Технически этот вариант лучше чем второй

Борьба была равна — сражались два жабоговна. Но в первом надо ещё и разучивать очередной неповторимый и уникальный интерфейс очередного неповторимого и уникального PropertyMapper.

в Java нет возможностей для синтаксической абстракции

На кой они тут нужны-то — достать из мапы два ключа и передать их на вход двум функциям? Ну я понемаю, жаберы — у них отсутствие в коде абстрактной фабрики синглтонов — это ай-яй-яй и code smell.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)