Чистый код в 1С 8.3: наводим порядок по стандартам
Содержание
Порядок в коде 1С держится на четырёх опорах: единые правила именования, разбивка модулей на области, рефакторинг штатными средствами и запросы без обращений к базе в цикле. Разберём каждую — с путями меню конфигуратора и примерами кода.
Чистый код в 1С:Предприятие 8.3 — это не вкусовщина. Типовые конфигурации (БП 3.0, ЗУП 3.1, УТ 11) написаны по «Системе стандартов и методик разработки» фирмы 1С. Если упорядочить свой код по тем же правилам, его легче сопровождать, обновлять рядом с типовым и передавать другому разработчику без долгих объяснений.
Ниже всё — про управляемые формы и платформу 8.3 с интерфейсом «Такси». Старый обычный интерфейс 8.2 не рассматриваем.
Единые имена: переменные, процедуры и префиксы
Имя должно читаться как фраза на русском. Фирма 1С рекомендует русские идентификаторы — они понятнее в предметной области учёта, чем транслит.
Правила, которые дают 80% чистоты:
- 🔤 Стиль ВерхнийКэмелКейс для процедур, функций и переменных:
СформироватьТаблицуОстатков,СуммаДокумента. Каждое слово с большой буквы, без подчёркиваний и пробелов. - 📛 Осмысленные имена.
пер1,ттт,ВремТаб2— мусор. Из имени должно быть ясно, что внутри:ТаблицаПродаж, а нетп. - ✅ Булевы — как утверждение:
ЭтоГруппа,Проведён,ТребуетсяПересчёт. Читается «если это группа», а не «если флаг3». - 🔁 Единообразие глаголов: получить данные — всегда
Получить…, сформировать —Сформировать…. Не плодите синонимыВзять…,Достать…,Сделать…для одного действия.
Для функций берите имя-существительное или вопрос («что вернёт»): ВалютаУчёта(), а для процедур — глагол-действие: ЗаполнитьРеквизиты().
Префиксы — обязательны в доработках типовых. Когда добавляете свои объекты метаданных и общие модули в типовую конфигурацию
, ставьте собственный префикс (например, гкСервер, _ДемоОбмен). Это отдельный стандарт 1С — «Префикс имён объектов метаданных». Префикс решает две задачи:
- ваши объекты не конфликтуют с типовыми при обновлении;
- в дереве конфигурации сразу видно, что добавлено вручную.
Короткий ориентир по префиксам и стилю:
| Что именуем | Как | Пример |
|---|---|---|
| Процедура | глагол + ВерхнийКэмелКейс | ЗаполнитьТаблицуСтрок |
| Функция | существительное / вопрос | ВалютаРегламентированногоУчёта() |
| Булева переменная | утверждение | Проведён, ЕстьОшибки |
| Объект в доработке типовой | свой префикс | гкОбменСБанком |
Плохо и хорошо на одном примере:
// было
Функция ф(д)
Возврат д.Контрагент.ИНН;
КонецФункции
// стало
Функция ИННКонтрагентаДокумента(Документ)
Возврат Документ.Контрагент.ИНН;
КонецФункции
Деление модуля на области и директивы компиляции
Длинный модуль без структуры — главный источник хаоса. Платформа 8.3 даёт для порядка два механизма: области (#Область … #КонецОбласти) и директивы компиляции.
Области группируют процедуры по назначению. Фирма 1С задала стандартные имена областей, и типовые следуют им. Для общего модуля порядок такой:
#Область ПрограммныйИнтерфейс
// Экспортные процедуры и функции — то, что вызывают снаружи
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
// Экспортные, но только для «своей» подсистемы
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
// Внутренняя кухня модуля, без Экспорт
#КонецОбласти
В модуле формы стандартный набор областей другой: ОбработчикиСобытийФормы, ОбработчикиСобытийЭлементовШапкиФормы, ОбработчикиКомандФормы, СлужебныеПроцедурыИФункции. Держите обработчики событий отдельно от вспомогательных процедур — тогда любой чужой код читается за минуту.
Экспортные процедуры (Экспорт) ставьте вверху, в области программного интерфейса. Служебные — ниже. Если перемешать, через полгода не вспомнишь, что из этого модуля можно вызывать снаружи, а что трогать нельзя.
Свойства общего модуля — тоже часть порядка. Куда положить процедуру, зависит от флагов модуля в палитре свойств. Не сваливайте всё в один «общий модуль на все случаи» — разнесите по назначению:
| Флаг модуля | Для чего | Пример содержимого |
|---|---|---|
| Сервер | серверная логика | расчёты, запросы, запись документов |
| Клиент (управляемое приложение) | клиентская логика | работа с формами, вопросы пользователю |
| Вызов сервера | серверные методы, доступные с клиента | получить данные для формы по кнопке |
| Повторное использование | кэшируемые функции | курсы валют, настройки на время сеанса |
| Привилегированный | код в обход прав доступа | служебные операции под полными правами |
Флаг «Повторное использование возвращаемых значений» ставьте только функциям, результат которых не меняется в пределах сеанса или вызова. Иначе получите устаревший кэш вместо актуальных данных — ошибку, которую трудно поймать.
Привилегированный модуль — не «кнопка, чтобы заработало». Код в нём исполняется без проверки прав, поэтому туда выносят только узкие служебные операции, а не бизнес-логику целиком.
Директивы компиляции определяют, где исполняется код, и их тоже надо держать в порядке:
| Директива | Где работает | Когда ставить |
|---|---|---|
&НаКлиенте | на клиенте | обработчики команд, реакция на действия пользователя |
&НаСервере | на сервере, с контекстом формы | когда нужны данные формы на сервере |
&НаСервереБезКонтекста | на сервере, без формы | запросы и расчёты, не зависящие от данных формы |
Правило: тяжёлую логику выносите в &НаСервереБезКонтекста. Такой метод не тянет с собой весь контекст формы, работает быстрее и не грузит канал клиент-сервер.
Каждую процедуру снабжайте шапкой-комментарием: краткое описание, параметры и что возвращается. Конфигуратор умеет генерировать заготовку такого описания автоматически — об этом в следующем разделе.
Рефакторинг штатными средствами конфигуратора и EDT
Наводить порядок вручную, переименовывая переменные поиском по тексту, — путь к ошибкам. В платформе есть встроенный рефакторинг.
В конфигураторе откройте меню Правка → Рефакторинг. Основные команды:
- Переименование — меняет имя процедуры или переменной во всех местах вызова внутри модуля, а не только под курсором.
- Выделить фрагмент — превращает кусок кода в отдельную процедуру или функцию, сам подставляет параметры. Лучший способ разбить метод-«простыню» на части.
- Создать описание процедуры/функции — генерирует шапку-комментарий со списком параметров по стандарту 1С.
Перед рефакторингом запустите синтаксический контроль модуля — Ctrl+F7. Переименовывать и дробить код со синтаксическими ошибками рискованно: часть ссылок рефакторинг может не увидеть.
В 1C:Enterprise Development Tools (EDT) рефакторинг мощнее: переименование по всей конфигурации, а не только в одном модуле, подсветка неиспользуемых переменных и быстрые исправления прямо в редакторе. Если проект большой и живёт долго, разработку удобнее вести в EDT, а конфигурацию выгружать в формат для конфигуратора.
Для контроля качества на уровне всей конфигурации есть отдельные инструменты:
- АПК (Автоматизированная проверка конфигураций) — конфигурация от фирмы 1С. Проверяет код и метаданные на соответствие стандартам: именование, структуру модулей, типичные ошибки.
- Хранилище конфигурации (
Конфигурация → Хранилище конфигурации) или Git через EDT — хранят историю изменений. Без истории «упорядочить» означает «сломать и не понять, что именно».
Запросы без лишних обращений к базе
Самая частая причина «грязного» и медленного кода — работа с базой внутри цикла. Один аккуратный запрос почти всегда лучше сотни мелких.
Что делать:
- Собирайте данные одним запросом. Не обращайтесь к
Ссылка.Реквизитв цикле по тысячам строк — каждое такое обращение это отдельный поход в базу. Получите всё нужное запросом заранее. - Перечисляйте поля явно.
ВЫБРАТЬ Номенклатура, Количествовместо «выбрать всё подряд». Лишние поля — лишняя нагрузка и невозможность использовать индекс-«только по индексу». - Условия — по индексированным полям. В секции
ГДЕфильтруйте по тому, что входит в индекс (измерения регистров, реквизиты с признаком индексирования). - Временные таблицы с индексами. Если промежуточный результат участвует в соединении, поместите его во временную таблицу и проиндексируйте поле соединения.
Простой пример — получить остатки одним запросом и дальше работать в памяти, а не дёргать базу построчно:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| Остатки.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата, ) КАК Остатки
|ГДЕ
| Остатки.КоличествоОстаток > 0";
Запрос.УстановитьПараметр("Дата", ДатаОтчёта);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// обработка строки — уже без обращений к базе
КонецЦикла;
Текст запроса собирайте в конструкторе запросов (правый клик в модуле → Конструктор запроса). Он расставит соединения и секции корректно, а вы не забудете проиндексированные условия.
Отдельная частая ошибка — соединение с виртуальной таблицей регистра в подзапросе или в цикле. Виртуальные таблицы (Остатки, ОстаткиИОбороты) рассчитываются «на лету», и дёргать их многократно дорого. Рассчитайте один раз, положите во временную таблицу — дальше соединяйтесь с ней.
Доработки типовых: расширения вместо правки оригинала
Самый чистый способ изменить типовую конфигурацию — не трогать её код, а вынести доработку в расширение конфигурации . Механизм появился в платформе начиная с 8.3.6 и с тех пор стал стандартом доработок.
Что это даёт для порядка:
- Типовая конфигурация остаётся на поддержке без снятия с замка. Обновления ставятся штатно, ваш код живёт отдельным файлом
.cfe. - Доработки собраны в одном месте, а не размазаны по чужим модулям. Их видно и легко отключить.
- Загрузка расширения (
.cfe) и обновление конфигурации базы данных — разные шаги: после загрузки файла изменения применяются, только когда вы выполните обновление конфигурации БД.
Правка кода прямо в типовой со снятием с поддержки оправдана всё реже. Если доработка ложится в возможности расширения — делайте расширением: следующее обновление пройдёт без ручного сравнения-объединения.
Если код всё же правится в самой конфигурации, помечайте вставки комментариями с префиксом (// гк + … // гк -), чтобы при обновлении сразу видеть свои изменения в окне сравнения.
Проверка и полировка перед выгрузкой
Перед тем как поместить изменения в хранилище или обновить рабочую базу, прогоните код через короткий финальный контроль. Это дешевле, чем ловить ошибку у пользователя.
Пара приёмов для финальной полировки:
- Отступы. В модуле выделите код и выровняйте табуляцией (
Tab/Shift+Tab); при вводе новой строки конфигуратор сам продолжает отступ предыдущей. Единый отступ — первое, что бросается в глаза при чтении чужого кода. - Мёртвый код. Удаляйте неиспользуемые переменные, процедуры и старые комментарии-заглушки. EDT подсвечивает неиспользуемое само; в конфигураторе ищите по глобальному поиску вызовов.
- Магические числа и строки. Повторяющиеся константы вынесите в переменные с понятным именем или в общий модуль, чтобы не искать «откуда взялось 0.2» по всей конфигурации.
Перед обновлением рабочей базы сделайте резервную копию. Рефакторинг «вроде бы безобидный», но переименование с ошибкой или удаление нужной процедуры проявятся уже в работе пользователей.
Чего не делать при наведении порядка
Несколько ошибок встречаются чаще прочих — и каждая способна превратить «уборку» в поломку рабочей базы.
- ❌ Переименовывать поиском-заменой по тексту. Автозамена пройдёт и по строкам запросов, где имена реквизитов стоят в кавычках, и по комментариям. Используйте рефакторинг
Правка → Рефакторинг → Переименование— он понимает структуру кода, а не ищет подстроку. - ❌ Считать, что автоотступ навёл порядок. Выравнивание отступов делает код опрятнее, но не меняет логику и не переставляет процедуры по областям. Структуру наводят руками.
- ❌ Дробить и переименовывать без истории. Нет хранилища или Git — нет возможности откатить неудачный рефакторинг. Сначала фиксация, потом правки.
- ❌ Выносить всё в привилегированный модуль «чтобы заработало». Это маскирует проблему с правами доступа, а не решает её, и открывает дыру в разграничении прав.
- ❌ Оставлять закомментированный код «на всякий случай». Старые версии хранит система контроля версий. Закомментированные блоки только засоряют модуль и путают следующего разработчика.