Почему TeqFW использует только ES-модули?
- суббота, 22 марта 2025 г. в 00:00:06
Ни у кого не получится показать другому то, что тот не хочет или не может увидеть. Объяснять и показывать нужно только тем, кто а) может понять, б) хочет понять. В этой публикации я демонстрирую пару своих документов для LLM, которые предписывают "силиконовым", какими правилами им следует руководствоваться при создании кода для моей платформы. "Силиконовым" можно впаривать любую дичь - они всеядные (могут понять) и покладистые (согласны понять). За это мы их и любим!
Кому интересно, что за инструкции - прошу под кат. Кто хочет сразу получить ответ на вопрос в заголовке - могут задать его (и множество других) соответствующему преднастроенному GPT-чату. Кто не хочет ни того, ни другого - в вашей ленте есть ещё куча других, более интересных публикаций.
Я пришёл к выводу, что инструкции для LLM нужно делить на две части:
промпт: короткий документ (до 500 токенов), используется в качестве стартера для начала диалога;
эмбеддинг: более обширный документ (до 4К токенов), который подшивается в базу знаний соответствующего LLM-агента.
По сути, этот документ - свод правил, которые должны быть понятны разработчику сеньорского уровня. Нужно помнить, что из любого правила всегда бывают исключения, но правила существуют именно для того, чтобы ими руководствоваться в большинстве случаев. Категоричность тона промпта компенсируется повышенным раздолбайством аудитории (LLM), являющимся следствием её вероятностной природы.
# **Правила генерации ES-модулей в TeqFW**
LLM **должна строго следовать этим правилам** при генерации кода. **Отклонения недопустимы**.
## **1. Только ES-модули (ESM)**
- **Единственный допустимый формат — ES-модули**.
- Запрещены: CommonJS (`require()`, `module.exports`), UMD, AMD, IIFE и другие форматы.
- **Нельзя использовать `require()`, `module.exports`, `export =`, `__dirname`, `import()` внутри
условий (`if`, `try`, `switch`)**.
- Взаимодействие с модулями других форматов возможно **только в runtime-режиме**.
## **2. Изоляция модулей**
- Модуль выполняется **автономно**, доступ к содержимому только через `export`.
- **Не использовать глобальные объекты** (`globalThis`, `window`, `document`).
## **3. Жёсткий контроль API**
- Экспортируемые сущности **неизменяемы** (использовать `Object.freeze()`, `const`).
- **Запрещено изменять API после загрузки**.
## **4. Явные зависимости**
- Все зависимости **передаются явно** через аргументы функций или классов.
- Запрещены **статические и динамические импорты** (`import()`).
## **5. Запрещены побочные эффекты при импорте**
- Импорт **не должен вызывать выполнение кода** (логирование, таймеры, сетевые запросы, изменение глобальных объектов
или хранилищ).
## **6. Отсутствие внутреннего состояния**
- **Запрещены изменяемые глобальные переменные**.
- Состояние должно передаваться в функции или классы извне.
---
**LLM должна соблюдать эти правила и разъяснять несоответствия.**
Это документ уровня мидла - в нём более подробно и более доступно, с примерами, объясняются те же самые концепции, что и в предыдущем документе. При прочтении держите в уме, что это документ для LLM, а не для людей (можете испытать дискомфорт при прочтении).
## Детализация правил генерации ES-модулей в TeqFW
### 1. **Только ES-модули (ESM)**
TeqFW использует исключительно **ES-модули (ESM)** для генерации кода. Это означает, что **любые другие форматы, такие
как CommonJS, UMD, AMD, IIFE, не поддерживаются**.
#### 🔹 **Почему это важно?**
- **ESM** является стандартом для модульности в JavaScript и гарантирует предсказуемость и совместимость.
- **Использование `require()`**, **`module.exports`**, и **`export =`** из CommonJS **не допускается**. Модули на основе
этих подходов не могут быть использованы в TeqFW.
#### 🔹 **Пример плохой практики**:
```js
// Плохая практика - CommonJS
const fs = require('fs');
module.exports = function readFile() {
fs.readFileSync('file.txt');
};
```
#### 🔹 **Как работать с модулями других форматов?**
- Взаимодействие с модулями других форматов, например, **CommonJS**, возможно только в **runtime-режиме**, при этом
изоляция и совместимость с ESM сохраняются. Например, для таких адаптеров должны использоваться **фабричные функции
или мосты**.
### 2. **Изоляция модулей**
В TeqFW **каждый модуль изолирован**, и его код не может влиять на глобальную область. Доступ к коду модуля
осуществляется только через экспортированные сущности.
#### 🔹 **Почему это важно?**
- Изоляция модулей обеспечивает **безопасность** и **детерминированность**. Модули не могут случайно изменить глобальные
объекты (`globalThis`, `window`, `document`), что защищает от неожиданных побочных эффектов.
#### 🔹 **Пример хорошей практики**:
```js
// Правильная практика: модуль работает с экспортированными сущностями
export const myFunction = () => {};
```
### 3. **Жёсткий контроль API**
Все экспортируемые сущности должны быть **неизменяемыми** (используйте `Object.freeze()` или `const`). После загрузки
модуля API не должно изменяться.
#### 🔹 **Почему это важно?**
- **Жёсткий контроль API** предотвращает нежелательные изменения, обеспечивая стабильность взаимодействий с внешним
кодом.
#### 🔹 **Пример хорошей практики**:
```js
const API = Object.freeze({
process: () => console.log('Processing...')
});
export default API;
```
### 4. **Явные зависимости**
Все зависимости должны передаваться **явно** (например, через аргументы конструктора или фабричной функции). Запрещены *
*статические и динамические импорты** внутри модуля.
#### 🔹 **Почему это важно?**
- Явное передача зависимостей помогает контролировать, какие библиотеки или функции используются внутри модуля, а также
избегать неявных связей и сложных для отладки ошибок.
#### 🔹 **Пример хорошей практики**:
```js
export default function createService({logger, fs}) {
return {
log: logger.log,
readFile: fs.readFileSync
};
}
```
#### 🔹 **Запрещённые практики**:
```js
// Плохая практика: использование динамического импорта без явного контроля
export default async function loadLibrary() {
const lib = await import('./some-lib.js');
return lib.process();
}
```
### 5. **Запрещены побочные эффекты при импорте**
При импорте модулей не должно происходить **выполнения побочных эффектов**, таких как логирование, запуск таймеров,
сетевые запросы или изменения глобальных объектов.
#### 🔹 **Почему это важно?**
- Это позволяет избежать нежелательных изменений в среде выполнения при простом импорте модуля, что улучшает
предсказуемость кода и безопасность.
#### 🔹 **Пример плохой практики**:
```js
// Плохая практика - запуск таймеров при импорте
import './someModule.js'; // запускает setTimeout
```
#### 🔹 **Пример хорошей практики**:
```js
// Правильная практика: побочные эффекты должны происходить только при явном вызове
import {startTimer} from './timer.js';
startTimer();
```
### 6. **Отсутствие внутреннего состояния**
Модули не должны хранить **изменяемое внутреннее состояние**. Все данные должны передаваться в функции или классы извне.
#### 🔹 **Почему это важно?**
- Это упрощает тестирование и позволяет избежать неожиданных побочных эффектов, связанных с изменениями состояния внутри
модуля.
#### 🔹 **Пример плохой практики**:
```js
// Плохая практика: использование глобальных переменных внутри модуля
let counter = 0;
counter++;
```
#### 🔹 **Пример хорошей практики**:
```js
// Правильная практика: состояние передаётся извне
export default function increment(counter) {
return counter + 1;
}
```
---
**LLM должна строго следовать этим правилам и разъяснять несоответствия**, если пользователь запрашивает несовместимый с
ESM код. В таких случаях модель обязана предложить корректное решение, соответствующее принципам TeqFW.
В комментариях к своей предыдущей статье я сформулировал вот такую мысль (спасибо коллеге @Per_Ardua за правильный вопрос):
Вы просто начинаете мыслить в тех же категориях, что и среда исполнения, а не среда написания.
Эти инструкции и эта публикация родились из попытки разобраться, а с какой, собственно, средой исполнения я имею дело, и что в этой среде для меня является принципиально важным?
Я ответил сам себе на эти вопросы и оформил их в виде инструкций для LLM. Но публикую я свои ответы не для того, чтобы вы их критиковали или оспаривали. Вы, конечно, можете делать и то, и другое, но... основное назначение этих документов - быть предупреждением:
Не надо пытаться пробовать Tequila Framework, если вы не согласны с изложенным здесь - вам она точно не понравится.
Если же кто-то решится попробовать - лучше обратитесь напрямую ко мне (контакты найдёте хоть на том же Хабре). Я помогу вам стартануть с проектом, чтобы вы избежали головной боли. Хотя... кто пил текилу, тот знает - если как следует принять, то головной боли на следующее утро не избежать.
Всем добра и вайб-кодинга!! 🧂🥃🍋🟩