framework/skills/bsl-practices/api-design/SKILL.md
Для проектирования и ревью публичного API подсистем 1С
npx skillsauth add steelmorgan/1c-agent-based-dev-framework api-designInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Основано на статье Infostart «База по API»: https://infostart.ru/1c/articles/2683808/.
1С в корпоративных решениях — это модульный монолит: библиотеки состоят из функциональных подсистем, а подсистемы общаются через задекларированные интерфейсы. Произвольный вызов через границы подсистем — это архитектурный дефект, а не удобный приём. Навык учит агента правильно классифицировать экспортные методы, определять допустимость изменений и проектировать API с учётом совместимости.
| Триггер | Действие |
|---------|----------|
| Проектирование нового общего модуля или экспортного метода | Применить классификацию интерфейса (5 категорий), задокументировать контракт |
| Изменение сигнатуры существующего экспортного метода | Проверить обратную совместимость по таблице ниже |
| Добавление параметра в экспортный метод | Определить — обязательный или нет; оценить impact на версию |
| Удаление или переименование экспортного метода | Создать deprecated-обёртку в УстаревшиеПроцедурыИФункции |
| Ревью кода: вызов метода из чужой подсистемы | Проверить категорию вызываемого метода (разрешён ли вызов?) |
| Ревью кода: изменение поведения без смены сигнатуры | Проверить, не нарушает ли это контракт (Программный интерфейс) |
| Вопрос о bump версии при выпуске изменений | Применить правила версионирования (секция «Версионирование») |
Каждый экспортный метод обязан принадлежать ровно одной из 5 категорий. Для категорий 1, 2, 4, 5 категория определяется #Областью модуля, в которой находится метод. Исключение — категория 3: она определяется тем, что метод лежит в переопределяемом модуле (*Переопределяемый), а не отдельным регионом — внутри такого модуля методы находятся в обычной #Область ПрограммныйИнтерфейс.
#Область ПрограммныйИнтерфейсПубличный контракт для внешних потребителей — других библиотек, прикладных решений, интеграций.
#Область ПрограммныйИнтерфейс
// Возвращает курс валюты на указанную дату.
//
// Параметры:
// Валюта - СправочникСсылка.Валюты - валюта, курс которой нужно получить.
// ДатаКурса - Дата - дата, на которую нужен курс.
// Если не указана, используется текущая дата сеанса.
//
// Возвращаемое значение:
// Число - курс валюты. 0 если курс не найден.
//
Функция КурсВалюты(Валюта, ДатаКурса = Неопределено) Экспорт
Возврат РаботаСВалютами.КурсВалюты(Валюта, ДатаКурса);
КонецФункции
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейсКонтракт для вызова из других модулей внутри одной библиотеки (не для внешних потребителей).
#Область СлужебныйПрограммныйИнтерфейс
// Обновляет кэш курсов валют при изменении данных.
// Вызывается только из подписки на событие РаботаСВалютамиОбновлениеКурсов.
//
Процедура ОбновитьКэшКурсовВалют() Экспорт
// ...
КонецПроцедуры
#КонецОбласти
*Переопределяемый)Точка расширения: библиотека вызывает метод потребителя через модуль с суффиксом Переопределяемый (например, РаботаСФайламиПереопределяемый). Региона «ПереопределяемыйИнтерфейс» не существует — «переопределяемость» это свойство самого модуля (его назначение в архитектуре БСП), а не региона внутри него; методы таких модулей находятся в обычной #Область ПрограммныйИнтерфейс.
// Модуль: РаботаСФайламиПереопределяемый
#Область ПрограммныйИнтерфейс
// Определяет настройки хранения присоединённых файлов.
//
// Параметры:
// НастройкиХранения - Структура - настройки, которые нужно заполнить.
//
Процедура ОпределитьНастройкиХраненияФайлов(НастройкиХранения) Экспорт
// Обязательно вызовите Базовую реализацию или заполните структуру самостоятельно.
КонецПроцедуры
#КонецОбласти
#Область ДляВызоваИзДругихПодсистемСтабильная зона интеграции между подсистемами одного решения.
#Область СлужебныеПроцедурыИФункцииВнутренняя реализация одной функциональной подсистемы. Не экспортируются.
Экспорт, либо переместить в нужную категорию.| Изменение | Условие |
|-----------|---------|
| Добавление необязательного параметра | Старые вызовы работают без него |
| Добавление нового метода в ПрограммныйИнтерфейс | Не конфликтует с именами потребителей |
| Изменение реализации без изменения поведения | Контракт не нарушается |
| Исправление ошибки в реализации | Документируется в changelog |
| Изменение | Требование |
|-----------|------------|
| Добавление обязательного параметра | Сохранить старую сигнатуру как deprecated, новый метод — новое имя или overload |
| Удаление метода из ПрограммныйИнтерфейс | Deprecated-обёртка в УстаревшиеПроцедурыИФункции + migration path |
| Переименование метода | Deprecated-обёртка со старым именем |
| Изменение типа параметра (несовместимое) | Deprecated-обёртка, новый параметр — через опциональный или перегрузку |
| Изменение смысла параметра (behavior break) | Новое имя параметра или документирование breaking change |
| Прямой доступ к данным другой подсистемы | Запрещён без явного API |
Требования обратной совместимости перекрывают косметические стандарты. Нельзя переименовать публичный метод «для правильного стиля» без deprecated-обёртки.
При устаревании метода:
#Область УстаревшиеПроцедурыИФункции.// Устарела. Используйте <НовыйМетод>().#Область УстаревшиеПроцедурыИФункции
// Устарела. Используйте КурсВалютыНаДату().
// Будет удалена в версии 4.0.
//
// Параметры:
// Валюта - СправочникСсылка.Валюты
// ДатаКурса - Дата
//
// Возвращаемое значение:
// Число
//
Функция ПолучитьКурсВалюты(Валюта, ДатаКурса) Экспорт
Возврат КурсВалютыНаДату(Валюта, ДатаКурса);
КонецФункции
#КонецОбласти
| Тип изменения | Bump |
|---------------|------|
| Исправление ошибки без изменения поведения API | build (x.x.x.N) |
| Новый необязательный параметр, новый метод в ПИ | minor (x.N.0.0) |
| Breaking change с deprecated-обёрткой | minor + документирование |
| Удаление deprecated-метода, несовместимый тип | major (N.0.0.0) |
Запрещено: вносить расширение публичного API (новые методы, новые параметры) в релиз с bump только по build. Build — только для bug fix.
Используй code-navigation (grep по исходникам) для поиска:
#Область УстаревшиеПроцедурыИФункции — проверить наличие deprecated-обёрток.// Поиск объявления метода
// grep: "Функция КурсВалюты" или "Процедура КурсВалюты"
// Поиск вызовов
// grep: "РаботаСВалютами.КурсВалюты"
// Поиск deprecated-области
// grep: "Устаревшие процедуры и функции"
Определить, к какой категории относится метод, и выбрать из таблицы ниже:
| Тип изменения | Категория метода | Требование |
|---------------|-----------------|------------|
| Новый метод | Любая | Разместить в правильной #Области |
| Новый необязательный параметр | ПрограммныйИнтерфейс | Допустимо, version bump |
| Новый обязательный параметр | ПрограммныйИнтерфейс | Deprecated-обёртка обязательна |
| Удаление метода | ПрограммныйИнтерфейс | Deprecated-обёртка обязательна |
| Изменение поведения | ПрограммныйИнтерфейс | Считается breaking change |
| Любое изменение | СлужебныеПроцедурыИФункции | Свободно (внутри подсистемы) |
| Новый обязательный параметр | Переопределяемые модули (*Переопределяемый) | Запрещено |
syntax-checkingПосле изменения сигнатуры:
Каждый метод из #Область ПрограммныйИнтерфейс — в том числе методы переопределяемых модулей (*Переопределяемый) — должен иметь:
Контекст: developer просит добавить функцию ПолучитьОстатокТоваров() в общий модуль УправлениеЗапасами.
Шаги:
#Область ПрограммныйИнтерфейс.СлужебныеПроцедурыИФункции).Контекст: reviewer получает PR, где у метода РаботаСВалютами.КурсВалюты() добавлен новый обязательный параметр ИсточникКурса.
Шаги:
code-navigation: найти все вызовы РаботаСВалютами.КурсВалюты( — оценить количество потребителей.ПрограммныйИнтерфейс, то breaking change.УстаревшиеПроцедурыИФункции с вызовом нового метода.КурсВалютыИзИсточника) или сделать параметр необязательным.Контекст: architect проектирует новую точку расширения для механизма уведомлений.
Шаги:
ИмяПодсистемыПереопределяемый), в его обычной #Область ПрограммныйИнтерфейс — не в специальном регионе.Контекст: reviewer замечает вызов ЧастнаяПодсистема.ВнутреннийМетод() из чужого модуля.
Шаги:
СлужебныеПроцедурыИФункции — это дефект, зафиксировать в замечании.ДляВызоваИзДругихПодсистем или ПрограммныйИнтерфейс.СлужебныйПрограммныйИнтерфейс и вызов из другой библиотеки — запросить явное соглашение или рефакторинг.| Ошибка | Последствие | Как избежать |
|--------|-------------|--------------|
| Вызов СлужебныеПроцедурыИФункции из другой подсистемы | Хрупкая интеграция, break при рефакторинге | Проверять #Область перед вызовом |
| Добавление обязательного параметра без deprecated-обёртки | Break всех вызовов в CI | Всегда создавать adapter в УстаревшиеПроцедурыИФункции |
| API-расширение в build-only релизе | Нарушение версионирования, путаница у потребителей | Build — только для bug fix |
| Метод переопределяемого модуля (*Переопределяемый) с новым обязательным параметром | Ошибки у всех существующих реализаций | Только необязательные параметры в переопределяемых |
| Изменение смысла параметра без документирования | Молчаливый behavioral break | Документировать в changelog, consider version bump |
| Подавление предупреждений BSL LS без причины | Скрытые breaking changes | Всегда документировать причину подавления |
| Прямой доступ к таблицам данных другой подсистемы | Жёсткая связанность, архитектурный долг | Использовать только задокументированный API |
Перед реализацией нового API:
https://infostart.ru/1c/articles/2683808/depends_on:
development
1C server maintenance webhooks: container restart and external component cache cleanup
development
Interactive DAP debugging of a single BSL procedure
tools
Rules for using RLM tools for project search and navigation in 1C/BSL
development
Creates web applications and routes on Winow (a web server on OneScript and Autumn). Use when working with a web server on OneScript, routing, or Winow controllers.