Стиль и удобочитаемость bash скриптов
Удобочитаемость
Код пишется один раз, а читать придется много раз ⇒ удобочитаемость имеет огромное значение.
- Не старайся быть “умным”, старайся быть ясным
- Только понятные и говорящие имена переменных, избегай абстрактных и общих понятий
- Справка (по -h/—help) в скриптах нужна
- Юзай source, а не ”.”, ибо точку сложнее найти
- По возможности юзай даты в формате ISO-8601 (Полный синтаксис:
2011-08-12T20:17:46.384Z
). Это международный формат. - Упорядочивай элементы списков: например, IP-адреса, имена хостов, пакеты для установки, операторы case, содержимое переменных или массивов/списков. Это упростит добавление/удаление элементов.
- Юзай длинные ключи команд (
diff --quiet
вместоdiff -q
) - такой код понятнее даже без комментов. Документируй свой выбор: почему взят именно этот ключ и даже почему не подходят другие ключи. Если у команды нет длинных ключей - поясняй комментами короткие. Документируй проблемные ключи, которые часто тянет заюзать.
Соус: Книга “Идиомы Bash” ⇒ Глава 11. “Разработка своего руководства по стилю” ⇒ “Удобочитаемость”
Комменты
- Комменты пиши с заглавной буквы и юзай пунктуацию только если комментарий не состоит из нескольких предложений.
- Юзай заголовки к командам (да и вообще ко всему).
- Комменты должны объяснять: ПОЧЕМУ что-то делается/не делается, а не “ЧТО делается”, ибо если ты и так пишешь понятный код - такие простые комменты ни к чему. Исключение - непонятные не знакомым с bash идиомы (здесь стоит объяснить, что делает идиома). Хорошо, когда комменты поясняют, почему ты поступил именно так и каковы твои намерения.
- Комментируй ключи
Логические блоки кода полезно выделять разделителями. Но добавлять рамки снизу и справа НЕ НАДО - потом будет дрочь обновлять содержимое внутри рамки, сдвигая рамки снизу и справа…🤢. Делай такие рамки:
Соус: Книга “Идиомы Bash” ⇒ Глава 11. “Разработка своего руководства по стилю” ⇒ “Комментарии”
Имена
Повторятся про говорящие имена не буду.
- Имена глобальных переменных и констант пиши ЗАГЛАВНЫМИ буквами, другие переменные - строчными.
- Старайся не изменять глобальные переменные, если это возможно (хотя иногда это упрощает код (KISS))
- Объявляй константы с помощью
readonly
илиdeclare -r
- Имена функций Смешанным_Регистром
- Не юзай ВерблюжийРегистр
- Не юзай дефис (-) в именах переменных
- Не сокращай имена
- Минимально юзай массивы bash - сложно читаются. Проще всего юзать
for var in $regular_var
- Вместо directly использования позиционных параметров ($1, $2…) присваивай их значения в начале переменным с говорящими именами.
- Различай типы ссылок:
$input_file
и$input_dir
- Юзай метки FIXME и TODO (с именами и номерами заявок, если это уместно).
Соус: Книга “Идиомы Bash” ⇒ Глава 11. “Разработка своего руководства по стилю” ⇒ “Имена”
Функции
- Юзай заголовки к функциям, представляющие их
- Функции определяются ДО их использования
- Функции лучше группировать в начале скрипта и отделять друг от друга w/ 2 blank lines.
- Не размещай между функциями иной код
- Юзай
function Some_Func
вместоSome_Func ()
, ибо первый вариант понятнее и его проще найти потом - Each функция должна содержать комменты, поясняющие:
- Что она делает
- Какие данные принимает (включая глобальные)
- Какие данные выводит/возвращает
- Повторяющиеся блоки кода оборачивай в функции, а те, которые востребованы в других скриптах (например, логирование, отправка почты) - в библиотеку-файл, чтобы потом
source
-ить их в других скриптах.- Пиши имена “библиотечных” функций с одинаковым префиксом (например, подчеркивание (_) -
_Log
)
- Пиши имена “библиотечных” функций с одинаковым префиксом (например, подчеркивание (_) -
- Юзай
local
переменные, если нет нужны в глобальных. Имей в виду, чтоlocal
переменные маскируют неудачный код возврата, поэтому объявляй и инициализируй их в отдельных строках, используя подстановку команд. Например, сначалаlocal var
и уже потомvar="$(some_cmd)"
- Длинные функции с кодом больше 25 строк закрывай комментарием
} # Конец фунции Some_Func
, чтобы легче было находить конец функции. Да и для коротких функций такие комменты не будут лишними. - В большинстве случаев функция main не нужна. Это имеет смысл в Python/C, где код может использоваться (также) в качестве библиотеки, + такая функция нужна для модульного тестирования
- Отделяй основной код от блока с функциями w/ 2 blank lines и разделительным комментом, особенно если функций много.
- Сделай в своей библиотеке функцию для логирования (например, _Log), чтобы, как минимум, унифицировать ее использование во всех скриптах. В идеале, лучше юзать логирование в syslog (особенно в “системных” скриптах), чтобы позволить ОС самой разобраться, куда логировать и т.п.
Можешь юзать заполнители в функциях, по типу:
Похоже на:
Соус: Книга “Идиомы Bash” ⇒ Глава 11. “Разработка своего руководства по стилю” ⇒ “Функции”
Кавычки
- Бери в кавычки переменные и строки, чтобы явно пояснять свои намерения/мотивы (только если эти кавычки не загромождают код).
- Бери в кавычки подстановку команд
- Бери в кавычки обе части выражения любого оператора проверки, например
[[ "$foo" == 'bar' ]]
. Исключения:- Целое число
- Если используется ~=, потому что RegEx нельзя брать в кавычки
- Бери в одинарные кавычки переменные внутри строк, чтобы легче было найти их:
echo "some '$text' w/ othuh shit"
. Но лучше, по мне, брать в[ ]
:echo "some [$text] w/ othuh shit"
. Так получишь ошибку, если переменная была undefined. - Юзай одинарные кавычки, если не нужна интерполяция
- Юзай одинарные кавычки в printf
- Не бери в кавычки целые числа
- Не юзай без необходимости ${var} конструкцию
Соус: Книга “Идиомы Bash” ⇒ Глава 11. “Разработка своего руководства по стилю” ⇒ “Кавычки”
Форматирование
- Не забудь про отступы, хоть они и не имеют значения в bash
- Не оставляй пробелов в конце строк. Для git, к примеру, это вызовет лишний шум.
- Длинные строки переноси на 78-м знаке (включая пробелы) и в next строке - отступ на два пробела.
- Разрывай строки ПЕРЕД символом | или >, чтобы в начале строк они были заметны
- Код, открывающий блок, пиши в одну строку:
if expr; then ...
orfor expr; do ...
- В case однострочные элементы закрывай символами
;;
в той же строке. Выравнивай отступы по)
в каждом элементе (если это не загромождает код).
Соус: Книга “Идиомы Bash” ⇒ Глава 11. “Разработка своего руководства по стилю” ⇒ “Форматирование”
Синтаксис
- Всегда юзай
$@
, только если не уверен, что тебе реально нужен$*
- Для проверки равенства юзай
==
вместо=
, чтобы не путать с присваиванием. - Юзай
[[
вместо[
, если только не нужен[
для переносимости (например, в bash). - Для integer арифметики юзай
(( ))
и$(( ))
, а неlet
иexpr
- Избегай
IFS=$'\n\t'
Соус: Книга “Идиомы Bash” ⇒ Глава 11. “Разработка своего руководства по стилю” ⇒ “Синтаксис”