name: ssl-patterns description: "MUST use WHEN используешь или расширяешь функциональность БСП (Библиотека стандартных подсистем). Provides каталог готовых функций ОбщегоНазначения и правила вызова подсистем без дублирования." uses_capabilities: - get_signature_help alwaysApply: false
Паттерны работы с БСП (Библиотека стандартных подсистем)
Код БСП проверен на миллионах установок, обновляется централизованно, знаком другим разработчикам. Дублирование БСП — антипаттерн.
Сигнатуры функций БСП — через
get_signature_help. У функцийОбщегоНазначенияи прочих модулей БСП много параметров и перегрузок; не угадывайте порядок и состав аргументов. В точке вызоваget_signature_help(uri, line, character)показывает параметры и перегрузки вызываемого метода прямо по месту — без открытия определения модуля БСП. Применяйте при вызове любой функции из каталога ниже, если не уверены в сигнатуре.
Правило 1: Модуль ОбщегоНазначения — основной «швейцарский нож»
Прежде чем писать свою реализацию, проверьте — возможно, в БСП уже есть готовая функция.
| Функция | Когда использовать |
|---|---|
ЗначениеРеквизитаОбъекта() |
Вместо Ссылка.Реквизит (избегаем точечную нотацию) |
ЗначенияРеквизитовОбъекта() |
Несколько реквизитов одним вызовом |
СообщитьПользователю() |
Сообщение с привязкой к полю (вместо Сообщить()) |
МенеджерОбъектаПоСсылке() |
Вместо Выполнить("Справочники." + Имя) |
ПодсистемаСуществует() |
Условный вызов модулей |
ОбщийМодуль() |
Динамический вызов модуля БСП |
ЭтоСсылка() |
Валидация параметров |
СсылкаСуществует() |
Проверка перед обращением |
// ПЛОХО: три обращения к БД через точку
Наименование = КонтрагентСсылка.Наименование;
ИНН = КонтрагентСсылка.ИНН;
Ответственный = КонтрагентСсылка.ОсновнойМенеджер;
// ПРАВИЛЬНО: одно обращение через БСП
РеквизитыКонтрагента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(
КонтрагентСсылка,
"Наименование, ИНН, ОсновнойМенеджер");
Правило 2: СтроковыеФункцииКлиентСервер — работа со строками
Модуль содержит оптимизированные функции, корректно обрабатывающие edge cases.
| Функция | Когда использовать |
|---|---|
ПодставитьПараметрыВСтроку() |
Аналог СтрШаблон(), с дополнительными проверками |
СтрокаСЧисломПредметов() |
Склонение: «5 документов», «1 документ» |
ЕстьНедопустимыеСимволы() |
Валидация ввода |
ТолькоЦифрыВСтроке() |
Валидация ИНН, КПП |
РазложитьСтрокуВМассивПодстрок() |
Парсинг по разделителю |
// Склонение: «1 документ», «2 документа», «5 документов»
ТекстОповещения = СтроковыеФункцииКлиентСервер.СтрокаСЧисломПредметов(
КоличествоДокументов,
НСтр("ru = 'документ, документа, документов'"));
Правило 3: ОбщегоНазначенияКлиентСервер — утилиты для обеих сред
Директива &НаКлиентеНаСервереБезКонтекста — доступен и на клиенте, и на сервере.
| Функция | Описание |
|---|---|
ДополнитьМассив() |
Объединение двух массивов |
ДополнитьСтруктуру() |
Объединение двух структур |
СвойствоСтруктуры() |
Безопасное чтение свойства (значение по умолчанию если нет) |
ПроверитьПараметр() |
Валидация типа с информативной ошибкой |
// Безопасный доступ с значением по умолчанию
ДатаНачала = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
ПараметрыОтчёта, "ДатаНачала", НачалоГода(ТекущаяДатаСеанса()));
Правило 4: Стратегия поиска функций БСП
Алгоритм: LSP -> grep -> AI
- LSP (если доступен):
navigate_symbol("ЗначенияРеквизитовОбъекта") - Поиск по тексту:
grep -r "Функция.*КурсВалюты" src/CommonModules/ - AI-ассистент: «Есть ли в БСП функция для получения курса валюты на дату?»
Когда писать своё vs использовать БСП
| Ситуация | Решение |
|---|---|
| В БСП есть подходящая функция | Используй БСП |
| В БСП есть похожая, но с лишним функционалом | Используй БСП — лишнее не мешает |
| Нужной функции нет в БСП | Пиши своё в стиле БСП |
| Конфигурация без БСП | Пиши своё |
Правило 5: Работа с журналом регистрации через БСП
См. error-handling, правило 7.
Правило 6: РаботаСФайлами — вместо прямого ФайловаяСистема
Прямая работа с файлами не учитывает: права доступа, временные файлы, кросс-платформенность.
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
Попытка
ТабличныйДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.XLSX);
// ... работа с файлом ...
Исключение
// Обработка ошибки
КонецПопытки;
// Явное удаление
УдалитьФайлы(ИмяВременногоФайла);
Правило 7: Типовые паттерны БСП
Проверка заполнения (ОбработкаПроверкиЗаполнения)
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Если НЕ ЗначениеЗаполнено(Контрагент) Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Не заполнен контрагент.'"),
ЭтотОбъект, "Контрагент",, Отказ);
КонецЕсли;
// Условное исключение реквизитов из проверки
Если ВидОперации = Перечисления.ВидыОпераций.Услуга Тогда
ОбщегоНазначенияКлиентСервер.УдалитьЗначениеИзМассива(
ПроверяемыеРеквизиты, "Склад");
КонецЕсли;
КонецПроцедуры
Получение данных для печати
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм,
ОбъектыПечати, ПараметрыВывода) Экспорт
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "Счёт") Тогда
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.КлючПараметровПечати = "Документ.РеализацияТоваровУслуг.Счёт";
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм, "Счёт", НСтр("ru = 'Счёт на оплату'"),
ТабличныйДокумент);
КонецЕсли;
КонецПроцедуры
Правило 8: Не дублируйте функционал БСП
| Что часто пишут сами | Что есть в БСП |
|---|---|
| Получение реквизита по ссылке | ОбщегоНазначения.ЗначениеРеквизитаОбъекта() |
| Подстановка в строку | СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку() |
| Склонение слов | СтроковыеФункцииКлиентСервер.СтрокаСЧисломПредметов() |
| Отправка почты | РаботаСПочтовымиСообщениями |
| Курс валюты | РаботаСКурсамиВалют.ПолучитьКурсВалюты() |
| Длительная операция в фоне | ДлительныеОперации.ВыполнитьФункцию() |
| Хранение секретов / паролей | БезопасноеХранилище.ПрочитатьДанные() |
| Профили прав доступа | ГруппыДоступаПользователей / ПрофилиГруппДоступа |
| Регистрация внешней обработки | СведенияОВнешнейОбработке() |
Правило 9: Модули «КлиентСервер» — разделение ответственности
| Суффикс модуля | Среда | Пример |
|---|---|---|
| (без суффикса) | Сервер | ОбщегоНазначения |
Клиент |
Клиент | ОбщегоНазначенияКлиент |
КлиентСервер |
Обе среды | ОбщегоНазначенияКлиентСервер |
ПовтИсп |
Сервер, с кэшированием | ОбщегоНазначенияПовтИсп |
Для клиентского кода формы — ищите сначала в *КлиентСервер, потом в *Клиент. Для серверного — в основном модуле (без суффикса). *ПовтИсп — для часто запрашиваемых справочных данных.
Правило 10: Длительные операции (ДлительныеОперации)
Используй подсистему ДлительныеОперации для любой серверной работы дольше ~3 сек. Не блокируй UI самодельным циклом ожидания.
// Запуск фоновой задачи
&НаСервере
Функция ЗапуститьОперацию(Параметры)
ПараметрыФона = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ПараметрыФона.НаименованиеФоновогоЗадания = НСтр("ru = 'Обработка данных'");
Возврат ДлительныеОперации.ВыполнитьФункцию("ОбщийМодуль.ФункцияДляФона",
ПараметрыФона, Параметры);
КонецФункции
// Подключение ожидания на клиенте
&НаКлиенте
Процедура ЗапуститьОперациюНаКлиенте()
Операция = ЗапуститьОперацию(ПараметрыРасчёта);
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.ВыводитьПрогресс = Истина;
ДлительныеОперацииКлиент.ОжидатьЗавершение(Операция,
Новый ОписаниеОповещения("ОперацияЗавершена", ЭтотОбъект), ПараметрыОжидания);
КонецПроцедуры
// Обработка результата
&НаКлиенте
Процедура ОперацияЗавершена(Операция, ДополнительныеПараметры) Экспорт
Если Операция = Неопределено Тогда
Возврат; // Отменена пользователем
КонецЕсли;
Если Операция.Статус = "Ошибка" Тогда
СтандартныеПодсистемыКлиент.ОбработатьОшибкуФоновогоЗадания(Операция);
Возврат;
КонецЕсли;
// Получить результат
РезультатОперации = ПолучитьРезультатСервер(Операция.АдресРезультата);
КонецПроцедуры
Ключевые правила:
- Передавай прогресс через
ДлительныеОперации.СообщитьПрогресс()внутри фоновой процедуры. - Не храни состояние между шагами в глобальных переменных — используй параметры задания.
- Реализуй идемпотентный перезапуск: повторный вызов с теми же параметрами должен давать тот же результат.
Правило 11: Безопасное хранилище (БезопасноеХранилище)
Никогда не храни пароли, токены и секреты в:
- реквизитах объектов метаданных
- константах конфигурации
- журнале регистрации
- системе контроля версий (конфиги, xml)
// Запись секрета
БезопасноеХранилище.Записать(ЭтотОбъект, Новый Структура("Пароль", ПарольПользователя));
// Чтение секрета
ДанныеХранилища = БезопасноеХранилище.ПрочитатьДанные(ЭтотОбъект);
Если ДанныеХранилища <> Неопределено Тогда
Пароль = ДанныеХранилища.Пароль;
КонецЕсли;
// Удаление при удалении объекта
БезопасноеХранилище.Удалить(ЭтотОбъект);
В обработчике ПередУдалением объекта всегда вызывай БезопасноеХранилище.Удалить() — иначе «осиротевшие» записи накапливаются в хранилище.
Правило 12: Профили групп доступа (ПрофилиГруппДоступа)
При разработке подсистем с ролевым доступом — используй механизм профилей БСП вместо прямого назначения ролей.
// Пример описания профиля в ОписаниеПрофилейГруппДоступа()
Профиль = УправлениеДоступом.ОписаниеПрофиля();
Профиль.Идентификатор = "ИдентификаторПрофиля_UUID";
Профиль.Наименование = НСтр("ru = 'Менеджер по продажам'");
Профиль.Роли.Добавить("РольМенеджерПродаж");
Профили.Добавить(Профиль);
Ключевые правила:
- Идентификатор профиля — фиксированный UUID, не меняется при переименовании.
- Для повышенных привилегий используй
ПривилегированныйРежим()строго локально, сразу снимай после операции. - Проверку прав выполняй через
УправлениеДоступом.ПроверитьДопустимостьДействия(), не черезРольДоступна()напрямую — последнее не учитывает RLS.
Правило 13: Внешние обработки и расширения (СведенияОВнешнейОбработке)
Регистрация внешней обработки в БСП-базе требует функции СведенияОВнешнейОбработке() в основном модуле обработки.
// В модуле обработки
Функция СведенияОВнешнейОбработке() Экспорт
СведенияОВнешнейОбработке = ДополнительныеОтчётыИОбработки.СведенияОВнешнейОбработке();
СведенияОВнешнейОбработке.Вид = ДополнительныеОтчётыИОбработкиКлиентСервер
.ВидОбработки().ДополнительнаяОбработка;
СведенияОВнешнейОбработке.Наименование = НСтр("ru = 'Моя обработка'");
СведенияОВнешнейОбработке.Версия = "1.0";
СведенияОВнешнейОбработке.БезопасныйРежим = Истина;
// Описание команды
Команда = СведенияОВнешнейОбработке.Команды.Добавить();
Команда.Представление = НСтр("ru = 'Выполнить'");
Команда.Идентификатор = "Выполнить";
Команда.ИспользованиеКонтекста = ДополнительныеОтчётыИОбработкиКлиентСервер
.ИспользованиеКонтекстаКоманды().ВПроцедуреВыполнитьКоманду;
Возврат СведенияОВнешнейОбработке;
КонецФункции
// Точка входа для команды
Процедура ВыполнитьКоманду(Идентификатор, ПараметрыКоманды, ОбъектыНазначения) Экспорт
// ... реализация ...
КонецПроцедуры
Поиск аналогов через Напарника
Если search_ssl_functions не дал результата — ask_ai_assistant (шаблон VALIDATE_BSL из buddy-prompting): передать фрагмент кода, получить рекомендации по замене на методы БСП. Также SEARCH_DOCS для документации по конкретному методу БСП.