О коде
2018-06-30
Мы — программисты. Мы пишем код.
Мы — девопсы. Или сисадмины. Или инженеры по инфраструктуре. Мы пишем конфиги.
Существует множество правил и техник как правильно писать код. От паттернов до SOLID. В общем, всё сводится к тому, чтобы избегать дублирования кода, переиспользовать код, делать код таким, чтобы его можно было переиспользовать без изменения самого кода.
В результате, хорошо написанный код гибко настраивается, чтобы его можно было применить в большем количестве случаев. А параметры настройки часто пишутся в файлах конфигурации, конфигах.
Если нужно ещё больше гибкости, то встраивают какой-нибудь язык программирования. Часто интерпретируемый. (Привет, JavaScript. Привет, Lua.) И, помимо основного кода, у нас появляются скрипты.
Например, игры. Со времён Quake (и даже раньше) у любой серьёзной игры есть движок. Это — код, написанный программистами. И ресурсы. Это — конфигурация, написанная гейм-дизайнерами. Со своими скриптами на QuakeC. И именно ресурсы делают игру игрой. Движок лишь предоставляет техническую возможность.
Где проходит граница между кодом и конфигом?
Если мы сделали классный и расширяемый код, не пора ли сделать классные, удобные и расширяемые конфиги к нему?
Есть ли паттерны и SOLID для конфигов?
Очевидно, есть. Только никто ещё не написал про это книжку. Возможно, потому, что не существует конфигов «общего назначения».
Посмотрите,
как организована конфигурация
того же Nginx
в Debian-based дистрибутивах.
В каталоге /etc/nginx/sites-available
,
в отдельных файлах,
имеются конфигурации виртуальных хостов.
Чтобы включить виртуальный хост,
нужно создать симлинк
в каталог /etc/nginx/sites-enabled
.
Чтобы выключить,
нужно убрать симлинк.
Чтобы добавить новый виртуальный хост,
достаточно добавить новый файл,
и сказать Nginx перечитать конфиги.
Не нужно править уже существующие конфиги.
Имхо,
это вполне очевидное следование заветам SOLID.
Причём
со стороны самого Nginx
тут нет ничего сверхъестественного.
Он читает лишь один файл
/etc/nginx/nginx.conf
.
Но в этом файле имеется несколько директив
include
.
«include» является точкой расширения
конфига.
И позволяет применять паттерны.
Как те,
которые приняты в Debian.
А Ansible? Изначальная идея очень проста. Есть модули, которые делают что-то полезное. Которые написаны на настоящем языке программирования Python. И которые могут переиспользоваться. Мы пишем последовательность вызова модулей, с соответствующими параметрами. То, что в Ansible называется task. Пишем в YAML файле. То есть пишем конфиг.
Но мы тоже хотим переиспользовать и расширять эти YAML файлы. И есть много способов в Ansible для этого. Можно переопределить переменные (а переменные могут влиять на поведение). Повторяющиеся наборы задач выделяют в роли, которые можно распространять и переиспользовать. Наборы хостов, на которые можно применить эти роли, образуют inventory. Ну и инклюды тоже никто не отменял.
Кстати, о переменных. Переменные окружения — неотъемлемая особенность процессов Unix. И они, нежиданно, снова в ходу для этих наших контейнеров. Казалось бы, каким образом можно огранизовать набор ключей и значений? Но и тут у нас есть наследование и возможность переопределить.
А Terraform? Хоть тут вовсе не императивный, а вполне себе декларативный язык, о расширении и переиспользовании разработчики позаботились.
Снова переменные, которые можно задать и переопределить кучей разных способов. Переиспользуемые модули. Публичные репозитории готовых модулей. Workspaces, чтобы добавить ещё одно измерение, где этот код может быть переиспользован.
Что бы ни считали разработчики, что с момента написания достаточно SOLIDного кода, когда все мыслимые настройки вынесены в файлы конфигурации, и их работа закончена, на самом деле потом начинается программирование конфигов. Программирование на XML (о, да, XSLT), на YAML, на HCL. (Только не на JSON, пожалуйста. Потому что в JSON нет комментариев.)
Конфиги — тоже код. Рано или поздно, так или иначе. И нужно предусмотреть способы расширения. И предложить шаблоны использования. Раз уж сами по себе языки разметки ничего подобного не умеют.