Как стать автором
Обновить

Комментарии 28

Хорошие бюджеты в  Naumen Service Management Platform. У Ситибанка переход на следующую версию Java занимает по пять лет по причине отстутствия денег на оплату работы программистов вне беклога.

А зачем переходить, если все и так работает?

Если кратко, то: первое — наши хорошо отлаженные процессы позволяют проводить подобные обновления, второе — как отметил в статье, каждое обновление приносит с собой и улучшение языка, и повышение безопасности и перформанса продукта из коробки. 

В финальной части доклада на ютубе более подробно рассказал, почему полезно обновление. 

позволяют проводить подобные обновления

Любая движуха, которая повышает квалификацию сотрудников без форс мажора для основной деятельности компании, это очень здорово. Поэтому подобного аргумента вполне достаточно :-)

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

Тут еще такой момент, что становится тяжело искать желающих работать в откровенно легасевом проекте. Лично я тупо не хочу идти в "молодой и динамично развивающийся продукт" на java 8. Я в своей карьере пережил много миграций: с 8 на 11, с 11 на 17, с 17 на 21, со Spring Boot 2 на 3. И еще с AngularJS на Angular9. Это выматывает. Приходить на java 8 и повторять этот квест нет желания. А пользоваться адекватными фичами инструмента все равно хочется.

Кстати, в моем текущем проекте переход с 19 на 21 и на второй компилятор Kotlin прошел на удивление быстро и спокойно за 1 спринт. Но это потому, что у нас зависимостей минимум.

Так что респект, что находите силы и время на это.

А расскажите про опыт перехода на котлин 2, если там есть что-то интересное конечно

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

Тот самый последный дремучий микросервис который не меняется 8 лет, можно на 7-ой яве оставить. Фиг с ним

Все что было после релиза java 8 - косметика

Вот да, переход на 8 был эпичным, а на 11-ю уже детсад по сути

Честно говоря, я уже от восьмерки плакал. Чтобы так откровенно начать убивать язык - это надо постараться. Все молятся на "Чистый код" Мартина, но требования второй главы в 8 нарушены чуть более чем полностью.

Что, кстати, проявляется и в этой статье - по мнению автора код под 21 читать проще и приятнее, а по мне это трэш и содомия. Полное несоответствие исходной семантике языка. Это даже не речь мастера Йоды, это хаотично добавленные слова, которые ты знаешь, но смысл всего предложения от тебя ускользает. Смотришь и не понимаешь, приходится прилагать усилия для перевода, несмотря на использование языка с 1996 года.

А код под 17 читать сложно не потому, что это 17, а потому что руки надо оторвать тому, кто его так отформатировал. В норме этот код читается намного проще:

public Double convert(Object value){
    if (null == value){
        return null;
    }
    if (value instanceof Double){
        return (Double)value;
    }
    if (value instanceof String){
	    String sValue = (String) value;
		return (sValue.trim.isEmpty()) ? null : Double.parseDouble(sValue)
    }
	if (value instanceof Number){
        return ((Number)value).doubleValue();
    }
    throw new AdvImportException("Can't convert value " + value + " to double");
}

Так более того, в 17 джаве можно избавиться от явного каста после instanceof с объявлением переменной

Честно говоря, я уже от восьмерки плакал. Чтобы так откровенно начать убивать язык - это надо постараться. Все молятся на "Чистый код" Мартина, но требования второй главы в 8 нарушены чуть более чем полностью.

Не могли бы уточнить к каким изменениям у Вас такие претензии?

Судя по

использование языка с 1996 года

основная претензия в том, что "раньше трава была зеленее".

Лямбды. Анонимные функции. Всё, что привело к потере именования кода. Вторая глава "Чистого кода" - она про именование. Если коротко - "именуйте всё, что можно именовать". Когда в метод передается функция двух целых параметров - ты принципиально не можешь сделать предположение о том, что она делает. Это надо целенаправленно разбираться. Если передается Comparator<Integer> - разбираться не надо, тут всё очевидно. Разница в том, что во втором случае надо написать целых лишних несколько слов:

new Comparator<Integer>{
    public int compare(Integer i1, Integer i2){
        // код функции
    }
}

Аж 8 штук. Один раз. Это такая затрата времени! Быстрее написать (i1, i2) -> // код функции

А о том, сколько лишнего времени уходит на разбор при поддержке этого кода - никто не думает. И SLA на поставку патча в течение двух часов со штрафом в 2млн тоже мало кто встречал.

И SLA на поставку патча в течение двух часов со штрафом в 2млн тоже мало кто встречал.

У вас ПТСР? Я правильно понял, что вся индустрия должна отказаться от ФП потому, что конкретный человек в конкретной организации с конкретным SLA не осилил синтаксис лямбд?

Назначение лямбды обычно очевидно из её кода и из имени функции, в которую она передаётся

Поддерживаю. @skipy, а тем, кому это неочевидно, могут просто сначала объявить переменную нужного типа.

Comparator<Integer> integerComparator = Integer::compareTo;

В Java 17 можно и так:

public Double convert(Object value) {
    if (null == value) {
        return null;
    } else if (value instanceof Double v) {
        return v;
    } else if (value instanceof String v) {
        return (v.trim().isEmpty()) ? null : Double.parseDouble(v);
    } else if (value instanceof Number v) {
        return v.doubleValue();
    }
    throw new AdvImportException("Can't convert value " + value + " to double");
}

А вариант Java 21 просто делает код более выразительным выделяя паттерны из кучи if в один switch:

public Double convert(Object value) {
    return switch (value) {
        case null -> null;
        case Double v -> v;
        case String v -> v.trim().isBlank() ? null : Double.parseDouble(v);
        case Number v -> v.doubleValue();
        default -> throw new IllegalArgumentException("Can't convert value" + value + " to double");
    };
}

Не понимаю почему второй вариант это прямо " хаотично добавленные слова, которые ты знаешь, но смысл всего предложения от тебя ускользает" - смысл тут ровно тот же что и в первом варианте и switch с case и раньше были - просто теперь внутри case разрешено ставить не только константу, но и "паттерн" (фактически "условие").

просто теперь внутри case разрешено ставить не только константу, но и "паттерн" (фактически "условие")

Тут не просто условие. Тут во-первых, совершенно неочевидный instanceof. В case всегда стояло значение того, что указано в switch, это важно. А тут неявно проверяется тип. Напишите value.class - и такой case будет интуитивно понятен.

Пусть у вас value типа Class. А передается туда Class<Number>. И есть два case - case Class и case Number. По типу (неявный instanceof) это Class, по значению Number. Какой case сработает? У вас приблизительно полсекунды на понимание. Дальше это уже "запнулся и потерял скорость восприятия".

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

Императивные языки - они более-менее одинаковые по выразительности. Я могу читать код на C#, С++, питоне, Го и еще много чем. Это не вызывает сложностей, это как диалекты одного языка, слова чуть разные, но правила построения фраз совпадают. А тут нарушены именно правила построения. Не получается читать логику, надо читать синтаксис. Отдельные слова.

"А тут неявно проверяется тип" - вполне себе явно, синтаксис другой, неоднозначностей нет.

У вас приблизительно полсекунды на понимание

Специально сложно сконструированный кейс, где мы разбираем и Class, и Number. С if-ми где делается instanceof вы ещё больше запнетесь

неочевидная связь этой переменной с тем, что стоит в switch

Точно также и с локальными переменными в принципе. Чтобы понять как она связана с текущим контекстом, надо смотреть где и как она объявлена

Все молятся на "Чистый код" Мартина, но требования второй главы в 8 нарушены чуть более чем полностью

Ну вот кто такие заявления делает - тот, видимо, и молится. Адекватные люди понимают, что "Чистый код" - не заповеди на скрижалях, а просто набор советов. Даже если дизайн джавы действительно что-то там нарушает, то Оракл имеет на это полное право.

Эти "советы" написаны кровью. Не успел за два часа разобраться в чужом коде, найти ошибку, исправить, протестировать, собрать патч и поставить заказчику - получил штраф в 2 млн. Работали в таких условиях? Я работал. Там нет времени на понимание очередного синтаксического сахара ради экономии двух слов в месяц. Кстати, у нас лямбды были запрещены.

А Oracle на всё имеет право. В том числе и на снижение использования языка. Что мы и наблюдаем по индексу TIOBE. С 2020 на первое место Java не поднялся ни разу, за всю историю индекса такого не было.

Работали в таких условиях? Я работал

Напомнило логику "Я служил! А ты служил?".

С 2020 на первое место Java не поднялся ни разу, за всю историю индекса такого не было

The index is calculated from the number of search engine results for queries containing the name of the language

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

Эти "советы' написаны теми, кому надо было продавать книгу

у нас лямбды были запрещены

Интересно, а кто принял такое решение?

В общем противоречивые эмоции. С одной стороны хочется конечно 100% совместимости. Чтобы вот обновляешь версию Ява машины и все работает бесшовно. Это было раньше и я не скажу, что развитие Явы в те времена меня устраивало.

Сейчас да есть несовместимости если "вы делаете странное" (давайте называть вещи своими именами).Но вроде фиксится не очень ужасно, за Яву скорее рад чем наоборот.

Все же развития языка для меня важнее, чем совместимость сломанная на private static reflection.

Кажется, что код, написанный на Java 21 не эквивалентен коду на старой версии

в старой версии есть обработка исключения при вызове parseDouble

try {
    return Double.parseDouble(stringValue);
} catch (NumberFormatException e) {
    throw new AdvImportException("Cannot convert value '" + stringValue + "' to Double", e);
}

в отрефакторенной версии этого нет

case String stringValue -> Double.parseDouble(stringValue);

Да, верно, изначально в коде этой строки не было, видимо, при публикации что-то слетело. Спасибо за внимательность, поправили!

Зарегистрируйтесь на Хабре, чтобы оставить комментарий