Обновить

Программирование как экспериментальная метафизика

Уровень сложностиСложный
Время на прочтение27 мин
Охват и читатели12K
Всего голосов 7: ↑7 и ↓0+10
Комментарии5

Комментарии 5

Сложность: Средний

Спасибо, посмеялся. Я уже на одной четверти текста перестал связывать одно с другим, а для тиктокера это вообще непролазный лес! Но в целом - я в восторге!! Никогда не смотрел на разработку программ в таком ключе. Получилось очень интересно и познавательно (ну, там, где я понял о чём речь, разумеется :))) ).

Попросил ИИшечку привести пост к моему когнитивному уровню - вроде стало чуть полегче. Выкладываю выжимку, может кому сгодится. Там, правда, под меня "заточено", но каждый может перегнать страницу в PDF, скормить "своей" ИИшке и получить трансляцию идей ТС'а "под себя".

Вот "под меня"

Интересная статья, но, на мой взгляд, её ценность не в том, что программирование буквально «доказывает» Платона, Аристотеля или Лейбница. Философские параллели здесь скорее язык, позволяющий разложить архитектурные решения по независимым вопросам.

В упрощённом виде автор предлагает спрашивать о системе следующее:

  1. Где находится общее: в явно объявленном типе, в фактической структуре объекта или только в именах и соглашениях?

  2. Что первично: устойчивый объект с изменяемым состоянием или поток событий, из которого состояние каждый раз выводится?

  3. Кто может менять состояние: любой обладатель ссылки или только сама сущность через обработку сообщений?

  4. Сохраняется ли форма в runtime: может ли система во время исполнения распознать тип, схему и смысл полученного сообщения?

  5. Кто владеет исполнением: внешний поток, единый event loop, coroutine, actor или отдельный процесс?

  6. Где находится цель: только у пользователя либо представлена внутри системы и самостоятельно ею преследуется?

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

Первый: главная проблема конкурентности — сочетание нескольких исполнителей с общим изменяемым состоянием. Лечить её можно в двух независимых направлениях: убрать изменяемость или убрать совместное владение. Отсюда два устойчивых подхода: свободно разделяемые immutable-значения и изолированное mutable-состояние с единственным владельцем.

Второй: у каждого изменяемого состояния должен быть понятный хозяин. Остальные компоненты не должны менять его напрямую — они предъявляют команду или сообщение, а владелец сам решает, как и когда его обработать. Это снижает число возможных комбинаций взаимодействий, хотя оплачивается очередями, сериализацией, задержками и необходимостью согласования.

Третий: интерфейс полезен именно как узкий контракт, а не как способ передавать потомкам кусок готового «бытия». Чем больше состояния и поведения спускается через наследование, тем сильнее связанность и тем сложнее независимо изменять части системы. Поэтому композиция и чистые интерфейсы обычно устойчивее глубоких иерархий классов.

Четвёртый: event sourcing не отменяет объекты, а переносит источник истины. В обычном ООП истина находится в текущем состоянии объекта. В event-sourced-системе — в журнале, а объект становится проекцией истории. Это полезно там, где важны аудит, восстановление, повторная обработка и объяснимость, но не является универсально лучшей моделью.

Пятый: runtime-системе необязательно иметь рефицированные типы самого языка, но ей необходимо какое-то доступное представление протокола — schema, discriminator, валидатор, таблица диспетчеризации или сгенерированный декодер. Замкнутый компонент может самостоятельно интерпретировать сообщение только тогда, когда формат сообщения представлен во время исполнения.

Шестой: автономность исполнения и наличие цели — разные свойства. Actor может иметь собственный цикл обработки и ни к чему не стремиться. Оптимизатор может преследовать цель, оставаясь полностью управляемым внешней петлёй. Для агентных систем это различие принципиально: отдельно должны проектироваться движитель, цель, полномочия и возможность её коррекции.

Наиболее сильной мне кажется последняя часть статьи про LLM-агентов. В обычной системе сообщение и код разделены: данные не должны переписывать поведение обработчика. У языкового агента и инструкции, и данные, и описание цели представлены одним субстратом — текстом. Поэтому message passing сам по себе не обеспечивает изоляции: сообщение может изменить не состояние, а интерпретацию правил и цели.

Практическое следствие — на внутренних границах агентных систем свободный естественный язык, вероятно, должен уступать место более жёстким протоколам:

  • явно заданному типу сообщения;

  • разделению данных, инструкций и системных правил;

  • валидируемому payload;

  • ограниченным capabilities;

  • аудируемому журналу действий;

  • отдельной процедуре изменения цели и полномочий.

Для мультиагентных систем из этого следуют два относительно устойчивых варианта. Либо один большой агент с внутренним разделением ролей, единым контекстом и общей целью. Либо несколько изолированных агентов с явными ролями, полномочиями, аудитом, арбитражем и процедурами согласования. Толпа агентов, свободно общающихся на естественном языке при размытых целях и широких правах, выглядит действительно неустойчивой.

При этом я бы осторожнее относился к сильным тезисам статьи. Аналогия между actor и монадой или между Paxos и предустановленной гармонией красива, но сама по себе ничего не доказывает. Заявленная ортогональность осей тоже не абсолютна: в реальных языках и runtime эти свойства часто сцеплены. А «закон сложности» работает только тогда, когда систему действительно можно разрезать по узким границам. Плохо декомпозированная распределённая система легко оказывается сложнее хорошего модульного монолита.

Поэтому я бы сформулировал практическое ядро статьи так:

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

Для агентных систем к этому добавляется ещё одно требование: изолировать нужно не только память, но также интерпретацию, инструкции, полномочия и цель. Здесь обычной инкапсуляции уже недостаточно — появляются роли, политики, аудит, арбитраж и ответственность.

В любом случае, есть над чем подумать. Спасибо за статью! (y)

Да, практическая выжимка хорошая, спасибо. Сложность поправил таки на "сложную", тут действительно нужна привычка к специфичному философскому языку. Плюс поправил косяки в последней таблице - MD не всегда правильно рендерится.

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

Сделал при помощи codex-агента скилл на основе этой публикации - architecture-foundations. Можно попробовать применить с ИИ-агентом (claude, codex, opencode,...). Установка через npx :

npx skills add flancer32/skill-architecture-foundations --skill architecture-foundations

или вручную, через копирование каталога architecture-foundations в ~/.agents/skills/.

Интересно попробовать описанные в публикации оси для анализа своих проектов.

Похоже, сейчас такой выбор совершается и на уровне всей AI-архитектуры: строим ли мы несколько централизованных систем, принадлежащих корпорациям, или распределённую систему участников. Вот хороший ролик, где эта развилка показана на примере Gonka: https://youtu.be/_uwgrHV_li0?r=1059

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации