Меня зовут Алекс Гусев и сегодня я расскажу о том, как ChatGPT убедил меня переписать библиотеку @teqfw/di, которую я бережно "выращиваю" с 2019-го года, и почему я всё-таки убедился.
Эта JS-библиотека позволяет мне использовать в своих веб-приложениях позднее связывание и даёт возможность писать изоморфный код, который без изменений работает и в браузере, и на бэке. Без транспиляции исходников, без ручной регистрации зависимостей - так, как я привык делать в Java и PHP. Я почти 7 лет вручную выверял каждую строку этой библиотеки, а на прошлой неделе я отдал её на откуп Codex-агенту и вот что он с ней сделал.

Что было у меня
У меня была библиотека, которая позволяла отказаться от статических импортов в прикладном коде (раннее связывание) и реализовывала принцип Inversion Of Control через внедрение зависимостей в конструктор (позднее связывание). Типовой прикладной код у меня выглядел так:
export default class Namespace_Package_Module_Component { constructor({ Namespace_Package_Module_Dep1: dep1, Namespace_Package_Module_Dep2: dep2, }) { ... } }
Мой контейнер объектов (после конфигурации, разумеется) анализировал ключи объекта, передаваемого в конструктор, и создавал по именам ключей нужные конструктору зависимости (у меня много статей на эту тему, там вся механика описана в деталях).
При необходимости в зависимости можно было добавлять библиотеки самого nodejs или пакетов из ./node_mpdules/ (через префикс node: в имени ключа). В общем, под конец у меня вообще статические импорты были только в composition root (bootstrap) и самой @teqfw/di.
Время перемен
Беда пришла, откуда не ждали - со стороны LLM-агентов. В IT-сфере сложилось публичное представление, что LLM-агенты должны помогать создавать код. Что они натасканы на тоннах примеров и затыкают за пояс не только джунов, но уже и мидлов. Всё, что нужно - нормальные понятные промпты!
Ну, я ж не мог остаться в стороне от такого движа - я попробовал (раз, два, три). Да, действительно - агенты (как минимум, Codex) могут создавать код, если им дать понятные инструкции. Они пишут ужасный (с моей точки зрения) код, но он работает. И главное - они делают это быстро. Очень быстро. Почти так же быстро, как сказать "черничный пирог".
Да, у меня несколько необычный стиль связывания JS-файлов, специфический стиль оформления es6-модулей и применения JSDoc-аннотаций. Но это всё решалось обычной документацией. Агенты - ребята дисциплинированные, кто бы что бы там ни говорил про их стохастическую природу.
Разумеется, я не мог не попробовать поручить агентам разработку самого базового своего пакета - @teqfw/di. И на прошлое неделе я это сделал.
Что стало у агента
Мы с GPT-чатиком всю неделю сидели писали корпус документации согласно моей же методологии ADSM (тоже в моих публикациях есть и про это). Ходили кругами от уровня к уровню, выравнивали описание, терминологию, функционал, архитектуру, соглашения и т.п. Ну, я-то всё и так знал, но нужно было доступно изложить это в виде контекстной документации агентам, которые будут писать код (вернее - переписывать).
С агентами было полное взаимопонимание - под моим чутким давлением до самого момента генерации кода библиотеки. Я решил слегка изменить грамматику кодирования зависимостей, чтобы можно было заставить tsserver в vscode понимать создаваемый код через JSDoc-аннотации. Было там пару неприятных моментов в моей текущей грамматике, что конфликтовали с JSDoc.
Ну я и дал в этом вопросе немного свободы агенту. Агент выдал - отныне ты в прикладном коде будешь описывать зависимости так:
export const __deps__ = { default: { dep1: 'Namespace_Package_Module_Dep1', dep2: 'Namespace_Package_Module_Dep2', }, }; export default class Namespace_Package_Module_Component { constructor({ dep1, dep2 }) { } }
"Ух! - говорю я. - Здорово! А зачем так? Это ж удвоение мест описания зависимостей!! А если ещё и @typedef аннотацию JSDoc добавить - то и утроение!!!"
А он мне и отвечает - "А мне так удобнее! Мне всё равно, одно-два-три места, если по шаблону. Мне ваш DRY до лампочки, особенно если всё в одном файле и ходить никуда не надо."
Ну и начал давить аргументами, типа твой способ сборки зависимостей работает только рекурсивно (а то я не в курсе!), при создании объекта контейнером, а мой (т.е. - его) способ позволяет проанализировать всё дерево зависимостей без создания объектов (ну, аргумент, не спорю).
Резюме
Знаете, что стало железобетонным аргументом со стороны агента? Практика! Мало того, что он за пару подходов соорудил в библиотеке код (ужасный код, повторяю, но - рабочий!), который привносит (уже по его схеме) в JS позднее связывание без транспилции и ручной регистрации зависимостей в контейнере (его контейнере!). Так он ещё за одну итерацию (2-3 минуты) перевёл мой последний проект со старой схемы декларации зависимостей (моей) на новую (свою).
Мы создавали правила разработки ПО для людей, а теперь нужно переписывать эти правила под агентов. А агентам DRY до лампочки, так-то. Им нужна ясность:
export const __deps__ = { configManager: 'Ttp_Back_Configuration_Manager$', storage: 'Ttp_Back_Storage_Repository$', aggregateFactory: 'Ttp_Back_Aggregate_Factory$', telegramReader: 'Ttp_Back_External_TelegramReader$', telegramPublisher: 'Ttp_Back_External_TelegramPublisher$', llmTranslator: 'Ttp_Back_External_LlmTranslator$', promptProvider: 'Ttp_Back_Prompt_Provider$', logger: 'Ttp_Back_Logger$', };
Поэтому и вот. Моралей не будет.
