Комментарии 101
Шутка про n-стандартов…
ИМХО, когда конфиг становится сложнее, чем можно описать в ini файле - что-то пошло не так. И этот конфиг уже перестает быть человекочитаемым и лучше уже иметь какой-то гуй.
В дополнение, крайние несколько лет являюсь адептом секты "config-less", когда все что нужно сконфигурировать - должно иметь cli/env ручки для этого, и знаете - этот подход более чем жизнеспособен! И строгие правила, и валидация, и генерация документации из этого кода - прям хорошо. Да что уж говорить - великий и могучий Traefik и тот умеет себя конфигурировать флагами без сильной боли ниже поясницы (если понимаешь что делаешь), а он тот еще комбаин.
На моем опыте в бизнесовых приложениях не удается обойтись простецким конфигом, который можно было бы удобно описать в ini
Во всех проектах всегда были фреймворки, которые из коробки давали модульность + слияние конфигов - и это прям надо реально. И даже для go приложений такое надо, потому как на нем мы тоже бизнесовый код пишем - сейчас мы мерджим yml
Понимаю проблему сложных конфигов, поэтому пытался найти баланс - добавил ключевые фичи, без которых нереально жить в бизнесовых приложениях ИМХО
Постарался в общем не усложнять синтаксис и читабельность конфига
Проблема в том что "ещё один", как расширение существующих стандартов может быть и имеет место быть, но как самостоятельный продукт это выглядит как "убийца json" который применяют во многом из-за широкой поддержки и простого синтаксиса.
Абсолютно все это и многое другое было с NFX laconic конфигах. Очевидно вдохновлялись
Гуй V2RayN.exe улыбается и машет. Ну и почти всех остальных аналогов тоже.
Лучше S-выражений еще ничто человечество не придумало.
Придумало: https://page.hyoo.ru/#!=8i7ao7_xfyxah
Нет ничего более нелепого чем форматы в которых отступы определяют вложенность. В таких форматах даже копи паста нормально не работает, а все гладко и удобно только в голове у авторов.
копи паста нормально не работает,
Если редактор не тупо захватывает пробелы в начале и их вставляет, а понимает, что блок копирует и делает (де)индент по месту вставки - работает. Ну или умеет по TAB/Shift-TAB отступ выделения менять - тогда немного ручной работы есть.
Но да, в nano редактировать неудобно.
давайте выдумаем сложностей, а потом героически их преодолеем. Делать больше нечего, что ли?
Со скобочками точно такие же сложности, если редактор не имеет спец поведения для конкретного синтаксиса. Плюс появляются сложности с исправлением авто форматирования, когда в копируемом были не сбалансированные скобки.
Но скобочки не требуют правильного индентирования - это на одну проблему меньше чем с индентированием
Но скобочки не требуют правильного индентирования
Но используются для индентации приблизительно всегда. Потому что иначе человеку читать неудобно. Потому после копи-пасты все равно приходится переформатировать.
Единственное исключение - когда все в одну строку пишется, и открывающая/закрывающая скобка оказываются на одной строке.
Там есть ещё один интересный кейс: ямловые шаблоны, которые с чего-то стали очень популярны
Представьте: язык, в котором "yes" может быть либо строкой либо булом, со значимыми пробелами, используется для шаблонизации и встраивания других объектов. No fun писать специальный темплейт движок для такого.
В языках со скобками можно просто зашаблонировать куски и вставить их "как есть", и получить однозначный результат после прогона форматтера
авайте выдумаем сложностей, а потом героически их преодолеем.
Где сложности и героизм? Выделил кусок в Rectangle Mode Selection (которое лидирующие пробелы не захватывает), поставил курсор в нужное место, нажал 'вставить' - и он в точности в таком виде (таким же прямоугольником) и вставился. С точно таким же отступом, как был у того места, где курсор стоял.
Вы никогда скриптами конфиги не правили? Попробуйте yaml править…
Я их генерировал. И тут нужен генератор, который понимает, что он, собственно, правит, а не тупо 'как есть' вставляет. Т.е. если плейсхолдер с отступом - то все строки, во что он разворачивается, вставляется с этим отступом. Ну да, просто sed-ом не справишься, но не так чтобы уж очень сложно.
У yaml проблема не с отступами, а в том, что у него неестественного интеллекта и возможностей интерпретаций написанного больше чем надо.
Жаль, что Hocon не популярный, очень приятный формат/расширение json
Кругом убийцы форматов... https://habr.com/ru/articles/248147/
Модульность и слияние нужно реализовать не как фичу самих конфигов, а в том месте где они подключаются, после декодирования - и при этом вообще не зависеть от формата - вот куда усилия приложить надо, а не в изобретение json диалекта
Такое реализовать на самом деле не сложно - можно любой формат переложить в мапу, сделать это несколько раз для нескольких файлов и сделать мердж
Так и делают чаще всего
Но что не нравится в таком подходе:
- список файлов определяется в приложении - то есть без просмотра кода конфигурацию не прочесть
- без просмотра кода не понять, по каким правилам строится конфигурация - кто кого переопределяет и все такое
Ну и моя версия включает в себя некоторые другие фичи, которые таким образом не реализовать или можно реализовать, но с помощью костылей
Основная проблема всех "статичных" языков не в синтаксисе (хотя насчёт ямла можно поспорить), а в том, что в этих языках нет синтаксических конструкций для избежания копипасты.
HCL пытается с этим что-то делать, вводя модули, но не забывая вводить магические переменные для описания циклов — что, по мне, отвратительно, и начинает напоминать Ansible с его декларативными конструкциями, которые на практике оказываются просто нетипизируемым ямлом. Ямл тоже пытается избежать копипасты со своими anchors, и <<, но, опять же, на практике это превращается в просто месиво.
Итого, потребность в хорошем языке для конфигов действительно есть.
В статье отсутствует какое-либо сравнение с существующими языками, включая плюсы и минусы каждого из них. Понятно, что ATMC яыляется более "выразительным", и более абстрактным, нежели JSON, YAML etc. Поэтому также стоит сравнить с Pkl, dhall, CUE, jsonnet и другими.
По статье, не доконца понял
можно ли отрендерить/экспоритировать .atmc конфиг в другие форматы?
как сделать ключ с пробелом?
можно ли сделать циклы?
пофейлится ли конфиг с одинаковыми ключами или есть какое-то правило?
при рекурсивном мерже, мержатся ли списки или просто перезаписываются?
Ещё много вопросов можно задать, но думать лень
YAML как раз позволяет "копипастить" причем довольно гибко, можно указывать шаблон, а потом докидывать и перезаписывать конкретные параметры, это не Ansible-приколы а часть стандарта
вообще из опыта конфиг нужно строить универсальным:
хочешь пихай json
хочешь yml или что то вообще странное
хочешь запускай без конфига вообще
хочешь укажи всего пару через cli параметры
решать за клиента как ему лучше самая порочная практика. Автор статьи вообще создал уже существующее неоднократно, есть куча похожих json-подобных языков конфигурации
Итого, потребность в хорошем языке для конфигов действительно есть.
Есть необходимость различать язык конфигов и язык программирования. Как только потребовалось что-то вроде циклов - нужно брать полноценный существующий и им и пользоваться, урезав возможности для того чтобы убрать всякие уязвимости.
Еще препроцессором можно начать пользоваться и генерировать полный конфиг из кусочков. Но опять же не забывать, что превращать конфиг в полноценный скрипт - вредно для понимаемости.
но не забывая вводить магические переменные для описания циклов — что, по мне, отвратительно
Согласен - поэтому такого у меня не будет - это все-таки язык конфигурации, а не язык программирования
> можно ли отрендерить/экспоритировать .atmc конфиг в другие форматы?
Сейчас можно только в JSON - причем это ненастоящая компиляция в json - применен такой хак: компилим в мапу, а из мапы в json с помощью стандартного пакета - в будущем можно сделать нормальную компиляция, но пока и так сойдет - можем себе позволить так как скорость компиляции не имеет значения:)
Больше ни во что нельзя
В планах компилировать в самого себя - то есть выдать один конфиг с отрезолвленными значениями - думаю будет удобно дебажить, как это позволяет делать nginx -T
> как сделать ключ с пробелом?
Никак. А надо?
> можно ли сделать циклы?
Если это про циклические зависимости, то нет - детектится и выдается ошибка
> пофейлится ли конфиг с одинаковыми ключами или есть какое-то правило?
Нет, не пофейлится - можно переопределить значения - это не то чтобы фича - просто так работает - возможно стоит запретить, а то потом такую проблему фиг отыщешь
> при рекурсивном мерже, мержатся ли списки или просто перезаписываются?
Массивы перезаписываются - мердж не позволит переопределить значения в нем, так как ключей там нет, как в объектах
все-таки язык конфигурации, а не язык программирования
Встаём на тонкий лёд споров об определениях. Является ли ваш х... и ямловый <<: *a тем же самым, что и питоновское a | { ... }? Если да, то почему одно является язком программирования, а другое нет?
Язык программирования не обязательно должен быть развесистым как питон, даже простенький DSL может являтся ЯПом. Также, к счастью, перечисленные мной конкуренты (CUE, jsonnet, Pkl, dhall) не являются generic-purpose язками, и некоторые даже не являются turing complete.
Было бы интересно увидеть подробное сравнение вашего языка и перечисленных.
как сделать ключ с пробелом?
Никак. А надо?
Получается, что язык даже не является суперсетом JSON. Но если серьёзо отвечать на вопрос, то да, конечно надо.
можно ли сделать циклы?
Если это про циклические зависимости, то нет - детектится и выдается ошибка
Нет, речь про циклы, конечно, а-ля for item in ... или подобные способы избежать копипасты кода. Особенно полезно при модификации списков, учитывая что рекурсивный мерж просто обновит значение (что в целом логично, и правильно)
В целом свой язык конфигов прикольно, хорошее занятие.
От себя могу добавить (и там в треде выше уже упомянули), что при работе с огромным количеством конфигов действительно хочется иметь простой не-тьюринг полный язык для избежания дедупликации всего по нескольку раз, и для этого нужны абстракции в виде циклов, условий, и т.п. Но это субъективно конечно. Моё мнение в основном совпадает с этой статьёй https://ruudvanasseldonk.com/2025/abstraction-not-syntax.
Если да, то почему одно является язком программирования, а другое нет?
Ну смотря, что считать языком программирования - я считаю языком программирования тюринг полный язык - соответсвенно мой язык под эту категорию не подходит
> Было бы интересно увидеть подробное сравнение вашего языка и перечисленных.
Ага, как-нибудь распишу
> даже не является суперсетом JSON.
Почему это плохо?
> Но если серьёзо отвечать на вопрос, то да, конечно надо.
Кому и зачем это надо? Никогда не видел, чтобы пробелы в конфигурации использовались
Если действительно надо, хотелось бы пример какой-нибудь, где без этого не обойтись
А если для галочки, чтобы стать суперсетом JSON, то думаю можно обойтись без этого
> Нет, речь про циклы, конечно, а-ля for item in ... или подобные способы избежать копипасты кода. Особенно полезно при модификации списков, учитывая что рекурсивный мерж просто обновит значение (что в целом логично, и правильно)
Что-то мне, кажется, что это дикий оверхед, который нужен 1% разрабов/проектов
Такая сложная логика должна быть на уровне приложения, а не на уровне конфигурации
Не очень понимаю, какая конфигурация с массивом должна быть, чтобы аж циклы понадобились
Возможно мы в очень разных сферах работаем, поэтому мне эта тема не близка и я ее не понимаю
В целом идея сделать максимально простой язык, который закрывает 99% потребностей
А вот этот 1%, где циклы нужны или еще какая-то экзотика уж лучше не покрывать
А из статьи с примером копипасты и замены его на цикл, я предпочту копипасту - намного читабельнее и не позволит разрабам городить дичь, используя такие сложные конструкции
Ну и в довесок в ATMC можно обращаться к полям импортированного конфига
То есть значения, которые дублируются можно вынести отдельно и обращаться к ним, а не копировать - по итогу можно будет изменить значение в одном месте и поменяется везде
Ну в общем не понимаю я циклы эти в конфигах - они меня пугают
---
Перечитал свой ответ и вижу, что ни с чем особо не согласился по итогу - но хочу сказать, что в любом случае спасибо за фидбек - это очень полезно для меня - много нового узнал:)
Без проблем. Опять же, у меня свой юзкейс для кучи деплойментов на десятки серверов, с кучей зависимых друг от друга частей, у вас — свой.
Могу сказать что в проде у нас для конфигов используется смесь ямла и питона (ворклоады либо определены прямо в питоне, либо питон парсит ямл и выплёвывает объект ворклоада). Так можно валидировать всё и вся. Например, можно статически на этапе сборки и проверки конфигов построить файл-мап всех портов которые должны быть открыты публично или только во внутренней подсети. Питон в целом нормально, но немного геморно, в основном потому, что нужно слишком много дата процессинга писать чтобы сконверить один ворклоад в нужный формат. (У питона есть и другие проблемы, но мы их опустим)
Было бы неплохо для этого использовать какой-нибудь простенький язык, но мы решили остаться на питоне, потому что остальные куски инфры уже были на нём. Но в целом я думаю какой-нибудь CUE бы нам подошёл.
Удачи вам с вашим языком конфигов, посмотрим как будет развиваться
Прикольно
Возможно не стоит пытаться угодить всему и вся
Есть сложные случаи, как у вас и возможно для таких случаев нужен более мощный язык
То есть для каждого кейса свой инструмент
Универсального ничего не бывает и это норма
А если бывает, то это сложно - всегда жертвуем простотой :(
Если нужно что-то сложнее ямла не понимаю в чем проблема какой-нибудь луа использовать
Почему не писать конфиги на Typescript? Тут и импорты и экспрорты и типы для валидации, а потом это все компилировать в json? А если эти конфиги редактирует 3rd party, то напишите им компилятор в json или же https://github.com/laverdet/isolated-vm
Потому что это сделает конфигурацию абсолютно нечитабельной
Код не читаемый? Или скомпилированный код? Если хотите читаемость, конфига который вы достали откуда-то, то носите компилятор вместе с прилагой.
Просто компилятор вместо парсера. Там и комментарии и типы и много файловость, и чтение переменных окружения и fetch и все что пробросите.
https://json5.org , это не оно?
Как только встает вопрос про валидацию сложного конфига, то оказывается что кроме JSON c JSON Schema больше ничего и нету.
Да и у этого решения тоже есть проблема, object или array никак не прокинешь из переменных окружения.
Да и у этого решения тоже есть проблема, object или array никак не прокинешь из переменных окружения.
Интересная идея
Мне такое не пригождалось никогда, поэтому даже не задумывался о таком
Может есть примеры, где такой функционал хотелось бы иметь?
array - список реплик для чтения, список endpoint-ов для каких-то запросов, список доступных языков, список доступных валют. Обычно приходиться колхозить что-то типа DATABASE_REPLICA_1, DATABASE_REPLICA_2 и тд. и ваш конфиг типа такого
{
database: {
replicas: $DATABASE_REPLICA_*
}
}
что развернеться в
{
database: {
replicas: [$DATABASE_REPLICA_1, $DATABASE_REPLICA_2]
}
}
object - тут чуть сложнее с примерами, они более редкие, это может быть например конфигурация oauth провайдеров, и будет что-то типа OAUTH_GOOGLE_ID, OAAUTH_GOOGLE_SECRET, OAUTH_APPLE_ID, OAUTH_APPLE_SECRET и тд. и ваш конфиг типа такого
{
oauth: $OAAUTH_$
}
что развернеться в
{
oauth: {
google: {
id: $OAUTH_GOOGLE_ID,
secret: $OAAUTH_GOOGLE_SECRET
},
apple: {
id: $OAUTH_APPLE_ID,
secret: $OAUTH_APPLE_SECRET
}
}
}оказывается что кроме JSON c JSON Schema больше ничего и нету.
это, конечно, не так, есть как минимум CUE и несколько других вариантов
Конечно же есть: https://page.hyoo.ru/#!=bl420c_mf5efi
Лично для меня yaml куда более читабелен чем пример который в статье. Опыт подсказывает что конфиг хорош такой, который можно править руками через nano «в особых случаях». YAML хоть я его и не люблю это делать позволяет без проблем, как и обычный config
А на тему “больших» конфигов где еще и модульность нужна - история уже про GUI , либо централизованная раздача конфигов через сеть. В каком они там формате уже будут - параллельно
Итого, без обид, но проблема высосана из пальца.
Опыт подсказывает что конфиг хорош такой, который можно править руками через nano «в особых случаях». YAML хоть я его и не люблю это делать позволяет без проблем, как и обычный config
Почему вы считаете, что ATMC нельзя так же править руками?
На мой взгляд его править даже удобнее, чем тот же yml, потому что в nano не видно ни пробелов ни табов и ошибиться с отступом в большом конфиге будет очень просто
Даже в IDE часто можно затупить с отступом. В прочем со скобкой тоже можно затупить:)
Почему вы считаете, что ATMC нельзя так же править руками?
Просто для меня скобки фигурные которые показывают вложенность – не humanlike формат, вот и все
На мой взгляд его править даже удобнее, чем тот же yml, потому что в nano не видно ни пробелов ни табов и ошибиться с отступом в большом конфиге будет очень просто
При аварийной правке есть гениально простые решения:
В корне лежит всегда default.yaml/conf как пример
При редактировании конфигурация копируется с приставкой backup
Это позволяет полностью забыть о спецсиволах даже когда накосячил с ними, все восстанавливается или просто копируется из существующих
Ну а если прям задача найти проблема: "cat -A файл" отобразит скрытое
Странно что я это объясняю, будто бы вы не понимаете как реально строится программное обеспечение
Даже в IDE часто можно затупить с отступом. В прочем со скобкой тоже можно затупить:)
Возможно "Даже" возникнет в вашем IDE, и тут только совет его поменять. А к примеру в VSCode затупить с yaml конфигурацией - это что-то нереальное. На тему скобок, тут тоже вопросы. На тему скобок тоже не понимаю, не помню вообще когда последний раз скобки ставил клавишей. Конкретный IDE на Golang по первым буквам func/switch+Enter сразу рисует необходимый блок автоматически со всеми скобками и ставит указатель на имя, потом +tab и можно заполнить аргументы...и тд
Лично для меня yaml куда более читабелен чем пример который в статье.
Да, для меня тоже
Тут проблема примеров просто - в реальности конфиги в 100 раз больше - там то и начинаются проблемы
Я рад что есть разработчики которые делают простыни конфигураций, к примеру такие можно найти на mysql и прочий софт. Но там хорошо, настроил один раз и забыл на большой период времени (в большинстве случаев)
Но если конфиги такие что еще надо постоянно что-то там менят, подкручивать или объединять и это сотнями строк в yaml/conf/ATMC файлах и все это без GUI – то думаю для таких программистов в аду есть отдельный котел
К слову, мы для своих систем писали раздачу конфигурации с сервера, т.е в приложение вшито или в конфиге адрес API точки доступа куда приложение обращается при запуске и тянет с сервера ту конфигурацию которая актуальна и можно даже пушить настройки + GUI где можно поменять настройки полностью для любого приложения. Когда мы создавали пакеты, ничего подобного и дельного не нашли. Вот таких систем не хватает...PS: Хотя может плохо искали
Мне вот интересно, что вы предпримете в таких условиях:
- вы начинаете новый проект
- понимаете, что конфигурация для prod и stg будут отличаться
- например, на prod нужно 10 воркеров для аутбокса, а на stg всего 5, чтобы не ушатать слабые машины на stg
Как вы поступите тут? Как будете конфигурировать приложение?
Этот вопрос почти в вакууме, но у меня есть пример монолитного приложения и которое на prod жрет как не в себя. После деплоя в папке лежит test.yaml / prod.yaml.
Для проверки на prod после deploy мы запускаем с test.yaml где зажаты все гайки в том числе количество потоков и ограничения (просто для проверки что приложение запускается и корректно переваривает данные), далее уже запускаем as service, но с prod.yaml.
Поэтому задачу stg/prod я решал бы абсолютно так же, просто в конфиге прописывались все ограничения или даже вводим бы вшитый механизм а-ля ключ запуска: stg/prod, в том числе можно вшить механизм оценки того сколько конкретная "машина" может держать потоков на базе информации о системе.
Другое вопрос если у вас в конфиге например ограничения описываются более чем 2-3 переменными (как в моем примере, т.к у нас все ограничения потоков описаны двумя строчками конфигурации).
Я понимаю что можно сделать монолит поставив к примеру 100500 endpoint точек API и на каждую повесить воркер с ограничением и потом успешно это в конфигурацию вынести отдельно, но опять же такие истории предполагают уж изменения конфигурации налету. При deploy нового подобного приложения собирается аналитика или при атаке на endpoint вносятся PUSH ограничения и тут мы опять приходим к централизации и GUI
раздачу конфигурации с сервера
А на сервере, как оно конфигурировалось? Через UI и в базе лежало?
У нас сейчас все хранится в mysql базе, GUI и сервер раздачи написал chatgpt. Нам надо было срочно решение с GUI.
Пакет тоже написал chatgpt для стыковки. Сейчас стараемся во весь софт сделать это обновление.
При старте приложения просто ./app --config=имя_приложения
Он по имени обращается на API вшитый в код и ему отдается JSON готовый из базы. Сделано на коленке, увы пока так и времени доделать нет. Но работает уже год и все довольны. Осталось весь софт перевести на эту историю
Вообще считаю что mysql это была ошибка, потенциальная точка отказа. Лучше в файлах...
Вот кстати ваш формат можно было к этому приспособить...т.к вы сами предположили что конфиги могут быть большими...Ну пускай в одном файле будет сразу много конфигураций и при запросе нужный кусок отдается по HTTP
Основная беда в том что mysql очень плохо переживает сбои если не настроена репликация (пс у нас она не настроена), т.е если что у нас будут веселые ночи. Если бы конфигурация была упакована в единый файл к примеру с вашим форматом...то вопрос бекапа – вопрос простого копирования. И если что-то случилось можно быстро перекинуть бек и загрузить новый экземпляр раздачи.
У вас такая прям явная точка отказа появилась. Аж мурашки по коже.
Даже не скрываю этого и эти мысли иногда посещают, что вот когда-нибудь оно откажет. Один жирный плюс на противовесе – структуры приложений, – вся конфигурация подтягивается один раз и работает сутки. Очень редкий кейс PUSH новых настроек. Т.е отвалится mysql или конфигуратор, приложения продолжат работу.
Но то что надо этим вопросом заняться и вообщем-то в эпоху chatgpt – дело реально 15 минут все прекрасно понимают. Не можем выбрать верную схему. Из вариантов которые рассматриваем – API точка на каждом приложении, которая сразу вещает схему и позволяет менять параметры приложения. Рисует GUI который подтягивает список всех приложений которые сейчас работают, там есть некий endpoint где GUI может получить схему которую можно менять и выводит формы необходимые. Ты меняешь что-то и через отдельный endpoint настройки сразу пушится в приложение. Но этот вариант уже не 15 минут + надо будет отладку делать перед добавлением в продакшен
Забавно. Упрекать шум, а потом использовать фигурные скобки и кавычки, что и есть самый неприятный шум в конфигах.
YAML навсегда!
Кавычки только для строк
Скобки позволяют хоть в одну строку писать конфиг
Причем скобки для массивов в yml тоже есть - можно и без них, если на новой строке писать - ну вот уже несколько способов сделать одно и тоже - не очень нравится
Ну и плюс скобки более четко визуально группируют данные - ну это ИМХО, конечно
В ямле no это строка "no" или false? (И там ещё много примеров, можно погуглить по "yaml from hell")
Уж лучше явные строки чем гадать на кофейной гуще, и вычленять различия версий 1.0, 1.1, 1.2 (речь про ямл спек, конечно же)
Ваша статья получилась очень близкой к тому, о чём многие регулярно вздыхают: усталость от бесконечных отступов и кавычек в YAML/JSON и желание наконец-то просто описывать настройки. Идея вынести импорт, слияние и подстановку переменных в отдельный, простой DSL - звучит заманчиво. Примеры синтаксиса понятно читаются, особенно нравятся лаконичные импорты и spread‑оператор.
Есть, правда, пара вопросов, которые было бы интересно обсудить. Например, как ATMC ведёт себя при конфликте типов при слиянии двух конфигов или что происходит, если ключ встречается в нескольких местах? Планируется ли типовая проверка, чтобы ловить подобные ошибки заранее? Как вы видите дальнейшее развитие проекта: будет ли поддержка других языков помимо Go и есть ли планы на интеграцию с редакторами (подсветка, автодополнение)? Сейчас конфигурационных DSL уже довольно много (HOCON, Dhall, CUE), любопытно было бы увидеть сравнение ATMC с ними.
В целом же направление классное: хочется, чтобы конфиги были такими же предсказуемыми и приятными, как код.
Удачи в развитии!
как ATMC ведёт себя при конфликте типов при слиянии двух конфигов или что происходит, если ключ встречается в нескольких местах?
В любом случае по итогу ключ будет всегда один на выходе - каждый будет переопределять предыдущий - тип ключа будет таким, какой он был у последнего ключа, который переопределил предыдуший
Планируется ли типовая проверка, чтобы ловить подобные ошибки заранее?
Даже не задумывался, пока не спросили. Вообще думаю хорошо бы завести такую проверку - поможет быстро находить ошибки в конфигурации
> Как вы видите дальнейшее развитие проекта: будет ли поддержка других языков помимо Go
Если язык заимеет хоть какой-нибудь успех на языке Go, то да
Иначе, кажется, это пустая трата времени
и есть ли планы на интеграцию с редакторами (подсветка, автодополнение)
Есть. Использую язык для своих проектов - чувствую, как без хотя бы подсветки жить тяжело (но все равно лучше, чем с json или yml :))
> любопытно было бы увидеть сравнение ATMC с ними
Выше тоже это подмечали. А я просто не хотел раздувать статью
Может быть распишу сравнение позже
Bash/make?
“Все уже украдено»
Любы Мерри из коробки, если Makefile то
V ?=default - если надо переопределять,
V := const если не надо чтобы переопределяли.
Подкину для обсуждения свеженький (но уже 12.7k stars) формат TOON (https://github.com/toon-format/toon), созданный для экономной передачи в LLM огромного количества данных, вплоть до содержимого целой базы данных. Это сильно модифицированный гибрид YAML и CSV. Сам по себе он мне понравился для моих целей (а это вовсе не общение с LLM, а передача данных в 6NF). Он практически идеален: почти нет визуального мусора, многократно меньше строк, чем в JSON. Одним щелчком вставляется в Excel в правильные столбцы (я в качестве разделителей выбрал табы). Но спецификация огромная и при этом отрывочная и неудобная. Пока не сконвертировал вручную JSON в TOON (см. мой пример), на что ушло много времни, ничего не было понятно. Поэтому есть сомнения, что все конверторы будут работать одинаково, хотя их уже много понаделали. Конверсия из JSON в TOON, к сожалению, односторонняя, если я правильно понял. Возможно, что это поправят. Три часа назад вышла версия 1.0.0.
Статьи о нем:
Is JSON Dead? Meet TOON – The Token-Efficient Alternative for LLM Prompts
JSON vs TOON – Token-efficient data format for LLMs
JSON, YAML, TOML, HCL - за последние годы человечество успело изобрести десяток языков для конфигурации.
Странно, что забыли в пример SGML/XML поставить, он самый шумный и избыточный. При этом приведены в пример зачем-то краснокнижный HCL и вторичный TOML. Ладно, это мелочи, просто к слову.
Каждый обещал быть "простым", "удобным" и "читаемым человеком".
Гибкость и строгость в большинстве случаев увеличивают сложность.
Но по факту - все они страдают от одних и тех же проблем: шумный синтаксис, хрупкие отступы, бесконечные кавычки и отсутствие элементарных возможностей вроде модульности и слияния конфигов.
Из всех представленных примеров (+XML) на отступы только YAML полагается. Кстати, по этой причине в реальных применениях редко используются все возможности: я встречал какой-то язык конфигурации с синтаксисом XML, но без атрибутов, только теги. Но самое главное: тут же автором предлагается РАСШИРЕННЫЙ вариант JSON5 с шахматами и балеринами.
Пора перестать с этим мириться и сделать конфигурации наконец человеческими.
И сразу вспоминается шутка про N стандартов и новый более лучший N+1-й стандарт.
Кстати Nix expression language на удивление хорош в качестве языка конфигурации. Там есть вообще все что надо и его можно evalить до json представления, а ещё у него хорошая поддержка тулов.
Как нибудь хочу попробовать его заюзать.
Еще одна хорошая фича в концепцию -"отложенное определение"
{
user: user..
address: address..
}
user : {
first: "Ivan",
second: "Ivanov",
}
address: {
country: "Russian Federation",
city: "Moscow",
street: "Lenina",
home: 1
}YAML, JSON страшные? А XML автор видел? )
И, вообще, мы - программисты, - не анархисты. Нас не заманишь АТМСкой мясистой. Особенно, когда она только для go.
JSON с импортами назвать топовым - это конечно сильно
А можно примеры как будут diff выглядеть?
Сортированый и максимально упрощённый yaml - понятен, там все более менее однозначно.
Toml уже заставляет грустить тем что Саша пишет пути так, а Маша по другому.
Json... если отсортировать и отбьютифарить, то можно, но скобочки добавят боли.
А как с этим здесь?
Почему JSON и YAML мешают...
Плохому танцору... Ну вы поняли
Ничего не понял, в новом формате такой же JSON как и было с кучей фигурных скобок = ужасно.
Самое хорошее:
1) для мелких конфигов: .ENV
(до 100 строк)
2) для средних конфигов: .INI
(до 1000 строк)
3) для сложных конфигов: .TOML
(не пользовался, но это улучшенный .INI)
4) для данных (не конфигов): .JSON
5) для данных в виде таблиц: .CSV
6) YAML - надо знать, но лучше не внедрять самому
Зачем куча форматов, если достаточно одного, который лучше справляется со всеми этими кейсами?
А какой лучше справляется?
Я выше кидал ссылку, не люблю повторяться.
Отправлять искать ссылку по десяткам комментариев - это выглядит хамовато, если честно.
Но я нашел. Хотелось бы понять, как вы себе представляете CSV в этом самом вашем волшебном формате? Не, конечно, так-то туда можно таблицу на 100 столбцов и 10000 строк запихать, но вот от наглядности и человекочитаемости там останется ровно ничего.
P.S. Что касается значащих вайтспейсов - это по определению зло. Отсутствие "экранировки" - тоже. Экранирующие символы используются не только для того, чтобы экранировать что-то, но и дают возможность вставлять символы, которые иным образом вставить либо невозможно, либо сложно, либо не наглядно.
Ну и, да, будем честными. Этот формат не справляется. Просто потому, что его никто не использует.
Что ж, если уж откровенничать, то ваш комментарий выглядит туповато.
Табличные данные представляются так: https://page.hyoo.ru/#!=5zg1fn_nw0oyv
Почему вы обратили внимание только на синтаксис?
Обратите внимание на фичи, пожалуйста
Ни один из перечисленных вами языков такие фичи не дает
Может я по диагонали смотрел, но выглядит прям как KYAML
Лучше бы создатели софта чаще следовали стандартам и рекомендациям, типа 12 факторов или xdg, чем "новые" стандарты не нужные изобретали
Но ведь это JSON, только без запятых???
И я не понял, в чём проблема все перечисленные проблемы решать JSON'ом?
Как в json сделать импорт и слияние?
В .NET раньше делалось так:return new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{EnvironmentName}.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build();
Здесь берём базовый файл с настройками appsettings.json, если есть файл с настройками конкретного окружения (например, appsettings.Development.json), то перезаписываем значения, которые есть во втором файле, остальные не трогаем, затем перезаписываем значениями из переменных окружения, опять же, только теми, которые есть в переменных, остальные не трогаем.
Сейчас мб что-то изменилось.
Поправка - язык написан.. - не написан, а нагенерен под. Вопрос, а что на хабр можно постить вывод LLM? Так можно было? *Ушел переливать дампы гениальных идей из LLM на хабр*
Почему бы не писать конфиги на ЯП с динамической типизацией, особенно если вы разрабатываете на этом языке.
Например Typescript позволяет написать DSL для вашего конфига, который будет применять правила в config-time (проверка типа). Вплоть до кастомных сообщениях о ошибках. Ваш LLM будет рад.
PS Typescript 6.0 будет уже написан на go. (не реклама) 😀
На ЯП со статической типизацией будет ещё лучше, жалко таких встраиваемых не так много. Кроме TS есть например ещё KTS.
Зачем? ЯП дает слишком много возможностей. Потом будете обкладываться документами, соглашениями с названием «что можно использовать при конфигурации, а что нет»
Потом будете обкладываться документами, соглашениями с названием «что можно использовать при конфигурации, а что нет»
А чем оно отличает от документации по языку конфигурирования?
Тем что в документации к языку конфигурирования написано, как им пользоваться
А в документации к ЯП, который используется для конфигурировании будет написано, как им нельзя пользоваться
И попробуй заставь новичков в проекте или джунов понять и осознать это быстро
Если есть хорошее ревью еще будет норм
Если ревью плохое (а не везде оно хорошее), жди беды
В случае с языком конфигурирования заговнокодить не получится - у него просто нет таких возможностей
Вот для аналогии: в php есть свой встроенный шаблонизатор, который позволяет вообще что по кайфу делать
Вопрос: сколько говнокода во вьюхах я видел?
Ответ: много
И походы в базу видел и кучу логики видел
Жуть
А будь там шаблонизатор, который не умеет все это делать, такой говнокод обошел бы меня стороной:)
И попробуй заставь новичков в проекте или джунов понять и осознать это быстро
Так не прямым 'eval' вся втягивать, а через линтер, что будет бить по рукам, когда вызовется или использоваться что-то кроме нужных функций.
Да, линтер решает, согласен
Причем удобно пользоваться языком, который тысячу раз протестирован и не имеет уязвимостей
Причем если ts на go переписан, то его AST получить изи, а значит сделать любой линтер или компилятор во что угодно на go тоже изи
Но мне мой лаконичный язык все равно больше нравится ахах
А есть уже подобные линтеры для ts конфигурации, не знаете?
Вот если бы еще сделать GUI, отдельное приложение для этого, чтоб можно было собирать конфиг, и еще прототипы добавить (типа классы) и чтоб приложение само сгенерировало файлы для языка, которые подключил а там например с++ классы с прописанными полями
Вот это было бы дааааа
HOCON уже вспоминали?
Симпатично выглядит, привлекает простота и лаконичность. Нравится идея опускания запятых в конце строки и имена ключей без кавычек, и одновременно обязательное наличие кавычек для строчных значений - новомодное их опускание в этой части в некоторых форматах приводит к неоднозначностям и ненужному усложнению спецификации и реализации, и даже к ухудшению восприятия.
Непонятно, почему минусы - человек поделился идеей (и неплохой) и своей реализацией - только за это уже молодец, разве нет?
Как мне кажется, минусы навалили из-за:
статья просто копипаста из ридми проекта (или наоборот)
в статье очень много воды, громких заголовков и повторений, что также отдаёт ЛЛМ вайбами
действительно важные фичи этого языка не вынесены на первый план и на них не сделан акцент, но в свою очередь сделан акцент на простоте синтаксиса
дополняя предыдущий поинт, нет сравнений даже с JSON, упомянутым в заголовке
ИМХО, у статьи было бы более высокая плотность информации на символ если бы она была сильно короче, к примеру:
короткое введение
нужно мержить конфиги рекурсивно? -- делается через
...нужно разбить конфиги на модули? -- есть модули
и т.д.

Почему JSON и YAML мешают вам писать нормальные конфиги (и чем их заменить)