Я люблю делать тексты ошибок понятными, читаемыми, информативными и стилистически красивыми.
База:
- заключать все подстаноуки в кавычки
- использовать двойные кавычки, вместо одинарных
- дочитать до конца и увидеть последний пункт
В далеком 2020 году я создал PR в Doctrine, но его морозили, и я не интересовался пинанием его дальше.
С того момента Doctrine изменилась сильно, но узнать плохое написание текстов с ошибками можно по первому байту. Сейчас всё расскажу.
Представим строчку:
"Invalid literal '" . $literal . "'"
Такая строчка выглядит как минимум грязно, а как максимум избыточно.
Если строка заключена в двойные кавычки, то вы сможете делать интерполяцию переменных внутри этой строки без надобности конкатенации.
Например, это могло бы выглядеть так:
"Invalid literal '$literal'"
Чуть более явный вид будет такой:
"Invalid literal '{$literal}'"
Более явный – потому что фигурными скобками я подчеркиваю намерение сделать интерполяцию, а не написать
$literal просто как текст, исключая возможность перепутать свои намерения.Следующий уровень мастерства (ирония) – вовсе не писать кавычки в подставляемые значения:
'Invalid parameter: token ' . $key . ' is not defined in the query.'
В итоге, когда получите ошибку при
$key = " "
Invalid parameter: token is not defined in the query.
И HTML склеит 2 пробела в 1, текст будет очень полезным и вспомогательным. Найти такие ошибки в исходниках бывает очень сложно, хоть здесь всего лишь 1 подстаноука.
Даже когда вы получите ошибку при
$key = "function"
Invalid parameter: token function is not defined in the query.
То сможете запомнить, что подстановки в данной библиотеке происходят без кавычек вовсе.
Так вот, когда вы получите первую ошибку где-нибудь на веб странице и она будет выглядеть так:
Invalid literal '5'
После того и будете думать, что
'5' – это значение подстановки.То есть, в переменной типа
string лежат 3 символа: кавычка, число, кавычка.Искать такое значения у себя по коду или алгоритмам, которые могли бы выдать такое значение сложно. Тем более, если они такого не делают.
Если открыть исходники и увидеть способ формирования строки ошибки:
"Invalid literal '" . $literal . "'"
Можно предположить, что
$literal = "5" или $literal = 5. Уже лучше, но порой бывает нужным еще и тип переменной вывести.Я уже много лет предпочитаю другой способ записи ошибок/интерполяции строк – через
sprintf:
sprintf('Invalid literal "%s".', $literal)
Этот вариант позволяет мне делать всё что захочу с текстом ошибки: кавычки, переносы строк, вложенные интерполяции, удобный поиск таких строк.
Я не теряю контекст текста ошибки, когда читаю или пишу его. Я могу писать
$ в тексте и не думать про интерполяцию.Когда текст ошибки простой – я позволяю себе делать простую конкатенацию
'An error occurred: ' . $error
Почему я считаю такое позволительным:
- не нужна интерполяция в конце, потому что дальше подстановки ничего нет – ни кавычек, ни точки, ни продолжения текста
- текст ошибки явно отделяет себя от подставляемого значения через символ двоеточия
- благодаря такому разделению можно не писать кавычки
Хоть текст
'An error occurred: %s' был бы полезнее при учетом интернационализации (i18n) приложения, без i18n такое использование вполне элегантное.Кстати, Intellij IDEA позволяет превратить строку с конкатенацией в строку с
sprintf за пару кликов при помощи интентов: - Option + Enter – нажать комбинацию клавиш на строке
- "spr" – для удобной фильтрации выдаваемых интентов
- Convert string interpolation to a
sprintf call – название нужного нам интентаПотом расскажу про интерполяцию в Kotlin, куда без этого.
Как вы относитесь к подстановкам через
sprintf vs string interpolation?---
PR: https://github.com/doctrine/orm/pull/8212
Doctrine/QueryException: https://github.com/doctrine/orm/blob/3.4.x/src/Query/QueryException.php#L80
---
@handle_topic