Меня зовут Алекс Гусев и сегодня я расскажу о том, как 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$', };
Поэтому и вот. Моралей не будет.
Источник


