Обзор курса от 1С «Пиши код грамотно», часть 1
Всё чаще звучат призывы писать код, который соответствует утвержденным стандартам вендора. На проектах внедряют проверки на соответствие кода стандартам, например, SonarQube. Вопрос заинтересовал меня, и я решил изучить более глубоко. Прошел курс от вендора и постарался кратко, «без воды», изложить важные моменты.
В статью вошли темы по структуре модулей, модули, в которых следует размещать код, наименования процедур, функций и их параметров и др. Вопросы по запросам, событиям модулей объектов войдут во вторую часть.
Для новичков рекомендую первоначально заппомнить самые простые правила — наименования переменных, функций и процедур, затем разобраться с параметрами функций/ процедур и структурой и т. д.
«Никто не обнимет необъятного», — Козьма Прутков.
Поначалу относился к стандарту, как к простым понятным правилам, которые можно прочитать по диагонали один раз и твой код будет соответствовать. Но прочитать, запомнить стандарт и даже писать код, соответствующий стандарту про разное. У каждого разработчика вырабатывается привычка как размечать код, как называть переменные, функции и, если эта привычка не соответствует стандарту — то, для изменения её требуется приложить усилия.
Мне сложно привыкнуть к правильному написанию условных операций — «Не», вместо «НЕ» и «Или» вместо «ИЛИ». Причем нужно учесть, что в запросах эти же условные операции пишутся «НЕ» и «ИЛИ». Также проверяю себя, чтобы функции и процедуры были распределены правильно по областям модуля. Благодаря этому получаю высокие оценки на код-ревью.
Информацию постарался представить в виде памятки, используя которую можно быстро освежить в памяти нужную информацию, не пересматривая все видео урока. Надеюсь, что вы внимательно прочитаете стандарты полностью. Финальное пожелание — возвращайтесь периодически к текстам стандартов, проверяйте себя.
Contents
- 1 Почему важно писать код по стандарту
- 2 В каком модуле вносить изменения
- 3 Структура модуля #std455
- 4 Правила образования имен переменных #std454
- 5 Имена процедур и функций #std647
- 6 Наименование функций
- 7 Параметры процедур и функций #std640
- 8 Структуры и таблицы значений в качестве параметров #std641
- 9 Описание процедур и функций #std453
- 10 Общие требования к текстам модулей #std456
- 11 Перенос выражений #std444
- 12 Предварительная инициализация локальных переменных #std494
Почему важно писать код по стандарту
Всё большую важность приобретает скорость внедрения изменений и создания ПО. Создание ПО по стандарту позволяет стандартизировать и код, и подходы к методам программирования и соответственно:
- быстрее определить точку изменения
- легче понять как работает
- быстрее найти ошибку
- легче изменить/ доработать
В стандарте описаны и некоторые общие ограничения, позволяющие избежать ошибок. Сам стандарт состоит из ряда отдельных небольших стандартов, касающихся различных вопросов. У каждого небольшого стандарта есть свой код и страница на сайте ИТС. Ознакомиться с текстом стандарта можно на сайте ИТС (доступен без подписки).
Инструкции по разработке на 1С / Методические материалы для разработчиков и администраторов 1С / 1С:Предприятие 8. Система стандартов и методик разработки конфигураций. Для быстрого переключения между стандартами можно использовать ссылку, в которой последнее трёхзначное число можно менять на нужный стандарт: https://its.1c.ru/db/v8std#content:486:hdoc
В каком модуле вносить изменения
Для этого предлагаю рассмотреть виды модулей платформы. Под конкретные задачи:
- Модуль приложения
- Модуль внешнего соединения
- Модуль сеанса
- Модули команд
- Модули Web- и HTTP-сервисов
- Модули ботов
- Модули сервисов интеграции
- Модули менеджеров значений (константы)
- Общие модули
- Модули объектов (наборов записей)
- Модули менеджеров объектов
- Модули форм
Из перечисленных модулей с первой восьмеркой не возникает двойственности — они необходимы для конкретных задач, а для последних четырех модулей периодически возникает вопрос: в какой из них нужно вносить изменения.
Модули объекта, менеджера и общие модули #std486
В стандарте описано для чего предназначены модуль объекта и модуль менеджера. Модуль объекта предназначен для реализации поведения отдельного экземпляра объекта (СправочникОбъект, ДокументОбъект и т.п.). В модуле объекта размещаются процедуры и функции, которые работают с данными объекта (ЭтотОбъект и переменные модуля объекта), в том числе когда он еще не записан в информационную базу.
Например, в модуле объекта могут размещаться:
- обработчики событий объекта
- процедуры заполнения экземпляра объекта.
Помните, что для вызова экспортных процедур и функций модуля объекта из других модулей может потребоваться предварительно получить сам экземпляр объекта из информационной базы с помощью метода ПолучитьОбъект. При этом происходит загрузка объекта из базы целиком, вместе с его табличными частями, что ресурсоемко. Из дополнительной информации делаем вывод, что помещение экспортных методов в модуль объекта сопряжено с ограничениями и рекомендовано для ограниченных случаев.
Про модуль менеджера объекта. Он предназначен для размещения «статической» функциональности, которая логически неразрывно связана с объектом метаданных, но не зависит от состояния конкретного экземпляра объекта данных. «Статическая» функциональность не связана с необходимостью получить экземпляр объекта. Это могут быть процедуры и функции, которые относятся ни к одному, а сразу к совокупности объектов.
Например,
- функции для вывода на печать списка объектов;
- функции, возвращающие информацию, общую для всех экземпляров объекта;
- процедуры обновления данных информационной базы, которые связаны с объектом метаданных, и которые работают с объектом, записанным в ИБ. В таких функциях входным параметром является ссылка на объект.
Например, это функции для получения печатной формы по ссылке на объект, процедуры формирования движений по ссылке на объект и т.п.
- это функции для вывода на печать списка объектов;
- функции, возвращающие информацию, общую для всех экземпляров объекта;
- процедуры обновления данных информационной базы, которые связаны с объектом метаданных; и т.п.
- которые работают с объектом, записанным в ИБ. В таких функциях входным параметром является ссылка на объект.
Например, это функции для получения печатной формы по ссылке на объект, процедуры формирования движений по ссылке на объект и т.п.
Важное дополнение в стандарте: для выполнения функций модуля менеджера объекта не должен требоваться экземпляр объекта данных (СправочникОбъект, ДокументОбъект и т.п.). Последний абзац данного стандарта:
Если функциональность невозможно однозначно отнести к тому или иному объекту метаданных, то она является логически общей для нескольких объектов. В этом случае ее следует размещать в общем модуле.
Следует добавить, что в модуле формы должен располагаться только код, касающийся конкретной формы, там не должно размещаться универсальной бизнес-логики. Выполнение бизнес-логики должно быть доступно без получения форм.
На данном рисунке представлена предлагаемая схема выбора модулей для размещения кода.

Структура модуля #std455
- Общая схема облестей задается стандартом
- Стандартная структура областей зависит от конкретного типа модуля
- Структура модуля оформляется с помощью областей
- Для быстрого управления областями на слайде используются быстрые кнопки:
Ctrl + Shift + «+ на цифровой» — раскрыть все
Ctrl + Shift + «- на цифровой» — свернуть все
Наиболее часто встречающиеся разделы:
«Программный интерфейс» содержит экспортные процедуры и функции, предназначенные для использования другими объектами конфигурации или другими программами (например, через внешнее соединение).
«Служебный программный интерфейс» предназначен для модулей, которые являются частью некоторой функциональной подсистемы. В нем должны быть размещены экспортные процедуры и функции, которые допустимо вызывать только из других функциональных подсистем этой же библиотеки.
«Служебные процедуры и функции» содержит процедуры и функции, составляющие внутреннюю реализацию модуля. В тех случаях, когда общий модуль является частью некоторой функциональной подсистемы, включающей в себя несколько объектов метаданных, в этом разделе также могут быть размещены служебные экспортные процедуры и функции, предназначенные только для вызова из других объектов данной подсистемы. Для объемных общих модулей рекомендуется разбивать этот раздел на подразделы, по функциональному признаку.
«Обработчики событий» содержит обработчики событий модуля объекта (ПриЗаписи, ПриПроведении и др.)
«Обработчики событий элементов шапки формы» содержит процедуры-обработчики элементов, расположенных в основной части формы (все, что не связано с таблицами на форме).
«Обработчики событий элементов таблицы формы <имя таблицы формы>» размещаются процедуры-обработчики таблиц формы и элементов таблиц. Для процедур-обработчиков каждой таблицы должен быть создан свой раздел.
«Обработчики команд формы» содержит процедуры-обработчики команд формы (имена которых задаются в свойстве Действие команд формы).
Особенность служебных разделов
Если есть экспортный метод, размещенный в служебном разделе, и разработан не нами, то мы такой метод вызывать не должны. Правило касается общих модулей с указанием «Служебный» в наименовании. Иначе не гарантируется обратная совместимость, т.е. при внедрении новой версии может быть изменен/ удален, могут быть добавлены/ удалены параметры.
Дополнительные рекомендации стандарта: допустимо внутри области задавать дополнительные области, позволяющие распределить процедуры и функции на меньшие области.
- В модулях не должно быть пустых областей.
- Нежелательно «техническое» распределение областей, например «НаКлиенте», «НаСервере». Желательно разделять области по функциональности.
- Рекомендуется располагать обработчики, придерживаясь порядка их следования в описании встроенного языка
Методическая рекомендация для случая, если на форме есть обработчики событий с одинаковыми действиями. У каждого события должна быть назначена своя процедура-обработчик. Если одинаковые действия должны выполняться при возникновении событий в разных элементах формы следует:
- создать отдельную процедуру (функцию), выполняющую необходимые действия
- создать отдельный обработчик с именем, назначаемым по умолчанию, для каждого элемента формы
- вызвать требуемую процедуру (функцию) из каждого обработчика.
Правила образования имен переменных #std454
- Имена переменных следует образовывать от терминов предметной области таким образом, чтобы из имени переменной было понятно ее назначение.
- Имена следует образовывать путем удаления пробелов между словами. При этом, каждое слово в имени пишется с прописной буквы. Предлоги и местоимения из одной буквы также пишутся прописными буквами.
- В наименование переменной не рекомендуется вносить тип переменной, поскольку в дальнейшем этот тип может быть либо расширен, либо изменен.
Пример:
Перем ДиалогРаботыСКаталогом; // Диалог работы с каталогом
Перем КоличествоПачекВКоробке; // Количество пачек в коробке
Примеры некорректных имен переменных: масРеквизитов, соотвВидИмя, новСтр
- Имена переменных запрещается начинать с подчеркивания.
- Имена переменных не должны состоять из одного символа. Использование односимвольных имен переменных допускается только для счетчиков циклов.
- Переменные, отражающие состояние некоторого флага, следует называть так, как пишется истинное значение этого флага.
Пример:
Перем ЕстьОшибки; // Признак наличия ошибок в процедуре.
Перем ЭтоТоварТара; // Признак, что товар относится к возвратной таре.
Имена процедур и функций #std647
Правильный выбор имен процедур и функций очень важен для повышения читаемости кода. В большинстве случаев хорошо выбранное имя процедуры в сочетании с правильно подобранными именами параметров избавляют от необходимости ее дополнительно описывать. В ряде случаев, сложности в выборе имени процедуры и (или) ее параметров свидетельствуют о неправильной архитектуре программного кода. И наоборот, если «самодокументирующееся» имя придумать легко, значит процедура спроектирована правильно.
- Не рекомендуется в названиях описывать типы принимаемых параметров и (или) возвращаемых значений
- Имена процедур (в общем случае) следует образовывать от глагола действия
- Имена функций (в общем случае) от описания возвращаемого значения
- При проектировании процедур и функций следует придерживаться принципа единственной ответственности, т.е. одна функция/ процедура решают одну задачу
Если при наименовании хочется задать имя с двумя действиями, то скорее всего желательно разделить данную процедуру/ функцию на две.
Наименование функций
Для функций в стандарте обозначено несколько случаев с рекомендациями к наименованию. В общем случае, как мы уже обозначили ранее: имена функций (в общем случае) следует образовывать от описания возвращаемого значения. В стандарте приведено три примера функций названных неправильно:
Функция ПолучитьПолноеИмяПользователя()
Функция СоздатьПараметрыЗаполненияЦенПоставщика()
Функция ОпределитьДатуНачалаСеанса()
Правильно:
Функция ПолноеИмяПользователя()
Функция НовыеПараметрыЗаполненияЦенПоставщика()
Функция ДатаНачалаСеанса()
В таких названиях функций становится понятно, возврат каких данных будет произведен. Если функция предназначена для создания какого-либо объекта, то рекомендуется в ее имени использовать слово «Новый»
Неправильно: Функция ДобавитьПолеФормы(), Правильно: Функция НовоеПолеФормы()
НЕ Функция СоздатьЭлементСправочникаФайлы(), а Функция НовыйЭлементСправочникаФайлы()
НЕ Функция ПолучитьТаблицуКоманд(), а Функция НоваяТаблицаКоманд()
Если функция выполняет проверку какого-то условия, то ее имя рекомендуется начинать со слова «Это» или использовать причастия.
НЕ Функция ПроверитьПроведенностьДокумента(), А Функция ДокументПроведен()
НЕ Функция ПроверитьИзменениеРеквизитовДокумента(), а Функция РеквизитыДокументыИзменены()
НЕ Функция ВнешняяЗадача(), а Функция ЭтоВнешняяЗадача()
В имени функции рекомендуется использовать глаголы в неопределенной форме в тех случаях, когда для понимания назначения функции важно, каким образом было получено возвращаемое значение:
Функция ВыбратьДанныеПоПравилу(Правило, ПользовательскиеНастройки)
Функция ПреобразоватьДанныеПоПравилу(НаборыДанных, ПараметрыПреобразования)
Если выполнение функции предполагает, прежде всего, какое-либо действие, и при этом возврат значения не является ее основной задачей (например, это признак успешно выполненного действия), то имена таких функций следует образовывать от неопределенной формы глагола, как и для процедур.
Функция РазрешитьРедактированиеРеквизитовОбъекта(Форма)
Параметры процедур и функций #std640
- Имена параметров следует образовывать от терминов предметной области таким образом, чтобы из имени параметра было понятно его назначение
- Не следует использовать вместо параметров функций другие средства конфигурирования (переменные модулей, реквизиты формы и т.п.)
- Параметры в функции должны идти в логической последовательности. Рекомендуется располагать параметры по принципу от общего к частному.
Неправильно:
Процедура ПересчитатьСуммуДокумента(ИмяПоляСумма, ДокументОбъект, СуммаВключаетНДС = Истина)
Правильно сначала расположить основные параметры ДокументОбъект и Форма:
Процедура ПересчитатьСуммуДокумента(ДокументОбъект, ИмяПоляСумма, СуммаВключаетНДС = Истина)
НЕ Процедура ПоменятьЦветПоляФормы(Цвет, ИмяПоля, Форма), а
Процедура ПоменятьЦветПоляФормы(Форма, ИмяПоля, Цвет)
Необязательные параметры (параметры со значениями по умолчанию) должны располагаться после обязательных параметров (без значений по умолчанию). Не рекомендуется объявлять в функциях много параметров (нужно ориентироваться на количество не более семи параметров), при этом не должно быть много параметров со значениями по умолчанию (нужно ориентироваться на количество не более трех таких параметров).
При необходимости передавать в функцию большое число параметров рекомендуется:
- группировать однотипные параметры в один или несколько составных параметров типа Структура. Например, в структуры могут быть объединены параметры, описывающие состав и значения полей некоторого объекта (ДанныеЗаполнения, ПараметрыПроведения, ДанныеФайла и т.п.);
- либо полностью пересмотреть логику работы функции, например, разделив ее на несколько разных, более простых функций.
Не рекомендуется
- при передаче параметров в одну функцию применять вложенные вызовы других функций
- при вызове функций использовать вложенный конструктор структуры: Новый Структура(…). Вложенное объявление структуры допустимо только в тех случаях, когда количество ее свойств небольшое (нужно ориентироваться на количество свойств не более трех).
- при вызове функций пропускать обязательные параметры. В противном случае, в параметр будет передано значение Неопределено, на которое функция может быть не рассчитана. Если же значение Неопределено является допустимым, то его необходимо передавать в функцию явно, или сделать этот параметр необязательным со значением по умолчанию Неопределено.
Структуры и таблицы значений в качестве параметров #std641
Для процедур и функций (далее по тексту: функций) с параметрами типа Структура, ТаблицаЗначений, а также ДеревоЗначений (далее по тексту рекомендации для таблицы значений также относятся к дереву значений) рекомендуется придерживаться следующего подхода к разработке.
Помимо функции, которая собственно реализует прикладную функциональность, необходимо определить функцию-конструктор параметров возвращающую: структуру-заготовку со свойствами (желательно с присвоением значений по-умолчанию); или пустую таблицу значений (дерево значений) с типизированными колонками, которую вызывающий код должен проинициализировать конкретными значениями и передать в вызываемую функцию.
- Имена свойств структуры соответствуют параметрам вызываемой функции, при этом параметры со значениями по умолчанию должны быть явно проинициализированы в этой структуре
- Для создания параметра с типом ТаблицаЗначений допускается не создавать отдельную функцию-конструктор, если таблица значений является результатом каких-либо расчетов в прикладном коде
- В вызывающем коде не следует инициализировать структуру параметров или добавлять в нее другие свойства, изменять состав и тип колонок таблицы значений. Во избежание неоднозначности и скрытых ошибок все допустимые параметры вызываемой функции должны быть определены явно в функции-конструкторе параметров. Если требуется изменить структуру по-умолчанию, то изменения нужно вносить в функцию — конструктор, а не в процедуру из которой она вызывается.
- При разработке программного интерфейса библиотек все функции, возвращающие значения в виде структур и таблиц значений, в том числе и функции-конструкторы, обязательно должны иметь описание типа возвращаемого значения. При этом необходимо описывать свойства структур и колонки таблиц значений, начиная с новой строки и предваряя символом *.
- В описании структур и таблиц значений могут быть вложенные описания, при этом перед именами вложенных свойств число звездочек увеличивается: для первого уровня вложенности 2 звездочки, для второго 3 и т. д.
Описание процедур и функций #std453
- Описание процедур и функций рекомендуется выполнять в виде комментария к ним. Необходимость комментирования отдельных участков кода определяется разработчиком, исходя из сложности и нестандартности конкретного участка кода
- Обязательного комментирования требуют процедуры и функции входящие в программный интерфейс модулей — т.е. все экспортные процедуры и функции. Такие процедуры и функции предназначены для использования в других функциональных подсистемах, за которые могут отвечать другие разработчики, поэтому они должны быть хорошо документированы
- Прочие процедуры и функции рекомендуется комментировать, если требуется пояснить назначение процедуры (функции) или особенности её работы. Также рекомендуется описывать причины невыполнения некоторых действий, если они кажутся неочевидными для данной процедуры или функции
- Следует избегать комментариев, не дающих дополнительных пояснений о работе не-экспортной процедуры (функции)
- Комментарий размещается перед объявлением процедуры (функции)
Описание разделяется на три блока: общее описание, описание параметров и описание возвращаемого значения — если это описание функции. Более подробно про описание можно ознакомиться в стандарте 453. Отмечу, что правильно заполненное описание распознается системой и при вызове описанной процедуры или функции система показывает подсказки из заполненного текста — например, показывает описание параметров процедуры/ функции при введении соответствующих параметров.
Общие требования к текстам модулей #std456
- В текстах модулей не допускается использовать букву «ё». Исключения составляют интерфейсные тексты
- Программные модули не должны иметь неиспользуемых процедур и функций; иметь закомментированных фрагментов кода, а также фрагментов, связанных с процессом разработки
- Тексты модулей оформляются по принципу «один оператор в одной строке»
- Текст модуля должен быть оформлен синтаксическим отступом. Для автоматического расставления синтаксического отступа используется табуляция Alt + Shift + F
- При длине строки более 120 символов следует использовать переносы
- Тексты модулей могут содержать комментарии
- Небольшие комментарии пишутся в конце строки
- Большие комментарии пишутся перед комментируемым кодом в отдельной строке
- Тексты больших процедур и функций можно разбивать на отдельные сворачиваемые области
- В конструкциях встроенного языка ключевые слова пишутся канонически (как в документации или Синтакс-помощнике)
- Логические выражения и логические значения (например, результат функции, возвращающей логическое значение, переменные типа Булево и пр.) не следует проверять путем сравнения с литералами Истина и Ложь
Правильно: Если ЭтоНовый() Тогда
Неправильно: Если ЭтоНовый() = Истина Тогда
- Составные логические выражения в Если…КонецЕсли переносятся согласно правилам переноса выражений
- В тех случаях, когда требуется сравнивать результаты выражений, следует предварительно присваивать результаты выражений промежуточным переменным, и сравнивать уже сами эти переменные
- Необходимо использовать системные наборы значений везде, где возможно их применить, например, вместо Символ(10) следует использовать Символы.ПС
Перенос выражений #std444
- При длине строки более 120 символов следует использовать переносы. Строки длиннее 120 символов делать не рекомендуется, за исключением тех случаев, когда перенос невозможен
- Длинные арифметические выражения переносятся следующим образом: в одной строке может находиться более одного операнда; при переносе знаки операции пишутся в начале строки (а не в конце предыдущей строки); операнды на новой строке предваряются стандартным отступом, либо выравниваются по началу первого операнда без учета знаков операций
- Длинные строковые константы рекомендуется переносить с помощью специального символа перевода на новую строку «|»
- В общем случае при конкатенации строк знак «+» рекомендуется писать в начале строки, так же как и при переносе арифметических выражений
- При конкатенации длинных строк знак «+» можно писать в конце строки, чтобы не ломать общее форматирование текста
- Для форматирования введенного кода необходимо выделить блок текста, и выбрать пункт меню Текст — Блок — Форматировать.
- Сложные логические условия в Если…ИначеЕсли…КонецЕсли следует переносить следующим образом: каждое элементарное условие нужно начинать с новой строки, если длина строки превышает ограничение в 120 символов; логические операторы И, ИЛИ ставятся в начале строки, а не в конце предыдущей строки; все условия предваряются стандартным отступом, либо выравниваются по началу первого условия, без учета логического оператора (для выравнивания выражений используются пробелы)
- При необходимости параметры процедур, функций и методов следует переносить следующим образом: параметры выравниваются по началу первого параметра, либо предваряются стандартным отступом; закрывающая скобка и разделитель операторов «;» пишутся в той же строке, что и последний параметр; допустим и способ форматирования, который предлагает функция автоформатирования в конфигураторе.
Предварительная инициализация локальных переменных #std494
В случаях когда фрагмент кода вычисляет значение одной или нескольких локальных переменных, рекомендуется явно выполнять предварительную инициализацию таких переменных. Это позволит избежать потенциальных ошибок времени выполнения, когда значение переменной оказывается Неопределено, а последующий код рассчитывает на определенный тип значения
Отличная статья, в одном месте собрано самое важное.
спасибо!