JSON, YAML, TOML, HCL - за последние годы человечество успело изобрести десяток языков для конфигурации.

Каждый обещал быть "простым", "удобным" и "читаемым человеком".

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

Пора перестать с этим мириться и сделать конфигурации наконец человеческими.

? Перестаньте

  • утомлять глаза, пытаясь разобраться в тонне бесполезных кавычек

  • утомлять глаза, пытаясь распознать в каком месте есть проблема с отступом

  • писать велосипед, когда в очередной раз нужно мержить конфиги для разных окружений

  • писать велосипед, когда нужно парсить env переменные в структуру конфига

  • забивать мозг, пытаясь разобраться в огромной конфигурации из-за отсутствия модульности

⁉️ Как перестать?

Использовать адекватный язык для конфигурации ATMC
ATMC - минималистичный, но мощный язык конфигурации, созданный для удобного описания системных настроек.
Он сочетает простоту синтаксиса, поддержку импортов, переопределений, гибкого слияния конфигов и переменные окружения.

? Почему ATMC?

  • топовый синтаксис

    • супер минималистичный

    • интуитивно понятный и простой

    • не перегружен конструкциями

    • не зависит от отступов, переносов, кавычек, запятых и прочей чепухи

    • очень простой и в то же время достаточно мощный

  • модульность

    • можно импортировать разные кусочки (модули) конфига

    • очень минималистичный синтаксис импорта

    • можно обращаться к вложенным полям импортированного конфига

  • слияние конфигов (киллер фича)

    • супер легко мерджить несколько конфигов (например, common + stg или prod)

    • есть возможность переопределять поля

    • умное слияние - рекурсивное - не перетирает поле полностью

  • встраивание

    • можно встраивать объекты и массивы с помощью spread (...) оператора

    • с помощью него же и происходит слияние

  • доступ к env переменным

    • $YOUR_ENV_VARIABLE

  • поддержка всех необходимых типов

    • int

    • float

    • string

    • bool

    • object

    • array

  • компиляция в структуру и мапу из коробки

  • поддержка комментариев

  • расширяемость:

    • можно получить итоговый AST со всеми резовленными значениями

    • можно сделать на этой основе компилятор во что угодно

    • в перспективе можно поддержать LSP

? Примеры использования

Простой пример

?File: config.atmc

{
    logging: {
        level: ["warn", "error"]
    }
    database: {
        clickhouse: {
            username: "username"
            password: "password"
            port: 9000
        }
    }
}

Пример с импортом

?File: config.atmc

db ./database.atmc // Супер минималистичный импорт

{
    logging: {
        level: ["warn", "error"]
    }
    database: db // Тут появится объект из импортированного файла
}

?File: database.atmc

{
    clickhouse: {
        username: "username"
        password: "password"
        port: 9000
    }
}

Пример с spread + env

?File: config.atmc

db ./database.atmc

{
    logging: {
        level: ["warn", "error"]
    }
    database: {
        postgres: {
            username: $POSTGRES_USERNAME // Будет подставленно значение из env
            password: $POSTGRES_PASSWORD
        }
        db... // Сюда встроится импортированный конфиг
    }
}

?File: database.atmc

{
    clickhouse: {
        username: "username"
        password: "password"
        port: 9000
    }
}

Пример с доступом к вложенному полю

?File: config.atmc

db ./database.atmc

{
    logging: {
        level: ["warn", "error"]
    }
    database: {
        postgres: {
            username: $POSTGRES_USERNAME // Будет подставленно значение из env
            password: $POSTGRES_PASSWORD
        }
        clickhouse: db.clickhouse // Сюда будет встроен вложенный в db объект
    }
}

?File: database.atmc

{
    clickhouse: {
      username: "username"
      password: "password"
      port: 9000
    }
}

Пример со слиянием

?File: common.atmc

{
    logging: {
        level: ["error"]
    }
    database: {
        postgres: {
            username: $POSTGRES_USERNAME
            password: $POSTGRES_PASSWORD
            host: "localhost"
            port: 5432
        }
    }
}

?File: prod.atmc - конфиг для prod окружения

common ./common.atmc

{
    common... // Встраивается общий конфиг
    // Далее добавляются новые параметры и переопределяются параметры из общего конфига
    logging: {
        level: ["warn", "error"] // Переопределяется
        enable_tracing: true // Добавляется новое поле
    }
    database: {
        postgres: {
            port: 6432 // Переопределяется только порт, остальные поля не будут затронуты      
        }
    }
}

?File: stage.atmc - конфиг для stage окружения

common ./common.atmc

{
    common... // Встраивается общий конфиг
    // Далее добавляются новые параметры и переопределяются параметры из общего конфига
    logging: {
        // Переопределяется - можно без запятых
        level: [
            "info"
            "warn"
            "error"
        ]
    }
}

⚙️ Что под капотом?

Язык конфигурации работает благодаря множеству компонентов:

  • lexer

    • преобразует код в токены

  • parser

    • преобразует токены в AST

  • analyzer

    • проверяет семантику в рамках одного AST

    • проверяет наличие неиспользованных переменных

    • проверяет использование неопределенных переменных

  • linker

    • резолвит значения переменных из всех связанных AST

    • резолвит значения переменных среды

    • выдает один итоговый AST

  • processor

    • получает на вход путь до файла с конфигом

    • запускает все необходимые компоненты для обработки всех связанных файлов

    • отдает полученный итого��ый AST после линковки

  • compiler

    • компилирует итоговый AST

    • компиляторы могут быть разными (в map, в struct и т.д.)

? Поддержка и интеграция

Язык написан пока только на Go, соответственно работает только для этого языка программирования.
В дальнейшем планируется поддержка других платформ

? В планах

  • компиляция в самого себя

    • будет удобно смотреть итоговый конфиг

    • можно будет выводить итоговый конфиг, как это делает, например, nginx -T

  • кодогенерация структур на базе конфига

    • тогда описывать конфиг придется только в одном месте - в atmc файле

  • автоматическая загрузка env переменных из .env файла

    • сейчас такого нет - нужно будет самим загружать, чтобы они стали доступны в os.Getenv

    • но будет удобно, если добавить

  • подсветка синтаксиса

  • имплементация LSP

    • умная подсветка синтаксиса

    • подсказки

    • поиск определений и помощь в импортах

P.S. Знаю, что уже есть похожие языки, но у всех есть свои недостатки. Где-то приятный синтаксис, но нет модульности; где-то есть модульность, но нет слияния; а где-то есть всё, но язык излишне усложнён. В ATMC есть всё нужное - и ничего лишнего.

Моя цель - сделать конфигурации такими же простыми, как Go-код: предсказуемыми, читаемыми и расширяемыми.


? Репозиторий и примеры: https://github.com/atmxlab/atmc

Комментарии (43)


  1. Landgraph
    10.11.2025 14:30

    Шутка про n-стандартов…

    ИМХО, когда конфиг становится сложнее, чем можно описать в ini файле - что-то пошло не так. И этот конфиг уже перестает быть человекочитаемым и лучше уже иметь какой-то гуй.


    1. paramtamtam
      10.11.2025 14:30

      В дополнение, крайние несколько лет являюсь адептом секты "config-less", когда все что нужно сконфигурировать - должно иметь cli/env ручки для этого, и знаете - этот подход более чем жизнеспособен! И строгие правила, и валидация, и генерация документации из этого кода - прям хорошо. Да что уж говорить - великий и могучий Traefik и тот умеет себя конфигурировать флагами без сильной боли ниже поясницы (если понимаешь что делаешь), а он тот еще комбаин.


    1. supermetrolog Автор
      10.11.2025 14:30

      На моем опыте в бизнесовых приложениях не удается обойтись простецким конфигом, который можно было бы удобно описать в ini

      Во всех проектах всегда были фреймворки, которые из коробки давали модульность + слияние конфигов - и это прям надо реально. И даже для go приложений такое надо, потому как на нем мы тоже бизнесовый код пишем - сейчас мы мерджим yml

      Понимаю проблему сложных конфигов, поэтому пытался найти баланс - добавил ключевые фичи, без которых нереально жить в бизнесовых приложениях ИМХО
      Постарался в общем не усложнять синтаксис и читабельность конфига


  1. Autochthon
    10.11.2025 14:30

    Лучше S-выражений еще ничто человечество не придумало.


    1. nin-jin
      10.11.2025 14:30

      1. Autochthon
        10.11.2025 14:30

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


        1. inkelyad
          10.11.2025 14:30

          копи паста нормально не работает,

          Если редактор не тупо захватывает пробелы в начале и их вставляет, а понимает, что блок копирует и делает (де)индент по месту вставки - работает. Ну или умеет по TAB/Shift-TAB отступ выделения менять - тогда немного ручной работы есть.

          Но да, в nano редактировать неудобно.


    1. krendelbok
      10.11.2025 14:30

      Жаль, что Hocon не популярный, очень приятный формат/расширение json


  1. Astrowalk
    10.11.2025 14:30

    Кругом убийцы форматов... https://habr.com/ru/articles/248147/


  1. pilot114
    10.11.2025 14:30

    Модульность и слияние нужно реализовать не как фичу самих конфигов, а в том месте где они подключаются, после декодирования - и при этом вообще не зависеть от формата - вот куда усилия приложить надо, а не в изобретение json диалекта


    1. supermetrolog Автор
      10.11.2025 14:30

      Такое реализовать на самом деле не сложно - можно любой формат переложить в мапу, сделать это несколько раз для нескольких файлов и сделать мердж

      Так и делают чаще всего

      Но что не нравится в таком подходе:
      - список файлов определяется в приложении - то есть без просмотра кода конфигурацию не прочесть
      - без просмотра кода не понять, по каким правилам строится конфигурация - кто кого переопределяет и все такое

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


  1. kez
    10.11.2025 14:30

    Основная проблема всех "статичных" языков не в синтаксисе (хотя насчёт ямла можно поспорить), а в том, что в этих языках нет синтаксических конструкций для избежания копипасты.

    HCL пытается с этим что-то делать, вводя модули, но не забывая вводить магические переменные для описания циклов — что, по мне, отвратительно, и начинает напоминать Ansible с его декларативными конструкциями, которые на практике оказываются просто нетипизируемым ямлом. Ямл тоже пытается избежать копипасты со своими anchors, и <<, но, опять же, на практике это превращается в просто месиво.

    Итого, потребность в хорошем языке для конфигов действительно есть.

    В статье отсутствует какое-либо сравнение с существующими языками, включая плюсы и минусы каждого из них. Понятно, что ATMC яыляется более "выразительным", и более абстрактным, нежели JSON, YAML etc. Поэтому также стоит сравнить с Pkl, dhall, CUE, jsonnet и другими.

    По статье, не доконца понял

    • можно ли отрендерить/экспоритировать .atmc конфиг в другие форматы?

    • как сделать ключ с пробелом?

    • можно ли сделать циклы?

    • пофейлится ли конфиг с одинаковыми ключами или есть какое-то правило?

    • при рекурсивном мерже, мержатся ли списки или просто перезаписываются?

    Ещё много вопросов можно задать, но думать лень


    1. user-book
      10.11.2025 14:30

      YAML как раз позволяет "копипастить" причем довольно гибко, можно указывать шаблон, а потом докидывать и перезаписывать конкретные параметры, это не Ansible-приколы а часть стандарта

      вообще из опыта конфиг нужно строить универсальным:

      • хочешь пихай json

      • хочешь yml или что то вообще странное

      • хочешь запускай без конфига вообще

      • хочешь укажи всего пару через cli параметры

      решать за клиента как ему лучше самая порочная практика. Автор статьи вообще создал уже существующее неоднократно, есть куча похожих json-подобных языков конфигурации


    1. inkelyad
      10.11.2025 14:30

      Итого, потребность в хорошем языке для конфигов действительно есть.

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

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


      1. kez
        10.11.2025 14:30

        урезав возможности для того чтобы убрать всякие уязвимости.

        или просто использовать уже готовый язык, с урезанными возможностями, хорошим тулингом и имплементацией с минимальным количеством зависимостей (чтобы уменьшить риск уязвимостей)

        но в целом это субъектившина


    1. supermetrolog Автор
      10.11.2025 14:30

      но не забывая вводить магические переменные для описания циклов — что, по мне, отвратительно

      Согласен - поэтому такого у меня не будет - это все-таки язык конфигурации, а не язык программирования

      > можно ли отрендерить/экспоритировать .atmc конфиг в другие форматы?

      Сейчас можно только в JSON - причем это ненастоящая компиляция в json - применен такой хак: компилим в мапу, а из мапы в json с помощью стандартного пакета - в будущем можно сделать нормальную компиляция, но пока и так сойдет - можем себе позволить так как скорость компиляции не имеет значения:)

      Больше ни во что нельзя
      В планах компилировать в самого себя - то есть выдать один конфиг с отрезолвленными значениями - думаю будет удобно дебажить, как это позволяет делать nginx -T

      > как сделать ключ с пробелом?

      Никак. А надо?

      > можно ли сделать циклы?

      Если это про циклические зависимости, то нет - детектится и выдается ошибка

      > пофейлится ли конфиг с одинаковыми ключами или есть какое-то правило?

      Нет, не пофейлится - можно переопределить значения - это не то чтобы фича - просто так работает - возможно стоит запретить, а то потом такую проблему фиг отыщешь

      > при рекурсивном мерже, мержатся ли списки или просто перезаписываются?

      Массивы перезаписываются - мердж не позволит переопределить значения в нем, так как ключей там нет, как в объектах


      1. kez
        10.11.2025 14:30

        все-таки язык конфигурации, а не язык программирования

        Встаём на тонкий лёд споров об определениях. Является ли ваш х... и ямловый <<: *a тем же самым, что и питоновское a | { ... }? Если да, то почему одно является язком программирования, а другое нет?

        Язык программирования не обязательно должен быть развесистым как питон, даже простенький DSL может являтся ЯПом. Также, к счастью, перечисленные мной конкуренты (CUE, jsonnet, Pkl, dhall) не являются generic-purpose язками, и некоторые даже не являются turing complete.

        Было бы интересно увидеть подробное сравнение вашего языка и перечисленных.

        как сделать ключ с пробелом?

        Никак. А надо?

        Получается, что язык даже не является суперсетом JSON. Но если серьёзо отвечать на вопрос, то да, конечно надо.

        можно ли сделать циклы?

        Если это про циклические зависимости, то нет - детектится и выдается ошибка

        Нет, речь про циклы, конечно, а-ля for item in ... или подобные способы избежать копипасты кода. Особенно полезно при модификации списков, учитывая что рекурсивный мерж просто обновит значение (что в целом логично, и правильно)

        В целом свой язык конфигов прикольно, хорошее занятие.

        От себя могу добавить (и там в треде выше уже упомянули), что при работе с огромным количеством конфигов действительно хочется иметь простой не-тьюринг полный язык для избежания дедупликации всего по нескольку раз, и для этого нужны абстракции в виде циклов, условий, и т.п. Но это субъективно конечно. Моё мнение в основном совпадает с этой статьёй https://ruudvanasseldonk.com/2025/abstraction-not-syntax.


        1. supermetrolog Автор
          10.11.2025 14:30

          Если да, то почему одно является язком программирования, а другое нет?

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

          > Было бы интересно увидеть подробное сравнение вашего языка и перечисленных.

          Ага, как-нибудь распишу

          > даже не является суперсетом JSON.

          Почему это плохо?

          > Но если серьёзо отвечать на вопрос, то да, конечно надо.

          Кому и зачем это надо? Никогда не видел, чтобы пробелы в конфигурации использовались
          Если действительно надо, хотелось бы пример какой-нибудь, где без этого не обойтись
          А если для галочки, чтобы стать суперсетом JSON, то думаю можно обойтись без этого

          > Нет, речь про циклы, конечно, а-ля for item in ... или подобные способы избежать копипасты кода. Особенно полезно при модификации списков, учитывая что рекурсивный мерж просто обновит значение (что в целом логично, и правильно)

          Что-то мне, кажется, что это дикий оверхед, который нужен 1% разрабов/проектов
          Такая сложная логика должна быть на уровне приложения, а не на уровне конфигурации

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

          В целом идея сделать максимально простой язык, который закрывает 99% потребностей
          А вот этот 1%, где циклы нужны или еще какая-то экзотика уж лучше не покрывать

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

          Ну и в довесок в ATMC можно обращаться к полям импортированного конфига
          То есть значения, которые дублируются можно вынести отдельно и обращаться к ним, а не копировать - по итогу можно будет изменить значение в одном месте и поменяется везде

          Ну в общем не понимаю я циклы эти в конфигах - они меня пугают

          ---
          Перечитал свой ответ и вижу, что ни с чем особо не согласился по итогу - но хочу сказать, что в любом случае спасибо за фидбек - это очень полезно для меня - много нового узнал:)


          1. kez
            10.11.2025 14:30

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

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

            Было бы неплохо для этого использовать какой-нибудь простенький язык, но мы решили остаться на питоне, потому что остальные куски инфры уже были на нём. Но в целом я думаю какой-нибудь CUE бы нам подошёл.

            Удачи вам с вашим языком конфигов, посмотрим как будет развиваться


  1. SWATOPLUS
    10.11.2025 14:30

    Почему не писать конфиги на Typescript? Тут и импорты и экспрорты и типы для валидации, а потом это все компилировать в json? А если эти конфиги редактирует 3rd party, то напишите им компилятор в json или же https://github.com/laverdet/isolated-vm


    1. supermetrolog Автор
      10.11.2025 14:30

      Потому что это сделает конфигурацию абсолютно нечитабельной


  1. NeoCode
    10.11.2025 14:30

    https://json5.org , это не оно?


    1. supermetrolog Автор
      10.11.2025 14:30

      Неа, не оно
      Насколько вижу, там нет фич, которые есть в ATMC (импорты, мерджи)
      Но синтаксис похож, да - ну это не удивительно, ведь я ориентировался на js-ные объекты


  1. Ru6aKa
    10.11.2025 14:30

    Как только встает вопрос про валидацию сложного конфига, то оказывается что кроме JSON c JSON Schema больше ничего и нету.

    Да и у этого решения тоже есть проблема, object или array никак не прокинешь из переменных окружения.


    1. supermetrolog Автор
      10.11.2025 14:30

      Да и у этого решения тоже есть проблема, object или array никак не прокинешь из переменных окружения.

      Интересная идея
      Мне такое не пригождалось никогда, поэтому даже не задумывался о таком
      Может есть примеры, где такой функционал хотелось бы иметь?


      1. Ru6aKa
        10.11.2025 14:30

        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
            }
          }
        }



        1. supermetrolog Автор
          10.11.2025 14:30

          На самом деле крутая идея
          Возьму на заметку, спасибо


    1. kez
      10.11.2025 14:30

      оказывается что кроме JSON c JSON Schema больше ничего и нету.

      это, конечно, не так, есть как минимум CUE и несколько других вариантов


  1. unicorn_style
    10.11.2025 14:30

    Лично для меня yaml куда более читабелен чем пример который в статье. Опыт подсказывает что конфиг хорош такой, который можно править руками через nano «в особых случаях». YAML хоть я его и не люблю это делать позволяет без проблем, как и обычный config

    А на тему “больших» конфигов где еще и модульность нужна - история уже про GUI , либо централизованная раздача конфигов через сеть. В каком они там формате уже будут - параллельно

    Итого, без обид, но проблема высосана из пальца.


    1. supermetrolog Автор
      10.11.2025 14:30

      Опыт подсказывает что конфиг хорош такой, который можно править руками через nano «в особых случаях». YAML хоть я его и не люблю это делать позволяет без проблем, как и обычный config

      Почему вы считаете, что ATMC нельзя так же править руками?
      На мой взгляд его править даже удобнее, чем тот же yml, потому что в nano не видно ни пробелов ни табов и ошибиться с отступом в большом конфиге будет очень просто

      Даже в IDE часто можно затупить с отступом. В прочем со скобкой тоже можно затупить:)


      1. unicorn_style
        10.11.2025 14:30

        Почему вы считаете, что ATMC нельзя так же править руками?

        Просто для меня скобки фигурные которые показывают вложенность – не humanlike формат, вот и все

        На мой взгляд его править даже удобнее, чем тот же yml, потому что в nano не видно ни пробелов ни табов и ошибиться с отступом в большом конфиге будет очень просто

        При аварийной правке есть гениально простые решения:

        1. В корне лежит всегда default.yaml/conf как пример

        2. При редактировании конфигурация копируется с приставкой backup

        Это позволяет полностью забыть о спецсиволах даже когда накосячил с ними, все восстанавливается или просто копируется из существующих
        Ну а если прям задача найти проблема: "cat -A файл" отобразит скрытое

        Странно что я это объясняю, будто бы вы не понимаете как реально строится программное обеспечение

        Даже в IDE часто можно затупить с отступом. В прочем со скобкой тоже можно затупить:)

        Возможно "Даже" возникнет в вашем IDE, и тут только совет его поменять. А к примеру в VSCode затупить с yaml конфигурацией - это что-то нереальное. На тему скобок, тут тоже вопросы. На тему скобок тоже не понимаю, не помню вообще когда последний раз скобки ставил клавишей. Конкретный IDE на Golang по первым буквам func/switch+Enter сразу рисует необходимый блок автоматически со всеми скобками и ставит указатель на имя, потом +tab и можно заполнить аргументы...и тд


    1. supermetrolog Автор
      10.11.2025 14:30

      Лично для меня yaml куда более читабелен чем пример который в статье.


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


      1. unicorn_style
        10.11.2025 14:30

        Я рад что есть разработчики которые делают простыни конфигураций, к примеру такие можно найти на mysql и прочий софт. Но там хорошо, настроил один раз и забыл на большой период времени (в большинстве случаев)

        Но если конфиги такие что еще надо постоянно что-то там менят, подкручивать или объединять и это сотнями строк в yaml/conf/ATMC файлах и все это без GUI – то думаю для таких программистов в аду есть отдельный котел

        К слову, мы для своих систем писали раздачу конфигурации с сервера, т.е в приложение вшито или в конфиге адрес API точки доступа куда приложение обращается при запуске и тянет с сервера ту конфигурацию которая актуальна и можно даже пушить настройки + GUI где можно поменять настройки полностью для любого приложения. Когда мы создавали пакеты, ничего подобного и дельного не нашли. Вот таких систем не хватает...PS: Хотя может плохо искали


        1. supermetrolog Автор
          10.11.2025 14:30

          Мне вот интересно, что вы предпримете в таких условиях:
          - вы начинаете новый проект
          - понимаете, что конфигурация для prod и stg будут отличаться
          - например, на prod нужно 10 воркеров для аутбокса, а на stg всего 5, чтобы не ушатать слабые машины на stg

          Как вы поступите тут? Как будете конфигурировать приложение?


          1. unicorn_style
            10.11.2025 14:30

            Этот вопрос почти в вакууме, но у меня есть пример монолитного приложения и которое на 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


        1. supermetrolog Автор
          10.11.2025 14:30

          раздачу конфигурации с сервера

          А на сервере, как оно конфигурировалось? Через UI и в базе лежало?


          1. unicorn_style
            10.11.2025 14:30

            У нас сейчас все хранится в mysql базе, GUI и сервер раздачи написал chatgpt. Нам надо было срочно решение с GUI.
            Пакет тоже написал chatgpt для стыковки. Сейчас стараемся во весь софт сделать это обновление.

            При старте приложения просто ./app --config=имя_приложения

            Он по имени обращается на API вшитый в код и ему отдается JSON готовый из базы. Сделано на коленке, увы пока так и времени доделать нет. Но работает уже год и все довольны. Осталось весь софт перевести на эту историю

            Вообще считаю что mysql это была ошибка, потенциальная точка отказа. Лучше в файлах...

            Вот кстати ваш формат можно было к этому приспособить...т.к вы сами предположили что конфиги могут быть большими...Ну пускай в одном файле будет сразу много конфигураций и при запросе нужный кусок отдается по HTTP

            Основная беда в том что mysql очень плохо переживает сбои если не настроена репликация (пс у нас она не настроена), т.е если что у нас будут веселые ночи. Если бы конфигурация была упакована в единый файл к примеру с вашим форматом...то вопрос бекапа – вопрос простого копирования. И если что-то случилось можно быстро перекинуть бек и загрузить новый экземпляр раздачи.


  1. andrey_27
    10.11.2025 14:30

    Забавно. Упрекать шум, а потом использовать фигурные скобки и кавычки, что и есть самый неприятный шум в конфигах.

    YAML навсегда!


    1. supermetrolog Автор
      10.11.2025 14:30

      Кавычки только для строк

      Скобки позволяют хоть в одну строку писать конфиг

      Причем скобки для массивов в yml тоже есть - можно и без них, если на новой строке писать - ну вот уже несколько способов сделать одно и тоже - не очень нравится

      Ну и плюс скобки более четко визуально группируют данные - ну это ИМХО, конечно


    1. kez
      10.11.2025 14:30

      В ямле no это строка "no" или false? (И там ещё много примеров, можно погуглить по "yaml from hell")

      Уж лучше явные строки чем гадать на кофейной гуще, и вычленять различия версий 1.0, 1.1, 1.2 (речь про ямл спек, конечно же)


  1. Hackitect7
    10.11.2025 14:30

    Ваша статья получилась очень близкой к тому, о чём многие регулярно вздыхают: усталость от бесконечных отступов и кавычек в YAML/JSON и желание наконец-то просто описывать настройки. Идея вынести импорт, слияние и подстановку переменных в отдельный, простой DSL - звучит заманчиво. Примеры синтаксиса понятно читаются, особенно нравятся лаконичные импорты и spread‑оператор.
    Есть, правда, пара вопросов, которые было бы интересно обсудить. Например, как ATMC ведёт себя при конфликте типов при слиянии двух конфигов или что происходит, если ключ встречается в нескольких местах? Планируется ли типовая проверка, чтобы ловить подобные ошибки заранее? Как вы видите дальнейшее развитие проекта: будет ли поддержка других языков помимо Go и есть ли планы на интеграцию с редакторами (подсветка, автодополнение)? Сейчас конфигурационных DSL уже довольно много (HOCON, Dhall, CUE), любопытно было бы увидеть сравнение ATMC с ними.
    В целом же направление классное: хочется, чтобы конфиги были такими же предсказуемыми и приятными, как код.
    Удачи в развитии!


    1. supermetrolog Автор
      10.11.2025 14:30

      как ATMC ведёт себя при конфликте типов при слиянии двух конфигов или что происходит, если ключ встречается в нескольких местах?

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

      Планируется ли типовая проверка, чтобы ловить подобные ошибки заранее?

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

      > Как вы видите дальнейшее развитие проекта: будет ли поддержка других языков помимо Go

      Если язык заимеет хоть какой-нибудь успех на языке Go, то да
      Иначе, кажется, это пустая трата времени

      и есть ли планы на интеграцию с редакторами (подсветка, автодополнение)

      Есть. Использую язык для своих проектов - чувствую, как без хотя бы подсветки жить тяжело (но все равно лучше, чем с json или yml :))

      > любопытно было бы увидеть сравнение ATMC с ними

      Выше тоже это подмечали. А я просто не хотел раздувать статью
      Может быть распишу сравнение позже


  1. SergeyProkhorenko
    10.11.2025 14:30

    Подкину для обсуждения свеженький (но уже 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