Стандарты кодирования 1С (в терминологии фирмы «1С» — стандарты разработки) — это набор правил фирмы «1С» о том, где размещать код, как структурировать модули, называть переменные и функции, описывать параметры и оформлять текст. Они опубликованы на ИТС в разделе «Система стандартов и методик разработки конфигураций» и открыты без подписки. Типовые конфигурации написаны по этим правилам, поэтому код, который им следует, проще читать, дорабатывать и проверять автоматически.

Прочитать стандарты один раз недостаточно: у каждого разработчика есть привычки, и переучиваться приходится осознанно. Ниже — памятка из правил, которые на моих код-ревью всплывают чаще всего. Это не замена первоисточнику, а способ быстро освежить главное.

Зачем соблюдать стандарты кодирования 1С

Стандарт — не про красоту, а про скорость изменений. Когда вся команда пишет одинаково:

  • быстрее находится место, где нужно внести правку;
  • проще понять, как работает чужой код;
  • быстрее находится ошибка;
  • безопаснее дорабатывать — меньше неожиданных побочных эффектов.

Часть стандартов прямо защищает от ошибок: запрет вызывать служебные методы чужих подсистем, требование ветки Иначе, предварительная инициализация переменных. Дополнительно их можно контролировать автоматически — об этом в конце статьи.

В каком модуле размещать код

Стандарты разработки 1С: выбор модуля для размещения кода
Стандарты разработки 1С: выбор модуля для размещения кода

С модулем приложения, сеанса, внешнего соединения, HTTP- и веб-сервисов, команд и менеджеров значений вопросов обычно нет — у них конкретное назначение. Сомнения возникают между четырьмя видами: модуль объекта, модуль менеджера, общий модуль и модуль формы.

МодульЧто размещатьЧего избегать
Модуль объектаОбработчики событий объекта (ПередЗаписью, ОбработкаПроведения), заполнение экземпляра, работа с ЭтотОбъект до записиЭкспортных методов, которые зовут снаружи: для вызова придётся делать ПолучитьОбъект() и читать объект целиком
Модуль менеджера«Статика» объекта: печать, движения по ссылке, общие для всех экземпляров данные, обработчики обновленияЛогики, требующей экземпляра объекта
Общий модульФункциональность, которую нельзя однозначно отнести к одному объекту метаданныхСвалки «всего подряд» без деления по назначению
Модуль формыТолько код конкретной формы: обработчики элементов и командБизнес-логики — она должна работать без открытия формы

Простой тест: если логику нужно выполнить из обработки, фонового задания или обмена — ей не место в форме. Если для неё нужен только идентификатор объекта — это модуль менеджера. Если она касается нескольких объектов — общий модуль.

Структура модуля: области

Код модуля раскладывается по областям #Область ... #КонецОбласти. Набор зависит от вида модуля; чаще всего встречаются:

  • ПрограммныйИнтерфейс — экспортные методы для других объектов и подсистем;
  • СлужебныйПрограммныйИнтерфейс — экспортные методы, которые разрешено вызывать только из той же библиотеки или подсистемы;
  • СлужебныеПроцедурыИФункции — внутренняя реализация;
  • ОбработчикиСобытий — события модуля объекта;
  • ОбработчикиСобытийФормы, ОбработчикиСобытийЭлементовШапкиФормы, ОбработчикиСобытийЭлементовТаблицыФормы<Имя>, ОбработчикиКомандФормы — для модулей форм.
1С
#Область ПрограммныйИнтерфейс

// Возвращает остаток товара на складе на текущую дату.
Функция ОстатокТовара(Номенклатура, Склад) Экспорт
	// ...
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция ТекстЗапросаОстатков()
	// ...
КонецФункции

#КонецОбласти

Правила, которые часто нарушают:

  • Не вызывайте чужие служебные методы. Если метод лежит в служебной области или в модуле со словом «Служебный» в имени и написан не вами, разработчик библиотеки не гарантирует его сохранность: в следующей версии он может исчезнуть или поменять параметры.
  • Пустых областей быть не должно.
  • Делите по смыслу, а не технически. Области «НаКлиенте» и «НаСервере» не нужны, подобласти — по функциональности.
  • У каждого события свой обработчик. Если разные элементы формы делают одно и то же, общий код выносится в отдельный метод, а из каждого обработчика с именем по умолчанию вызывается этот метод.

Имена переменных, процедур и функций

Переменные. Имя образуется от терминов предметной области, слова пишутся слитно, каждое с заглавной буквы: КоличествоПачекВКоробке, а не колПач. Тип в имя не вносится (масРеквизитов, соотвВидИмя — плохо), подчёркивание в начале запрещено, однобуквенные имена — только для счётчиков циклов. Флаги называют по истинному значению: ЕстьОшибки, ЭтоТоварТара.

Процедуры называют от глагола действия: ЗаполнитьТабличнуюЧасть, ОтправитьУведомление.

Функции — от того, что они возвращают:

НеудачноПо стандарту
ПолучитьПолноеИмяПользователя()ПолноеИмяПользователя()
СоздатьПараметрыЗаполнения()НовыеПараметрыЗаполнения()
ПроверитьПроведенностьДокумента()ДокументПроведен()
ВнешняяЗадача() (возвращает Булево)ЭтоВнешняяЗадача()

Для функций-конструкторов используется слово «Новый», для проверок — «Это» или причастие. Если способ получения результата важен, допустим глагол: ВыбратьДанныеПоПравилу(). Если функция прежде всего что-то делает, а результат — лишь признак успеха, её называют как процедуру.

Хороший индикатор архитектуры: если для метода хочется имя с двумя действиями через «И», его стоит разделить на два.

Параметры и их описание

  • Параметры идут от общего к частному: сначала объект или форма, потом детали. ПересчитатьСумму(ДокументОбъект, ИмяПоля, СуммаВключаетНДС = Истина), а не наоборот.
  • Необязательные — после обязательных. Ориентир: не больше семи параметров и не больше трёх со значениями по умолчанию.
  • Если параметров много — сгруппируйте их в структуру с функцией-конструктором, которая создаёт заготовку со всеми свойствами и значениями по умолчанию. Вызывающий код только заполняет значения, но не добавляет новые свойства.
  • Не заменяйте параметры переменными модуля или реквизитами формы: метод должен получать всё, что ему нужно, явно.
  • Не вкладывайте вызовы функций и конструкторы структур прямо в список аргументов — вынесите в переменные.
1С
// Возвращает параметры отправки уведомления со значениями по умолчанию.
//
// Возвращаемое значение:
//   Структура:
//   * Получатель - СправочникСсылка.Пользователи - кому отправить.
//   * Тема - Строка - тема уведомления.
//   * Срочно - Булево - признак срочной отправки.
//
Функция НовыеПараметрыУведомления() Экспорт

	Параметры = Новый Структура;
	Параметры.Вставить("Получатель", Неопределено);
	Параметры.Вставить("Тема", "");
	Параметры.Вставить("Срочно", Ложь);
	Возврат Параметры;

КонецФункции

Экспортные методы описываются комментарием обязательно: общее описание, блок «Параметры» и «Возвращаемое значение». Конфигуратор и EDT распознают такой комментарий и показывают его в подсказках при вызове. Для неэкспортных методов комментарий нужен, если он что-то объясняет, а не пересказывает имя.

Оформление текста модуля

  • Один оператор — одна строка; синтаксический отступ табуляцией (в конфигураторе — автоформатирование выделенного блока).
  • Строки длиннее 120 символов переносятся. Знаки операций и И/Или ставятся в начале новой строки.
  • Ключевые слова пишутся канонически: Не, И, Или, Истина — так, как в синтаксис-помощнике. В тексте запросов, наоборот, принято НЕ, И, ИЛИ.
  • Буква «ё» в тексте модулей не используется, кроме интерфейсных строк.
  • Не сравнивайте булево с литералами: Если ЭтоНовый() Тогда, а не Если ЭтоНовый() = Истина Тогда.
  • Используйте системные наборы значений: Символы.ПС вместо Символ(10).
  • Не оставляйте закомментированный код, отладочные фрагменты и неиспользуемые методы.
  • Инициализируйте локальные переменные до ветвлений, чтобы не получить Неопределено там, где ожидается число или строка.

Сложность методов и защитное программирование

Стандарты разработки 1С: снижение когнитивной сложности метода
Стандарты разработки 1С: снижение когнитивной сложности метода

Помимо формальных правил, инструменты статического анализа считают метрики сложности. Ориентиры, на которые я опираюсь:

МетрикаПорогЧто считает
Когнитивная сложность15Ветвления, циклы, Попытка, логические операторы, с надбавкой за вложенность
Цикломатическая сложность20Количество независимых путей выполнения
Глубина вложенности4 уровняВложенные Если и циклы
Длина метода1–2 экранаОриентиры разные, общий смысл — метод должен читаться целиком

Как снижать сложность:

  • Выносите сложные условия в функцию с говорящим именем. Вместо шести Или в Если — вызов ЭтоОтчетБезРасшифровки(Идентификатор).
  • Выделяйте фрагменты в отдельные методы. В конфигураторе есть «Рефакторинг → Выделить фрагмент», в EDT — аналогичная команда.
  • Ранний выход. Проверка граничных условий в начале метода с Возврат убирает уровень вложенности для всего остального кода.
  • Сложный тернарный оператор заменяйте на Если. ?() уместен, когда условие одно и простое.

Защитное программирование: в цепочке Если ... ИначеЕсли последней должна идти ветка Иначе — с действием (например, исключением о неожиданном типе) или с комментарием, почему ничего делать не нужно.

1С
Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
	ЗаполнитьПоСтруктуре(ДанныеЗаполнения);
ИначеЕсли ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказКлиента") Тогда
	ЗаполнитьПоЗаказу(ДанныеЗаполнения);
Иначе
	ВызватьИсключение НСтр("ru = 'Неподдерживаемый тип данных заполнения.'");
КонецЕсли;

Магические числа, литералы и секреты в коде

  • Магические числа и даты. Длительность < 36000 непонятно без контекста. Вынесите в переменные с именами: ЧасовВИнтервале * СекундВЧасе.
  • Повторяющиеся строковые литералы — в переменную или функцию, чтобы опечатка в одном месте не ломала логику.
  • Адреса, логины, пароли, пути к каталогам в коде недопустимы: их видят все разработчики, при смене требуется новый релиз, а тестовый контур работает с другими значениями. Храните настройки в данных базы с разграничением доступа, а пароли — в безопасном хранилище БСП.
  • Явный Возврат в функции. Без него функция вернёт Неопределено, и это часто становится скрытой ошибкой.

Как контролировать соблюдение стандартов

Запомнить всё невозможно, поэтому формальную часть лучше отдать автоматике:

  • BSL Language Server — диагностики стандартов и метрики сложности; работает в VS Code и как основа других инструментов;
  • SonarQube с плагином для 1С — контроль качества в CI на каждом коммите;
  • плагины к конфигуратору и EDT, подсвечивающие нарушения прямо в редакторе;
  • встроенная проверка конфигурации и «1С:Автоматизированная проверка конфигураций» для типовых требований.

Связка «проверка в CI + ревью» — то, что я настраиваю командам в рамках DevOps для 1С. Если нужен взгляд со стороны на уже написанную конфигурацию, это задача аудита 1С; новые решения с нуля по стандартам — разработка конфигураций.

Стандарты не читают один раз. Возвращайтесь к ним, когда ревьюер в третий раз пишет одно и то же замечание: это верный знак, что правило пора перечитать.

Коротко

  • Бизнес-логика живёт в модулях менеджера и общих модулях, а не в формах; экспортные методы в модуле объекта — исключение.
  • Модуль делится на стандартные области; чужие служебные методы не вызываем.
  • Функции называем по возвращаемому значению, процедуры — по действию, флаги — по истинному значению.
  • Много параметров — структура с функцией-конструктором; экспортные методы всегда с описанием.
  • Сложность держим в пределах ориентиров, а соблюдение формальных правил проверяем автоматически.