Ключевое слово «var» в Java: пожалуйста, только не это

в 10:39, , рубрики: java, Программирование, Проектирование и рефакторинг

Ключевое слово var

Прошедшее 8-е марта для разработчиков Java выдалось особенно насыщенным. Причиной тому послужил новый JEP 286: Local-Variable Type Inference, который предлагает ввести ключевое слово var, избавляя нас от необходимости явно указывать тип локальной переменной:

var unbufOut = NetUtils.getOutputStream(sock);

вместо

OutputStream unbufOut = NetUtils.getOutputStream(sock);

А на днях подоспели и результаты опроса разработчиков, которые недвусмысленно показали — var в Java быть. Хорошо это или плохо?

Судя по лентам Твиттера и результатам опроса, первая реакция многих разработчиков (включая меня) была такой:

No god please no

Я решил разобраться, почему этот JEP вызывает у меня отторжение.

Почему «нет»

Java всегда была и остается достаточно консервативной платформой. Иногда этот консерватизм реально ограничивает пользователей. Нашумевшая история с выпиливанием Unsafe, проникновение которого во многом есть результат игнорирования нарастающей потребности в низкоуровневом API, — ярчайший тому пример.

Консервативность языка, напротив, давала Java ряд преимуществ. Во-первых, это низкий порог вхождения. Базовый синтаксис языка очень компактен, и прост в изучении. Во-вторых, это экспрессивность. Языки, напичканные всевозможными фишечками, вроде Scala и C#, позволяют писать совершенно нечитаемые конструкции. Смешайте лямбды, type inference и имплицитный return, и читателям вашего кода придется хорошенько напрячься. В Java написать нечитаемый код значительно сложнее.

Отсюда и главная претензия к var — риск снижения читабельности. На практике мы «понимаем» код во многом благодаря трем составляющим: типы переменных, имена переменных, и имена методов. Повсеместное (а в худшем случае — бездумное) использование var, уничтожит первую из них. Для поддержания читабельности на том же уровне, придется больше внимания уделять именам методов, так как их вклад в восприятие кода значительно возрастет.

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

Люди пишут в опроснике:

Scope is small, so will only give more confussion to new developers. The typing of the boiler plate is tackled by decent IDEs.

We have IDEs so I don't care

В комплексе все это делает преимущества type inference достаточно сомнительными.

Особенно непросто придется любителям разработки «в блокноте». Существует мнение, что данный аргумент высосан из пальца, так как все пользуются IDE, а условный «notepad» — это удел фриков, неадекватных работодателей и джуниоров, пишущих свой первый «Hello, world!». Это не совсем так. IDE — это инструмент работы с кодом. Но сам код находится в других местах: в файлах, в mail-листах, в баг-трекерах, на форумах, и так далее. Когда вы открываете JIRA-тикет с куском кода, Вы сначала читаете его в браузере, верно? Поэтому чтение кода вне среды разработки — совершенно нормальная и распространенная практика, которой занимаются едва ли не все разработчики. Есть вполне обоснованные опасения, что var этот процесс затруднит.

I'm not sure if it will not increase the difficulty of code review

I code both in Java and C# and sometimes and need to work with C# code where people have used var. It makes it a lot harder to see the type of a variable for no or very little gain.

Почему «да»

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

Для аналогии вспомним ООП. При правильном использовании это невероятно полезный и мощный инструмент. Поэтому ООП везде. При этом код инженера, который только-только закончил читать Gang Of Four, лучше обходить стороной. Он будет чрезмерно сложным и перегруженным. И только через некоторое время, после того, как человек набьет руку в проектировании, ООП начинает давать свои плоды.

С развитием языка ситуация ровно та же. Появляется новый инструмент. Какое-то время люди учатся, притираются, делают ошибки. Появляются новые тренды и подходы, которые находят своих сторонников и противников. Наконец, образуются устоявшиеся практики, которые применяют в конкретных проектах.

Поэтому до начала массового использования var, достаточно сложно сказать, насколько много проблем и неудобств оно принесет. Но мы можем обратиться к языкам, которые уже имеют type inference — C++, C#, Scala… давайте иначе — а в каком известном вам мейнстримовом языке этого нет? Лично у меня нет информации о том, чтобы какой-то язык серьезно пострадал от type inference. Кто-то пользуется, а кто-то нет, кому-то нравится, а кому-то нет, вот и все.

Ради эксперимента я походил по кодовой базе Akkа и Spark. Намеренно искал места, в которых было бы сложно разобраться конкретно из-за type inference. Субъективно — не нашел. В подавляющем большинстве мест смысл переменной был легко понятен из контекста благодаря именам переменных и методов. По моим ощущениям, хороший код не пострадает. А вот плохой код может стать еще хуже. Ну и бог с ним.

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

Мне всегда было достаточно сложно понять мотивацию больших и сложных проектов, использующих JVM-based языки. Например, что получили Akka и Spark от использования Scala? Издержки очевидны — дополнительный барьер между продуктом и миллионами Java-разработчиков. А польза? Добавление новых фич, начиная с такой важнейшей вещи, как лямбды, и заканчивая относительно бесполезным var, позволит прекратить разброд и шатания, и вновь сконцентрирует комьюнити вокруг непосредственно Java. Это безусловный плюс.

Thanks so much! This will remove yet another death-by-a-thousand-cuts issues w Java that drive people to seek alternatives

Please simplifiy the Java language (and JavaEE in general)! Type inference is a great step into the right direction.

Итог

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

Is there way to add union and intersection types in Java?

Could you consider the introduction of case classes (like in Scala)?

when do you expect primitive types be allowed in generics?

Remove getters and setters.

When will we have async/await feature in Java ( like c# and f# ) ?

Но лично я пользоваться var не хочу. Блокнот сподручнее.

Автор: devozerov

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js