Понял. Получается, у нас общий Model-first подход, но разная граница исполнения.
У вас RDF/OWL задают более богатую семантическую модель, а SPARQL уже частично используется как язык логики поверх неё.
У меня модель уже: типы, потоки, контракты, связи и транспорт. Зато описанная часть ближе к execution IR: из неё можно воспроизводимо генерировать сервисы для разных runtime, сохраняя одинаковую семантику, но выражая её идиоматично для каждого из них. Бизнес-логика остаётся обычным кодом, потому что на уровне архитектуры мы обычно не опускаемся до деталей её реализации.
То есть у вас модель шире по смыслу, у меня — уже, но ближе к исполнению.
Спасибо, посмотрел — интересно. У нас, похоже, довольно близкая цель, но движение идёт с разных сторон.
У вас получается примерно код → AST → граф → диаграммы/контекст: граф восстанавливается из существующей кодовой базы и становится индексом структуры и зависимостей.
У меня направление скорее обратное: архитектурная модель → граф → сгенерированный код. Существенные связи, типы, потоки и границы сервисов задаются явно до генерации, а реализации бизнес-функций остаются обычным кодом.
Я тоже смотрел в сторону восстановления модели из AST, но пока мне не удавалось достаточно просто извлечь оттуда именно смысловые границы. AST хорошо показывает структуру программы и зависимости, но гораздо сложнее автоматически понять, где находится существенный этап бизнес-процесса, который стоит отдельно выделить на диаграмме как независимый блок, а где просто вспомогательная функция, преобразование данных или техническая обвязка. Формально корректный граф из AST довольно легко получить, а вот сделать его полезным для обсуждения архитектуры — уже заметно сложнее.
Я проводил эксперимент: дал агенту большой проект RTB платформы и попросил построить DSL на питоне. После нескольких уточнений он достаточно хорошо это сделал. Ему хорошо помогал валидатор и то, что можно было сгенерировать проект и скомпилировать его (это добавляло ему понимания). По началу он пошел переносить в граф AST очень подробно. Но потом я ему задал более четкие границы и получилось достаточно не плохо.
RDF/OWL для описания предметной области встречал, но у меня задача немного другая: не построить универсальную онтологию системы, а описать исполняемую топологию — типизированные потоки данных, контракты узлов, связи, транспорт и границы сервисов — так, чтобы из этой модели можно было генерировать рабочий код для разных runtime.
Python здесь скорее язык сборки модели, а не язык самой архитектуры. Получившаяся модель от Python не зависит: сейчас из неё генерируются сервисы на Go, C++, Rust, Python и TypeScript. Поэтому теоретически сверху вполне может появиться и BPMN-подобный редактор, и AI-язык, и вообще другой DSL — если они транслируются в ту же модель.
С UI пока в эту модель не лезу. Мне кажется, там уже появляется другой набор сущностей и семантика взаимодействия, и я бы скорее связывал отдельную UI-модель с моделью сервисов через контракты, чем пытался описывать всё одной онтологией.
На более верхнеуровневые AI/BPMN-языки тоже смотрю с интересом. Я бы только разделял язык, удобный человеку/агенту для описания намерения, и достаточно строгую промежуточную модель, которую уже можно валидировать и из которой можно воспроизводимо генерировать код. У меня Service Architect сейчас как раз скорее про второй слой.
Мы уже проходили похожие переходы: от ассемблера к C, потом к C++, Java, Rust и т.д. Но результат всегда оставался детерминированным — компилятор выполнял строго определённую трансформацию.
С IDD и SDD у меня пока остаётся открытый вопрос. Я пока не видел действительно крупных публичных проектов, где тысячи спецификаций стали бы основным артефактом разработки. Если рядом с кодом появятся десятки тысяч Intent/Spec-файлов, кто гарантирует их непротиворечивость? Кто гарантирует, что архитектурные ограничения не конфликтуют между собой? И кто гарантирует, что они действительно перенесены в код, а не остались только в спецификациях?
Мне кажется, мы действительно будем подниматься на всё более высокий уровень абстракции. Но этот уровень должен быть не просто текстовым описанием, а формальной моделью, которую можно автоматически валидировать, проверять на противоречия и использовать как детерминированную границу ограничений. Иначе мы рискуем не решить проблему, а просто перенести её из кода в ещё один слой артефактов.
Да, абсолютно верно. В некотором смысле так было всегда: либо мы сначала изменяем описание системы и затем приводим реализацию в соответствие с ним, либо меняем код, после чего актуализируем описание.
Полностью устранить эту двойственность, вероятно, невозможно, если описание поведения не является одновременно исполняемой моделью. Но хочется хотя бы сократить объём ручных действий, необходимых для поддержания этих представлений в согласованном состоянии.
При этом дополнительный архитектурный слой полезен ещё до генерации кода. Он выступает валидируемой моделью, на которой архитектор может заранее проверить структуру системы, допустимость связей, контракты взаимодействия и архитектурные ограничения. То есть часть ошибок и противоречий можно обнаружить ещё до появления реализации.
Особенно это важно, если мы движемся в сторону агентной разработки. Хочется не просто передавать агенту репозиторий и надеяться, что он правильно восстановит замысел системы, а явно задавать ему архитектурный контекст, ответственность конкретного узла и ограничения, в пределах которых он должен работать.
Более того, агент может использовать этот слой не только как контекст для изменения кода. Он может предлагать или вносить изменения и в саму архитектуру. Поскольку архитектурная модель формализована и валидируется, такие изменения можно проверить до генерации или модификации реализации.
Таким образом, задача этого слоя — не стать единственным источником истины для всей бизнес-логики, а сделать разработку более контролируемой: уменьшить стоимость синхронизации описания и кода, сузить пространство решений для агента и позволить валидировать архитектурные изменения до того, как они превратятся в код.
В текущей реализации используется двусторонний вариант, и он уже работает для той структуры, которая задаётся фреймворком.
Из графа можно сгенерировать Go-сервис(ы). Если затем разработчик вручную изменит в коде поддерживаемую фреймворком структуру, её можно извлечь обратно и загрузить в дизайнер.
При этом речь не идёт о восстановлении всей программы или произвольной бизнес-логики. Сейчас извлекаются узлы графа, связи между ними, семантика вызовов и частично информация о контрактах. Кастомный код внутри узлов остаётся обычным Go-кодом и обратно в граф не преобразуется.
Причём граф намеренно не опускается до деталей реализации контрактов — например, до конкретного набора полей структуры. Для него важен сам тип контракта и его роль во взаимодействии между узлами. Детальное описание поведения конкретного узла, бизнес-правил и внутренней логики остаётся задачей архитектора. Именно эта информация должна дополнять архитектурный граф и служить исходным контекстом для AI-агента, который затем использует её при реализации конкретной функциональности. Иными словами, граф отвечает на вопрос «как устроена система», а архитектор — «что должен делать каждый узел».
Поэтому это не полный round-trip для Go-кода, а двусторонняя синхронизация той части архитектурной структуры, которая выражена через примитивы фреймворка. Случайные детали реализации при таком извлечении в граф попадать не должны, поскольку анализируется не произвольный код, а только известные фреймворку конструкции.
Информация
В рейтинге
1 097-й
Зарегистрирован
Активность
Специализация
Бэкенд разработчик, Архитектор программного обеспечения
Понял. Получается, у нас общий Model-first подход, но разная граница исполнения.
У вас RDF/OWL задают более богатую семантическую модель, а SPARQL уже частично используется как язык логики поверх неё.
У меня модель уже: типы, потоки, контракты, связи и транспорт. Зато описанная часть ближе к execution IR: из неё можно воспроизводимо генерировать сервисы для разных runtime, сохраняя одинаковую семантику, но выражая её идиоматично для каждого из них. Бизнес-логика остаётся обычным кодом, потому что на уровне архитектуры мы обычно не опускаемся до деталей её реализации.
То есть у вас модель шире по смыслу, у меня — уже, но ближе к исполнению.
Спасибо, посмотрел — интересно. У нас, похоже, довольно близкая цель, но движение идёт с разных сторон.
У вас получается примерно
код → AST → граф → диаграммы/контекст: граф восстанавливается из существующей кодовой базы и становится индексом структуры и зависимостей.У меня направление скорее обратное:
архитектурная модель → граф → сгенерированный код. Существенные связи, типы, потоки и границы сервисов задаются явно до генерации, а реализации бизнес-функций остаются обычным кодом.Я тоже смотрел в сторону восстановления модели из AST, но пока мне не удавалось достаточно просто извлечь оттуда именно смысловые границы. AST хорошо показывает структуру программы и зависимости, но гораздо сложнее автоматически понять, где находится существенный этап бизнес-процесса, который стоит отдельно выделить на диаграмме как независимый блок, а где просто вспомогательная функция, преобразование данных или техническая обвязка. Формально корректный граф из AST довольно легко получить, а вот сделать его полезным для обсуждения архитектуры — уже заметно сложнее.
Я проводил эксперимент: дал агенту большой проект RTB платформы и попросил построить DSL на питоне. После нескольких уточнений он достаточно хорошо это сделал. Ему хорошо помогал валидатор и то, что можно было сгенерировать проект и скомпилировать его (это добавляло ему понимания). По началу он пошел переносить в граф AST очень подробно. Но потом я ему задал более четкие границы и получилось достаточно не плохо.
RDF/OWL для описания предметной области встречал, но у меня задача немного другая: не построить универсальную онтологию системы, а описать исполняемую топологию — типизированные потоки данных, контракты узлов, связи, транспорт и границы сервисов — так, чтобы из этой модели можно было генерировать рабочий код для разных runtime.
Python здесь скорее язык сборки модели, а не язык самой архитектуры. Получившаяся модель от Python не зависит: сейчас из неё генерируются сервисы на Go, C++, Rust, Python и TypeScript. Поэтому теоретически сверху вполне может появиться и BPMN-подобный редактор, и AI-язык, и вообще другой DSL — если они транслируются в ту же модель.
С UI пока в эту модель не лезу. Мне кажется, там уже появляется другой набор сущностей и семантика взаимодействия, и я бы скорее связывал отдельную UI-модель с моделью сервисов через контракты, чем пытался описывать всё одной онтологией.
На более верхнеуровневые AI/BPMN-языки тоже смотрю с интересом. Я бы только разделял язык, удобный человеку/агенту для описания намерения, и достаточно строгую промежуточную модель, которую уже можно валидировать и из которой можно воспроизводимо генерировать код. У меня Service Architect сейчас как раз скорее про второй слой.
Мы уже проходили похожие переходы: от ассемблера к C, потом к C++, Java, Rust и т.д. Но результат всегда оставался детерминированным — компилятор выполнял строго определённую трансформацию.
С IDD и SDD у меня пока остаётся открытый вопрос. Я пока не видел действительно крупных публичных проектов, где тысячи спецификаций стали бы основным артефактом разработки. Если рядом с кодом появятся десятки тысяч Intent/Spec-файлов, кто гарантирует их непротиворечивость? Кто гарантирует, что архитектурные ограничения не конфликтуют между собой? И кто гарантирует, что они действительно перенесены в код, а не остались только в спецификациях?
Мне кажется, мы действительно будем подниматься на всё более высокий уровень абстракции. Но этот уровень должен быть не просто текстовым описанием, а формальной моделью, которую можно автоматически валидировать, проверять на противоречия и использовать как детерминированную границу ограничений. Иначе мы рискуем не решить проблему, а просто перенести её из кода в ещё один слой артефактов.
Да, абсолютно верно. В некотором смысле так было всегда: либо мы сначала изменяем описание системы и затем приводим реализацию в соответствие с ним, либо меняем код, после чего актуализируем описание.
Полностью устранить эту двойственность, вероятно, невозможно, если описание поведения не является одновременно исполняемой моделью. Но хочется хотя бы сократить объём ручных действий, необходимых для поддержания этих представлений в согласованном состоянии.
При этом дополнительный архитектурный слой полезен ещё до генерации кода. Он выступает валидируемой моделью, на которой архитектор может заранее проверить структуру системы, допустимость связей, контракты взаимодействия и архитектурные ограничения. То есть часть ошибок и противоречий можно обнаружить ещё до появления реализации.
Особенно это важно, если мы движемся в сторону агентной разработки. Хочется не просто передавать агенту репозиторий и надеяться, что он правильно восстановит замысел системы, а явно задавать ему архитектурный контекст, ответственность конкретного узла и ограничения, в пределах которых он должен работать.
Более того, агент может использовать этот слой не только как контекст для изменения кода. Он может предлагать или вносить изменения и в саму архитектуру. Поскольку архитектурная модель формализована и валидируется, такие изменения можно проверить до генерации или модификации реализации.
Таким образом, задача этого слоя — не стать единственным источником истины для всей бизнес-логики, а сделать разработку более контролируемой: уменьшить стоимость синхронизации описания и кода, сузить пространство решений для агента и позволить валидировать архитектурные изменения до того, как они превратятся в код.
В текущей реализации используется двусторонний вариант, и он уже работает для той структуры, которая задаётся фреймворком.
Из графа можно сгенерировать Go-сервис(ы). Если затем разработчик вручную изменит в коде поддерживаемую фреймворком структуру, её можно извлечь обратно и загрузить в дизайнер.
При этом речь не идёт о восстановлении всей программы или произвольной бизнес-логики. Сейчас извлекаются узлы графа, связи между ними, семантика вызовов и частично информация о контрактах. Кастомный код внутри узлов остаётся обычным Go-кодом и обратно в граф не преобразуется.
Причём граф намеренно не опускается до деталей реализации контрактов — например, до конкретного набора полей структуры. Для него важен сам тип контракта и его роль во взаимодействии между узлами. Детальное описание поведения конкретного узла, бизнес-правил и внутренней логики остаётся задачей архитектора. Именно эта информация должна дополнять архитектурный граф и служить исходным контекстом для AI-агента, который затем использует её при реализации конкретной функциональности. Иными словами, граф отвечает на вопрос «как устроена система», а архитектор — «что должен делать каждый узел».
Поэтому это не полный round-trip для Go-кода, а двусторонняя синхронизация той части архитектурной структуры, которая выражена через примитивы фреймворка. Случайные детали реализации при таком извлечении в граф попадать не должны, поскольку анализируется не произвольный код, а только известные фреймворку конструкции.