DI - это про внедрение зависимостей. Зависимости есть в любом коде, состоящем из более, чем одного файла. Статические импорты в JS - это тоже зависимости.
// bootstrap.mjs
import Container from '@teqfw/di';
const container = new Container();
container.addNamespaceRoot(
'App_',
new URL('./src/App/', import.meta.url).href,
'.mjs'
);
const greet = await container.get('App_Greet$');
console.log(greet(' aLEX '));
Вот архив с кодом - достаточно распаковать, затем npm install & npm start.
Если кодовая база большая, то нужен какой-то механизм для связывания отдельных файлов. В JS для этого используют импорты - статические и динамические. DI - это как раз и есть связывание отдельных исходников в единую кодовую базу через динамический импорт. ООП тут вообще перпендикулярно стоит ко всему этому.
DI-контейнер - это никакая не революция. Им сто лет в обед. Я со Spring'ом работал в 2010-х. Это уже была 3-я версия платформы. Затем я использовал DI в PHP - в Magento. Очень своеобразный DI, особенно в первой версии (2008 - 2015 год). Использовал DI из Symfony 2. В PHP вообще с этим делом всё хорошо, даже стандарт есть - PSR-11.
Когда окончательно перешёл в JS даже "запилил" свой DI - чтобы писать в привычной для себя манере. Правда я позволил ИИ его "под себя" переписать (под "силиконовых", а не под "кожаных").
Что касается примеров кода, то могу предложить посмотреть вот этот код - @flancer32/teq-cms. Я писал его "ручками", ещё на "рукописном" DI. А код в @flancer32/teq-web уже написан ИИ (Codex) с "его" DI. Я в код заглядывал, но руками старался не править ничего. Самый, что ни на есть "машинный код".
Рабочий код на фронте - вот. Зайдите в DevTools и посмотрите, что видит браузер:
То же самое, что видит разработчик в IDE
Это старый код, но сделан тоже в той же IoC-парадигме с моим рукописным DI в основе. Для построения UI используется vue и Quasar.
Если вы посмотрите все es6-модули, то там не будет ни одного (!) статического импорта. Статические импорты нужны в головном скрипте для загрузки DI-библиотеки, а дальше контейнер сам динамически (через import()) загружает нужные зависимости по мере необходимости. Как следствие, код становится изоморфным (без изменений может использоваться как в браузере, так и в nodejs). Вот вообще без изменений! Поначалу я на бэке импортировал node'овские библиотеки, но сейчас и они инжектятся. То есть, можно и бэкендовый код в браузере запускать, только node-библиотеки нужно замокать (делается через препроцессор контейнера). А сам код приложения остаётся без изменений.
И в отличие от многих других DI-контейнеров (включая контейнер автора статьи), у моего контейнера ограничена возможность что-то зарегистрировать специально:
const container = new Container()
.registerValue(ID_GENERATOR, randomUUID)
.registerValue(CLOCK, () => new Date())
.registerClass(CartApplicationService);
У меня регистрировать можно только если перевести контейнер в тестовый режим:
То есть, в prod-режиме все es6-модули резолвятся и подгружаются автоматически, сколько бы их там ни было. Нужно только "потянуть" головной модуль, а дальше строится дерево зависимостей и подтягиваются исходники (можно прямо с unpkg.com тянуть). Более того, с учётом наличия в контейнере препроцессора, можно менять маппинг идентификаторов зависимостей на исходный код и реализовывать такие посторонние для "ванильного" JS вещи, как интерфейсы. А с учётом наличия там же постпроцессора, можно использовать в JS и AOP.
Все эти приёмы и технологии давным давно используются в программировании и никакая не революция. Просто они используются там, где кодовая база проекта начинает заваливать за миллионы строк кода (в Magento 2, например, больше 2 млн. и для работы с JS используется requirejs, тоже своего рода DI).
Много у вас примеров таких объёмных кодовых баз именно на JavaScript? А для кодирования на одной веб-страничке чего угодно такие навороты действительно не нужны.
IMHO, всё сильно поменялось, а чувак сделал глобальный вывод на основе своих локальных про... махов - "миддлы не вытаскивают!!".
А может пора уже в новых условиях всю эту "табель о рангах" вместе со сторипоинтами заменить на что-то другое? На те же токены, например, тип модели и уровень reasoning'а? На одной и той же задаче 5.6 Sol на light reasoning даст результат, очень отличающийся от результата 5.6 Luna на high reasoning. И не всегда в лучшую сторону.
Про "сделать видимым контур проверки результата" - мысль дельная. Но об этом писали буквально в первых публичных версиях GPT: "ChatGPT может допускать ошибки. Рекомендуем проверять важную информацию."
В целом - статья годная и полезная. Вопрос - уже половина ответа.
А почему только для Codex? Разве другие агенты не работают с "распределённым AGENTS.md" таким же образом? Лично я в основном работаю именно с Codex'ом. Немного работал с opencode, но там я визуально не контролировал, что агент считывал всю иерархию AGENT.md до целевого каталога (с Codex'ом я это проверял). Думал, что все агенты действуют по такому же принципу - считывают все AGENTS.md от корня проекта и до рабочего каталога. Это не так?
UPDATE:
Проверил opencode. На промпт "Сколько файлов AGENTS.md участвует в формировании инструкций для этого каталога. Перечисли все." Получил такой ответ:
Четыре файла AGENTS.md образуют иерархию инструкций:
/home/alex/work/flancer32/alarisa/AGENTS.md — корневой уровень продукта; предписывает консультироваться с ctx/ и ctx/docs/.
/home/alex/work/flancer32/alarisa/ctx/AGENTS.md — корень когнитивного контекста; направляет читать docs/.
/home/alex/work/flancer32/alarisa/ctx/docs/AGENTS.md — уровень проектной документации; перечисляет product/ как один из разделов.
/home/alex/work/flancer32/alarisa/ctx/docs/product/AGENTS.md — уровень документации продукта; содержит прямые правила для работы с файлами в этом каталоге.
"Этот каталог" бы указан ранее.
Похоже, что opencode тоже видит файлы AGENTS.md в иерархии. Что логично, по такому же принципу работают конфигурационные файлы .htaccess для apache.
UPDATE2:
Это для Copilot'а:
Copilot также перечислил все AGENTS.md, лежащие в иерархии на пути к целевому каталогу. Каждый AGENTS.md содержит инструкции для своего уровня и в совокупности собираются в единый пул инструкций для рабочего каталога.
Вот у меня отдельный AGENTS.md на каждый важный для проекта каталог (112 строк для корневого). Я уже про это писал. Агенты (codex как минимум) читают все AGENTS.md от корня проекта к рабочему (для агента) каталогу. Правила для агентов можно (и нужно!) "размазывать" по всему проекту.
Там один клиент, которому надо открыть в 4 раза больше магазинов за год, чем он это делал вручную. Если клиент способен оплатить 6 месяцев работы команды из 3 человек и кучи агентов, а в ответ получает выполнение своих планов ("закрытие боли"), то... какая там разница что за код нагенерировал компилятор ИИ, если код выполняет свою работу?
Кстати, ИИ вполне себе нормально код генерирует, он архитектуру не держит. А код сгенерирует в любом стиле, особенно если есть скилл под этот стиль.
Продукт ответил на вопрос бизнеса: сказал, где строить, — и клиент пошёл строить.
Это не стартап, а одноразовое приложение, для одного клиента: "Продукт ответил на вопрос бизнеса: сказал, где строить, — и клиент пошёл строить".
Для следующего клиента нужно уже на этих же инструментах и методологии писать другое приложение.
Из очевидного: доработка таких "одноразовых приложений" до новых нужд клиента - довольно дешёвый процесс:
Главное наблюдение: чем больше контекста накапливалось, тем быстрее шла разработка. В какой-то момент стало достаточно сказать «добавь в CRM такую-то сущность» — и агент по накопленным примерам сам создавал таблицу, сервис, контроллеры и фронтенд, и всё это вписывалось в дизайн продукта.
Отсюда вывод - ценность разработки смещается не в код, а в документацию к коду.
С нетерпением жду продолжение про шаринг библиотек и изоляцию зависимостей.
А знаете где эта проблема уже решена на уровне архитектуры? В языке, который не рекомендуют использовать для создания браузерных приложений - в JavaScript.
Да, несколько непонятно, что именно нужно делать в игре. Нужно разбираться методом проб и ошибок. Но в целом - впечатляет (y) Интересно, а насколько долго в неё можно играть? Насколько большая "игровая Вселенная"? Если это "браузерка", то все возможные повороты сценария должны быть предопределены и загружены. Если, в теории, я выполню все квесты, то - всё?
Слоистый AGENTS.md разложен по подпапкам, поэтому в контекст подтягивается ровно то, что относится к текущему модулю, а не вся документация разом.
Я называл такой подход "иерархией AGENTS.md", "слоистый" - интересный подбор терминов. Необычный, как по мне. В любом случае, ваш опыт также подтверждает, что множественное использование AGENTS.md в одном проекте - вполне себе практическое решение. А то мне за ту статью минусов в панамку напихали, типа нейрослоп. Ну, да - нейрослоп. Специально сжатый. Не умеем мы ещё читать нейрослоп. Даже специально сжатый.
Это так, мысли вслух. Удачи в эволюции приложения!
Неудачный пример. Я, например, могу выключить газ с закрытыми глазами. Да и вы тоже. Попробуйте просто. С электроподжигом я могу и включить газ с закрытыми глазами - горящий газ шумит по-другому. Я, когда дома чайник ставлю, никогда специально под него не заглядываю - ни когда включаю, ни когда выключаю. У меня плита с электроподжигом.
Или у вас действительно были случаи, когда вы газ выключили, а он продолжил гореть? Я лично с таким не сталкивался ни разу.
Интересный взгляд. Плюсанул. Мне кажется, что заполнять своё контекстное окно нужно "маловероятным". LLM тяготеют к высоким вероятностям, а низкие вероятности остаются не при делах.
Свершилось то, о чём предупреждал Иоанн Богослов в своих "откровениях":
Но, как ты тепл, а не горяч и не холоден, то извергну тебя из уст Моих.
Это как раз про вероятности. "Кожаным" придётся уходить в сторону отклонений (холоден или горяч), т.к. срединная ниша (тёплый) теперь занята "силиконовыми".
Это, разумеется, шутка, но в каждой шутке есть только доля шутки. IMHO, творческая составляющая развития (эволюция) - за человеком, стабилизирующая (удерживающая) - за ИИ.
Ключевая проблема в том, что при разработке приложений вы "думаете" не на том языке, на котором "думает" компьютер при их выполнении.
В природе существуют транспиляторы в JavaScript, как минимум, для следующих языков: CoffeeScript, Dart, Kotlin, Scala, F#, Clojure, Elm, PureScript, Haxe, Go, Java, Python, Ruby, ...
Простую "программу для браузера" можно написать на любом из этих языков, но её придётся транспилировать в JS (или WASM) - браузеры просто не понимают ничего, кроме JavaScript и WASM (но WASM уже плохо понимает человек).
Каждый из перечисленных выше языков обладает какими-то преимуществами и какими-то недостатками, вытекающими из преимуществ. При транспиляции из одного языка в другой недостатки каждого языка суммируются, а преимущества исходного языка просто теряются.
Так вот, чем TypeScript кардинально лучше любого из этих языков? Тем, что похож на JavaScript больше любого другого? Больше любого другого на JS похож сам JS - в нём недостатки только его самого, которые хоть как-то компенсируются его достоинствами.
TS можно и нужно было использовать вместо JS до появления ES6 - c 2012 по 2015 год. А потом качественная разница между ними лишь уменьшалась.
Если вам удобно кодировать "программы для браузера" на TypeScript - пожалуйста, кодируйте на TypeScript. Другим удобно это делать на других языках (я перечислил только часть). Браузер всё равно понимает лишь JavaScript и WASM.
Когда я пишу "программы для браузера", я предпочитаю делать это на максимально близком ему языке, чтобы не привносить в runtime недостатки других ЯП. Только и всего.
А вы-то сами можете "детерминированно генерировать код"? Не на уровне "Hello, World!" или "ToDo List", а на уровне приложения хотя бы на пару тысяч LOC? Каковы ваши собственные пределы детерминированности?
Я когда-то, в первой половине 90-х, изучал ассемблер и писал на нём работающие программы. Не то, чтобы я читал с листа машкоды, но разбирался с помощью справочника, что именно там написано. А потом мне как-то стало плевать на сохранность этого навыка и я ушёл в сторону ЯП высокого уровня - сначала C/Pascal, потом C++, потом Java, а потом вообще PHP и JS.
Буквально вчера вечером я попросил агента исправить одноразовое приложение на JS, которое такой же агент создавал 10 месяцев назад для мониторинга сайта объявлений и которое проработало несколько недель, пока не перестало быть нужным. Теперь надо было мониторить другую категорию объявлений с другой структурой. В этом приложении есть веб-сервер для регистрации пользователей на получение push-уведомлений и сервис, который опрашивает сервер объявлений на предмет появления новых, после чего отправляет push-уведомление всем зарегистрированным пользователям. Я ж говорю, чисто одноразовое приложение под текущую задачу.
Так вот, я полез читать код, который там нагенерён - не помню я через 10 месяцев, что там вообще. Потом плюнул и просто спросил агента - что это и как оно работает. Через минут 5 у меня в памяти была восстановлена картина в общих чертах. Ещё минут 10 мы с агентом переключались на новую категорию объявлений и обновляли библиотеки, после чего я минут 20 восстанавливал окружение, которое я снёс за ненадобностью - веб-сервер, DNS, systemd, ... Сейчас это приложение уже крутится и мониторит новую категорию.
В код я так больше и не заглядывал. Не пригодилось.
Я в курсе, что не во всех сферах человеческой деятельности такой подход применим. Я даже могу согласиться, что во многих сферах традиционного программирования такой подход не применим. Но такой подход открывает ниши, где неприменим уже традиционный подход "с чтением кода и написанием его вручную".
Кстати, буквально вчера стучал рекрутёр с вопросом, а могу ли я всё ещё работать с Lotus Notes? А я уже лет 15-20, как с ним не работаю никак. Не сохранил я этот навык, как и множество других, когда-то полезных - умение администрировать машины с MS-DOS и Windows for Workgroups, NT4, XP, Win2K, OS/2 Warp, Novell Netware, Solaris, Slackware, RedHat/Fedora, писать проги под MS Office и Lotus Notes/Domino, сервлеты под Tomcat, утратил навыки программирования портлетов для Liferay и их интеграции с Intalio BPMS, я больше не программирую на Clarion / C / LotusScript / VisualBasic / Java и почти уже не программирую на PHP и начал забывать Magento. У меня много утраченных навыков и много приобретённых. Одним больше, одним меньше...
Да, у вас такая сфера деятельности, где нужны работающие и проверенные практикой подходы. Вангую, что к вам ИИ-кодинг придёт позже других и в уже достаточно стабильном виде :) Ну а эксперименты с ИИ будут проводиться в других сферах.
То что работает у вас, не факт что сработает в другой сфере, не только моей.
Ладно, давайте расширять. Вот JS-код. Во всех исходниках всего пакета (./src/) нет ни одного статического import'а. А там порядка 20 файлов. Тем не менее, пакет рабочий и используется в составе других пакетов (например, github-flows-app).
Это называется "late binding". В таком виде (без статических импортов) JS-код становится изоморфным - может работать и в браузере, и на бэке без изменений. Юнит-тестирование такого кода становится детской игрой, так как можно подменить моком любую зависимость, вплоть до node-библиотек.
Этот подход пришёл из того самого "энтерпрайза", который вы пренебрежительно называете "Ынтырпрайз". В кодовой базе Magento Open Source 2.4.x свыше 2 млн. строк на PHP, а ещё под 0.5 млн - на JavaScript (не TypeScript!). В базовом наборе платформы порядка 200+ модулей, а сторонние разработчик дают возможность доставить в базу ещё свыше 2К модулей и одному Богу известно, сколько там строк кода. И весь этот "зоопарк" способен крутиться согласованно и на фронте, и на бэке, благодаря технологиям "Ынтырпрайза", в том числе и позднему связыванию.
И тот же WebStorm использует TypeScript Language Server для валидации типов
WebStorm появился в 2010 году - за два года до TypeScript'а. В нём есть отдельно настройки для JavaScript и для TypeScript. Да, для валидации типов в TypeScript IDEA может использовать TS Language Server. Но его можно отключить и писать на чистом JS.
В IDEA JS можно использовать без TS
Это означает: больший размер бандла (нет минификации и удаления неиспользуемого кода),
Минификации JSDoc не мешает - можно выкинуть все JSDoc'и и код остаётся рабочим. А неиспользуемого кода здесь нет в принципе - связывание идёт в runtime.
Да, для TS есть своя ниша - "галеры". Создаётся ощущение контроля за ситуацией. Типа, мы "натянули типы" на JS. Но - нет, не натянули. Их там как не было, та и нет. Откройте DevTools в браузере по F12 и убедитесь сами. Типы есть только в вашем IDE и лишь до транспиляции.
Я пять лет назад уже публично пояснил, почему я предпочитаю JS. С тех пор не особо что изменилось. Вернее, поводов использовать TS становится всё меньше. А ИИ-агенты - так это вообще повод TS не использовать. Им-то зачем лишний раз код транспилить при рефакторинге? Экономия токенов идёт от понимания моделью контекста задачи, а не от количества символов, и JSDoc здесь как раз к месту.
DI - это про внедрение зависимостей. Зависимости есть в любом коде, состоящем из более, чем одного файла. Статические импорты в JS - это тоже зависимости.
DI в JS можно вообще без классов использовать:
Вот архив с кодом - достаточно распаковать, затем
npm install&npm start.Если кодовая база большая, то нужен какой-то механизм для связывания отдельных файлов. В JS для этого используют импорты - статические и динамические. DI - это как раз и есть связывание отдельных исходников в единую кодовую базу через динамический импорт. ООП тут вообще перпендикулярно стоит ко всему этому.
DI-контейнер - это никакая не революция. Им сто лет в обед. Я со Spring'ом работал в 2010-х. Это уже была 3-я версия платформы. Затем я использовал DI в PHP - в Magento. Очень своеобразный DI, особенно в первой версии (2008 - 2015 год). Использовал DI из Symfony 2. В PHP вообще с этим делом всё хорошо, даже стандарт есть - PSR-11.
Когда окончательно перешёл в JS даже "запилил" свой DI - чтобы писать в привычной для себя манере. Правда я позволил ИИ его "под себя" переписать (под "силиконовых", а не под "кожаных").
Что касается примеров кода, то могу предложить посмотреть вот этот код - @flancer32/teq-cms. Я писал его "ручками", ещё на "рукописном" DI. А код в @flancer32/teq-web уже написан ИИ (Codex) с "его" DI. Я в код заглядывал, но руками старался не править ничего. Самый, что ни на есть "машинный код".
Рабочий код на фронте - вот. Зайдите в DevTools и посмотрите, что видит браузер:
Это старый код, но сделан тоже в той же IoC-парадигме с моим рукописным DI в основе. Для построения UI используется vue и Quasar.
Если вы посмотрите все es6-модули, то там не будет ни одного (!) статического импорта. Статические импорты нужны в головном скрипте для загрузки DI-библиотеки, а дальше контейнер сам динамически (через
import()) загружает нужные зависимости по мере необходимости. Как следствие, код становится изоморфным (без изменений может использоваться как в браузере, так и в nodejs). Вот вообще без изменений! Поначалу я на бэке импортировал node'овские библиотеки, но сейчас и они инжектятся. То есть, можно и бэкендовый код в браузере запускать, только node-библиотеки нужно замокать (делается через препроцессор контейнера). А сам код приложения остаётся без изменений.И в отличие от многих других DI-контейнеров (включая контейнер автора статьи), у моего контейнера ограничена возможность что-то зарегистрировать специально:
У меня регистрировать можно только если перевести контейнер в тестовый режим:
То есть, в prod-режиме все es6-модули резолвятся и подгружаются автоматически, сколько бы их там ни было. Нужно только "потянуть" головной модуль, а дальше строится дерево зависимостей и подтягиваются исходники (можно прямо с unpkg.com тянуть). Более того, с учётом наличия в контейнере препроцессора, можно менять маппинг идентификаторов зависимостей на исходный код и реализовывать такие посторонние для "ванильного" JS вещи, как интерфейсы. А с учётом наличия там же постпроцессора, можно использовать в JS и AOP.
Все эти приёмы и технологии давным давно используются в программировании и никакая не революция. Просто они используются там, где кодовая база проекта начинает заваливать за миллионы строк кода (в Magento 2, например, больше 2 млн. и для работы с JS используется requirejs, тоже своего рода DI).
Много у вас примеров таких объёмных кодовых баз именно на JavaScript? А для кодирования на одной веб-страничке чего угодно такие навороты действительно не нужны.
IMHO, всё сильно поменялось, а чувак сделал глобальный вывод на основе своих локальных про... махов - "миддлы не вытаскивают!!".
А может пора уже в новых условиях всю эту "табель о рангах" вместе со сторипоинтами заменить на что-то другое? На те же токены, например, тип модели и уровень reasoning'а? На одной и той же задаче 5.6 Sol на light reasoning даст результат, очень отличающийся от результата 5.6 Luna на high reasoning. И не всегда в лучшую сторону.
Про "сделать видимым контур проверки результата" - мысль дельная. Но об этом писали буквально в первых публичных версиях GPT: "ChatGPT может допускать ошибки. Рекомендуем проверять важную информацию."
В целом - статья годная и полезная. Вопрос - уже половина ответа.
А почему только для Codex? Разве другие агенты не работают с "распределённым AGENTS.md" таким же образом? Лично я в основном работаю именно с Codex'ом. Немного работал с opencode, но там я визуально не контролировал, что агент считывал всю иерархию AGENT.md до целевого каталога (с Codex'ом я это проверял). Думал, что все агенты действуют по такому же принципу - считывают все AGENTS.md от корня проекта и до рабочего каталога. Это не так?
UPDATE:
Проверил opencode. На промпт "Сколько файлов AGENTS.md участвует в формировании инструкций для этого каталога. Перечисли все." Получил такой ответ:
"Этот каталог" бы указан ранее.
Похоже, что opencode тоже видит файлы AGENTS.md в иерархии. Что логично, по такому же принципу работают конфигурационные файлы
.htaccessдля apache.UPDATE2:
Это для Copilot'а:
Copilot также перечислил все AGENTS.md, лежащие в иерархии на пути к целевому каталогу. Каждый AGENTS.md содержит инструкции для своего уровня и в совокупности собираются в единый пул инструкций для рабочего каталога.
Вот у меня отдельный AGENTS.md на каждый важный для проекта каталог (112 строк для корневого). Я уже про это писал. Агенты (codex как минимум) читают все AGENTS.md от корня проекта к рабочему (для агента) каталогу. Правила для агентов можно (и нужно!) "размазывать" по всему проекту.
Я откушал полной ложкой то, что вы называете "their own medicine". А вот вы в это время "ели" что-то другое.
"Мы есть то, что мы едим." (с)
А так всё верно. Самый надёжный способ проверить, что человек умеет плавать - бросить его в воду. Все, кто выплыл - 100% умеют.
Какая "сотня активных пользователей"?!
Там один клиент, которому надо открыть в 4 раза больше магазинов за год, чем он это делал вручную. Если клиент способен оплатить 6 месяцев работы команды из 3 человек и кучи агентов, а в ответ получает выполнение своих планов ("закрытие боли"), то... какая там разница что за код нагенерировал
компиляторИИ, если код выполняет свою работу?Кстати, ИИ вполне себе нормально код генерирует, он архитектуру не держит. А код сгенерирует в любом стиле, особенно если есть скилл под этот стиль.
Это не стартап, а одноразовое приложение, для одного клиента: "Продукт ответил на вопрос бизнеса: сказал, где строить, — и клиент пошёл строить".
Для следующего клиента нужно уже на этих же инструментах и методологии писать другое приложение.
Из очевидного: доработка таких "одноразовых приложений" до новых нужд клиента - довольно дешёвый процесс:
Отсюда вывод - ценность разработки смещается не в код, а в документацию к коду.
А знаете где эта проблема уже решена на уровне архитектуры? В языке, который не рекомендуют использовать для создания браузерных приложений - в JavaScript.
Чистейший late binding! Приятно видеть, что технологии "кровавого энтерпрайза" прорастают в браузерных приложениях.
Да, несколько непонятно, что именно нужно делать в игре. Нужно разбираться методом проб и ошибок. Но в целом - впечатляет (y) Интересно, а насколько долго в неё можно играть? Насколько большая "игровая Вселенная"? Если это "браузерка", то все возможные повороты сценария должны быть предопределены и загружены. Если, в теории, я выполню все квесты, то - всё?
Я называл такой подход "иерархией AGENTS.md", "слоистый" - интересный подбор терминов. Необычный, как по мне. В любом случае, ваш опыт также подтверждает, что множественное использование AGENTS.md в одном проекте - вполне себе практическое решение. А то мне за ту статью минусов в панамку напихали, типа нейрослоп. Ну, да - нейрослоп. Специально сжатый. Не умеем мы ещё читать нейрослоп. Даже специально сжатый.
Это так, мысли вслух. Удачи в эволюции приложения!
Неудачный пример. Я, например, могу выключить газ с закрытыми глазами. Да и вы тоже. Попробуйте просто. С электроподжигом я могу и включить газ с закрытыми глазами - горящий газ шумит по-другому. Я, когда дома чайник ставлю, никогда специально под него не заглядываю - ни когда включаю, ни когда выключаю. У меня плита с электроподжигом.
Или у вас действительно были случаи, когда вы газ выключили, а он продолжил гореть? Я лично с таким не сталкивался ни разу.
А вы правда верите, что качество кода зависит от того, что на него кто-то посмотрел?
Интересный взгляд. Плюсанул. Мне кажется, что заполнять своё контекстное окно нужно "маловероятным". LLM тяготеют к высоким вероятностям, а низкие вероятности остаются не при делах.
Свершилось то, о чём предупреждал Иоанн Богослов в своих "откровениях":
Это как раз про вероятности. "Кожаным" придётся уходить в сторону отклонений (холоден или горяч), т.к. срединная ниша (тёплый) теперь занята "силиконовыми".
Это, разумеется, шутка, но в каждой шутке есть только доля шутки. IMHO, творческая составляющая развития (эволюция) - за человеком, стабилизирующая (удерживающая) - за ИИ.
Ключевая проблема в том, что при разработке приложений вы "думаете" не на том языке, на котором "думает" компьютер при их выполнении.
В природе существуют транспиляторы в JavaScript, как минимум, для следующих языков: CoffeeScript, Dart, Kotlin, Scala, F#, Clojure, Elm, PureScript, Haxe, Go, Java, Python, Ruby, ...
Простую "программу для браузера" можно написать на любом из этих языков, но её придётся транспилировать в JS (или WASM) - браузеры просто не понимают ничего, кроме JavaScript и WASM (но WASM уже плохо понимает человек).
Каждый из перечисленных выше языков обладает какими-то преимуществами и какими-то недостатками, вытекающими из преимуществ. При транспиляции из одного языка в другой недостатки каждого языка суммируются, а преимущества исходного языка просто теряются.
Так вот, чем TypeScript кардинально лучше любого из этих языков? Тем, что похож на JavaScript больше любого другого? Больше любого другого на JS похож сам JS - в нём недостатки только его самого, которые хоть как-то компенсируются его достоинствами.
TS можно и нужно было использовать вместо JS до появления ES6 - c 2012 по 2015 год. А потом качественная разница между ними лишь уменьшалась.
Если вам удобно кодировать "программы для браузера" на TypeScript - пожалуйста, кодируйте на TypeScript. Другим удобно это делать на других языках (я перечислил только часть). Браузер всё равно понимает лишь JavaScript и WASM.
Когда я пишу "программы для браузера", я предпочитаю делать это на максимально близком ему языке, чтобы не привносить в runtime недостатки других ЯП. Только и всего.
А вы-то сами можете "детерминированно генерировать код"? Не на уровне "Hello, World!" или "ToDo List", а на уровне приложения хотя бы на пару тысяч LOC? Каковы ваши собственные пределы детерминированности?
Я когда-то, в первой половине 90-х, изучал ассемблер и писал на нём работающие программы. Не то, чтобы я читал с листа машкоды, но разбирался с помощью справочника, что именно там написано. А потом мне как-то стало плевать на сохранность этого навыка и я ушёл в сторону ЯП высокого уровня - сначала C/Pascal, потом C++, потом Java, а потом вообще PHP и JS.
Буквально вчера вечером я попросил агента исправить одноразовое приложение на JS, которое такой же агент создавал 10 месяцев назад для мониторинга сайта объявлений и которое проработало несколько недель, пока не перестало быть нужным. Теперь надо было мониторить другую категорию объявлений с другой структурой. В этом приложении есть веб-сервер для регистрации пользователей на получение push-уведомлений и сервис, который опрашивает сервер объявлений на предмет появления новых, после чего отправляет push-уведомление всем зарегистрированным пользователям. Я ж говорю, чисто одноразовое приложение под текущую задачу.
Так вот, я полез читать код, который там нагенерён - не помню я через 10 месяцев, что там вообще. Потом плюнул и просто спросил агента - что это и как оно работает. Через минут 5 у меня в памяти была восстановлена картина в общих чертах. Ещё минут 10 мы с агентом переключались на новую категорию объявлений и обновляли библиотеки, после чего я минут 20 восстанавливал окружение, которое я снёс за ненадобностью - веб-сервер, DNS, systemd, ... Сейчас это приложение уже крутится и мониторит новую категорию.
В код я так больше и не заглядывал. Не пригодилось.
Я в курсе, что не во всех сферах человеческой деятельности такой подход применим. Я даже могу согласиться, что во многих сферах традиционного программирования такой подход не применим. Но такой подход открывает ниши, где неприменим уже традиционный подход "с чтением кода и написанием его вручную".
Кстати, буквально вчера стучал рекрутёр с вопросом, а могу ли я всё ещё работать с Lotus Notes? А я уже лет 15-20, как с ним не работаю никак. Не сохранил я этот навык, как и множество других, когда-то полезных - умение администрировать машины с MS-DOS и Windows for Workgroups, NT4, XP, Win2K, OS/2 Warp, Novell Netware, Solaris, Slackware, RedHat/Fedora, писать проги под MS Office и Lotus Notes/Domino, сервлеты под Tomcat, утратил навыки программирования портлетов для Liferay и их интеграции с Intalio BPMS, я больше не программирую на Clarion / C / LotusScript / VisualBasic / Java и почти уже не программирую на PHP и начал забывать Magento. У меня много утраченных навыков и много приобретённых. Одним больше, одним меньше...
Да, у вас такая сфера деятельности, где нужны работающие и проверенные практикой подходы. Вангую, что к вам ИИ-кодинг придёт позже других и в уже достаточно стабильном виде :) Ну а эксперименты с ИИ будут проводиться в других сферах.
Полностью согласен.
Ладно, давайте расширять. Вот JS-код. Во всех исходниках всего пакета (./src/) нет ни одного статического import'а. А там порядка 20 файлов. Тем не менее, пакет рабочий и используется в составе других пакетов (например, github-flows-app).
Это называется "late binding". В таком виде (без статических импортов) JS-код становится изоморфным - может работать и в браузере, и на бэке без изменений. Юнит-тестирование такого кода становится детской игрой, так как можно подменить моком любую зависимость, вплоть до node-библиотек.
Этот подход пришёл из того самого "энтерпрайза", который вы пренебрежительно называете "Ынтырпрайз". В кодовой базе Magento Open Source 2.4.x свыше 2 млн. строк на PHP, а ещё под 0.5 млн - на JavaScript (не TypeScript!). В базовом наборе платформы порядка 200+ модулей, а сторонние разработчик дают возможность доставить в базу ещё свыше 2К модулей и одному Богу известно, сколько там строк кода. И весь этот "зоопарк" способен крутиться согласованно и на фронте, и на бэке, благодаря технологиям "Ынтырпрайза", в том числе и позднему связыванию.
WebStorm появился в 2010 году - за два года до TypeScript'а. В нём есть отдельно настройки для JavaScript и для TypeScript. Да, для валидации типов в TypeScript IDEA может использовать TS Language Server. Но его можно отключить и писать на чистом JS.
Минификации JSDoc не мешает - можно выкинуть все JSDoc'и и код остаётся рабочим. А неиспользуемого кода здесь нет в принципе - связывание идёт в runtime.
Да, для TS есть своя ниша - "галеры". Создаётся ощущение контроля за ситуацией. Типа, мы "натянули типы" на JS. Но - нет, не натянули. Их там как не было, та и нет. Откройте DevTools в браузере по F12 и убедитесь сами. Типы есть только в вашем IDE и лишь до транспиляции.
Я пять лет назад уже публично пояснил, почему я предпочитаю JS. С тех пор не особо что изменилось. Вернее, поводов использовать TS становится всё меньше. А ИИ-агенты - так это вообще повод TS не использовать. Им-то зачем лишний раз код транспилить при рефакторинге? Экономия токенов идёт от понимания моделью контекста задачи, а не от количества символов, и JSDoc здесь как раз к месту.
JSDoc появился в 1999-м, TS - в 2012-м.
Не вижу смысла дискутировать. У нас с вами очень разные картины мира. Мне будет неуютно в вашей, а вам - в моей. Останемся при своих.