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

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

Ситуация со string templates напоминает анекдот, где унитаз на потолок приделали. Плохо сделали, Вася, надо переделать

$-синтаксис объективно хуже

По мне лучше как то явно обозначить темплейт, чем определять это по \{} в строке. Тогда имхо и ${} можно было бы использовать не ломая совместимость с существующим кодом. Что то вроде _"Hello ${name}", для получения результата STR._"Hello ${name}". Я при переключении с java на typescript до сих пор часто ошибаюсь на стрелочных функциях. Потом буду еще на этих темплейтах ошибаться. Причем тут даже ошибку и компайлер не поймает. Если вместо \{} напишу ${}. Если я правильно понял это

System.out.println(“Hello \{name}”);

В этом примере строковый темплейт является объектом класса StringTemplate, а не String (отсутствует неявная интерполяция), и выбирается перегрузка println для StringTemplate


Причем тут даже ошибку и компайлер не поймает. Если вместо {} напишу ${}

В TS поймает?

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

И пользователи могут вызывать это так:
String s = String.format(“Hello %12s{name}”);

Объясните, пожалуйста, в чём профит. Я вижу, что в шаблоне строки появляется нездоровая привязка к контексту (name), и теперь её нельзя куда-нибудь вынести (в базу, ресурсы и т.п.). В то время как традиционное форматирование — это точка, где сводятся абстрактный шаблон и конкретный контекст.

в чём профит

https://openjdk.org/jeps/459

Goals

  • Simplify the writing of Java programs by making it easy to express strings that include values computed at run time.

  • Enhance the readability of expressions that mix text and expressions, whether the text fits on a single source line (as with string literals) or spans several source lines (as with text blocks).

  • Improve the security of Java programs that compose strings from user-provided values and pass them to other systems (e.g., building queries for databases) by supporting validation and transformation of both the template and the values of its embedded expressions.

  • Retain flexibility by allowing Java libraries to define the formatting syntax used in string templates.

  • Simplify the use of APIs that accept strings written in non-Java languages (e.g., SQL, XML, and JSON).

  • Enable the creation of non-string values computed from literal text and embedded expressions without having to transit through an intermediate string representation.

Это же и в статье есть.

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

Что касается конкретно этой цитаты, в отдельных местах это какое-то натягивание совы на глобус.

Improve the security of Java programs that compose strings from user-provided values and pass them to other systems (e.g., building queries for databases) by supporting validation and transformation of both the template and the values of its embedded expressions.

Как же мы всю жизнь боролись без интерполяций с SQL-инъекциями? Ах да, у нас же для этого был функционал query-builder'а, который и занимался безопасностью с учётом предметной области. А теперь что? Снова выносить санитайзинг на уровень прикладного программиста?

А держать все литералы в коде — это, может быть, приемлемо для хелло-ворлдов, но не для промышленных программ, где все тексты потенциально локализуемые, их пишут и правят копирайтеры, а не кодеры

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

Ах да, у нас же для этого был функционал query-builder'а, который и занимался безопасностью с учётом предметной области.

Так они и хотят (ради этого и был сыр-бор с процессорами), чтобы можно было написать query-builder, но так, чтобы читался попроще.

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

А можно просто пример кода, где от интерполяции больше пользы, чем вреда? Заранее спасибо. Устроит на любом языке, т.к. пихают её всюду.

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

log.info("User "+user.getUsername()+" initiated operation: "+operation)
  vs
log.info("User ${user.getUsername()} initiated operation $operation")

Спасибо.

Во-первых, про конкатенацию речи вообще не идёт. За неё надо сразу гнать из профессии. Надо сравнивать форматирование и интерполяцию.

А, во-вторых, это как раз то, про что я написал. Тут предполагается, что логи нелокализуемые, ненастраиваемые из конфигов, ненастраиваемые VERBOSE'ом и т.д. Для курсовой, для пет-проекта, для прототипа это нормальные предположения, для промышленного софта — не очень.

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

Локализуемые логи - это что-то реально существующее? Я такого не встречал.

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

log.info(() -> "User ${user.getUsername()} initiated operation $operation")

Но разве это хуже вот этого:

log.info("User {} initiated operation {}", user.getUsername(), operation)

Локализуемые логи - это что-то реально существующее? Я такого не встречал.

Если продукт B2B (какая-нибудь СУБД, СКД, система управления производством или просто софтина, идущая в комплекте с промоборудованием) и поставляется в разные страны, локализация логов не будет особо отличаться от локализации остального, например, дашборда. С её помощью можно сегментировать рынки, чтобы купившие локальную версию со скидкой не могли её внедрить за пределами страны, чтобы впарить курсы, сертификацию и т.п. У продажников это называется «(к)анальная дисциплина».

Почему verbose не настраивается?

Мне кажется, это не очень правильно, когда в прикладном коде вообще есть какие-то признаки поддержки verbose. Например, надо что-то менять, когда мы добавляем verbose, или, наоборот, удаляем его. Думать об этом должен автор логгера, когда такое бизнес-требование появится (может, оно и не появится). А в прикладном коде надо просто отдать ему событие логгирования и все значения, которые имеют для него смысл. Заодно не будем проблем, когда (и если) понадобится конфигурирование, локализация и пр. Ну и вообще — гораздо ведь лучше, когда данные отделены от кода.

в данном случае все было довольно ясно - $-синтаксис объективно хуже

Совершенно непонятно, чем он хуже. Ну и в целом обороты вроде

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

Оставляют впечатление недосказанности

Как я понял, главная проблема с $-синтаксисом, что уже есть куча строк, где используются такие темплейты. Могут возникнуть неожиданные коллизии. Например, с темплейтами в Спринге.

Котлин же как-то справился с этим

Котлину проще. Там темплейты изначально. А исходники java просто перекомпилируют с новой версией.

Не совсем понял почему нельзя было сделать как GString в Groovy с неявным презованием строки шаблона в строку там где нет соответствующей перегрузки

В груви это приводит к огромному числу внезапностей и неожиданностей. Например, что будет если положить в HashMap в качестве ключа GString, а искать String?

В этом смысле явное точно лучше неявного.

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