К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как правильно писать код в 1С: практическое руководство

Как писать код в 1С правильно: стандарты разработки, работа с запросами, обработка ошибок, транзакции, именование объектов и типичные ошибки начинающих.

Код на встроенном языке 1С пишется быстро, но плохо написанный код оборачивается медленными отчётами, блокировками базы и ошибками, которые всплывают у пользователей в самый неподходящий момент. Разница между «работает у меня на тестовой базе» и «работает в продакшене» почти всегда сводится к соблюдению нескольких базовых правил: корректной работе с запросами, транзакциями, обработкой ошибок и понятным именованием.

Это руководство собирает прикладные правила разработки на платформе 1С:Предприятие 8.3: как структурировать модули, как писать запросы без обходов таблиц, где ставить попытки-исключения, как не ломать данные при обменах и проведении документов. Материал ориентирован на начинающих и практикующих разработчиков, которые дорабатывают типовые конфигурации или пишут собственные подсистемы.

Перед любыми доработками типовой конфигурации сделайте резервную копию базы и проверяйте изменения сначала на копии. Изменение общих модулей и подписок на события затрагивает работу всех пользователей, и откат без бэкапа может оказаться невозможным.

Структура модулей и именование: основа читаемого кода

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

Имена переменных и процедур должны отражать смысл, а не тип. Вместо Таб или Стр1 используйте ТаблицаТоваров, СтрокаЗаказа. Процедуры называйте глаголом с дополнением: РассчитатьСуммуДокумента(), ПроверитьЗаполнениеРеквизитов(). Код в 1С традиционно пишется на русском языке — это норма платформы, а не недостаток.

Общие модули группируйте по подсистемам, а не по типам операций. Модуль РаботаСоСтроками с сотней разрозненных функций быстро превращается в свалку. Лучше: ЗаказыКлиентовСервер, ОбменССайтом — по имени модуля сразу понятно, где искать нужную функцию.

Запросы вместо циклов: как не убить производительность

Самая частая причина медленного кода в 1С — обход выборки с обращением к базе внутри цикла. Конструкция, где внутри Пока Выборка.Следующий() выполняется ещё один запрос по каждой строке, на тестовых данных работает нормально, а на реальных объёмах выполняется минутами и держит соединения с СУБД.

Правильный подход — один запрос с соединениями таблиц, который возвращает все нужные данные сразу. Если нужно сгруппировать результат по документам, используйте итоги и обход по группировкам (ОбходРезультатаЗапроса.ПоГруппировкам) вместо вложенных запросов.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ЗаказыТовары.Ссылка КАК Заказ,

| СУММА(ЗаказыТовары.Сумма) КАК Сумма

|ИЗ

| Документ.ЗаказКлиента.Товары КАК ЗаказыТовары

|ГДЕ

| ЗаказыТовары.Ссылка В (&СписокЗаказов)

|СГРУППИРОВАТЬ ПО

| ЗаказыТовары.Ссылка";

Запрос.УстановитьПараметр("СписокЗаказов", СписокЗаказов);

Результат = Запрос.Выполнить().Выгрузить();

Всегда передавайте значения через параметры запроса (УстановитьПараметр), а не конкатенацией строк. Подстановка строк в текст запроса — это и риск ошибок на спецсимволах, и потенциальная уязвимость. Также избегайте ВЫБРАТЬ * и лишних соединений: выбирайте только те поля, которые реально используются.

Типичные ошибки в запросах
01
Запрос внутри цикла по выборке — рост числа обращений к СУБД пропорционально объёму данных
02
Соединение с виртуальной таблицей без отборов — чтение всей таблицы регистра
03
Получение объекта через ПолучитьОбъект() только ради чтения одного реквизита — лишняя выборка всех данных объекта
04
Отсутствие индексируемых полей в условиях соединения — полное сканирование таблиц

Транзакции и запись данных: не оставляйте базу в рассогласованном состоянии

Любая операция, которая записывает больше одного объекта, должна выполняться в транзакции. Если после записи шапки документа код упал на записи связанного регистра, без транзакции в базе останутся неполные данные, которые потом придётся искать и чинить вручную.

Явные транзакции открываются через НачатьТранзакцию() и завершаются ЗафиксироватьТранзакцию() либо ОтменитьТранзакцию(). Внутри транзакции не должно быть диалогов с пользователем, длительных расчётов и обращений к внешним ресурсам — всё это удерживает блокировки и мешает работе других пользователей.

Порядок безопасной записи нескольких объектов
  1. 1
    Подготовьте и проверьте все данные до начала транзакции
  2. 2
    Вызовите НачатьТранзакцию()
  3. 3
    Выполните запись всех объектов внутри Попытка...Исключение
  4. 4
    При ошибке вызовите ОтменитьТранзакцию() и передайте понятное сообщение
  5. 5
    При успехе вызовите ЗафиксироватьТранзакцию()
  6. 6
    Проверьте в журнале регистрации отсутствие ошибок записи

Учитывайте управляемые блокировки: в типовых конфигурациях режим управляемых блокировок включён по умолчанию. При записи наборов данных, с которыми работают несколько пользователей, устанавливайте управляемые блокировки через БлокировкаДанных до чтения данных, которые будете менять, — иначе возможны конфликты и взаимоблокировки.

Обработка ошибок: попытка-исключение без пустых веток

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

В обработчике исключения фиксируйте ошибку через ЗаписьЖурналаРегистрации с подробным описанием (ОписаниеОшибки() или ИнформацияОбОшибке().ПодробноеОписаниеОшибки), а пользователю показывайте понятное сообщение без технических деталей стека.

Попытка

Ответ = HTTPСоединение.Получить(ЗапросHTTP);

Исключение

ЗаписьЖурналаРегистрации("ОбменССайтом",

УровеньЖурналаРегистрации.Ошибка, , ,

ОписаниеОшибки());

ВызватьИсключение "Не удалось получить данные с сайта. Подробности — в журнале регистрации.";

КонецПопытки;

Доработка типовых конфигураций: расширения вместо правки кода

Прямое изменение модулей типовой конфигурации — главный источник проблем при обновлениях. Каждое изменённое место придётся сравнивать и переносить вручную, а при снятии конфигурации с поддержки обновление усложняется многократно. Поэтому доработки по возможности выносите в расширения конфигурации.

Расширение позволяет добавлять собственные объекты, формы, подписки на события и доопределять типовые процедуры через аннотации &После, &Перед, &Вместо. Аннотацию &Вместо используйте в крайнем случае: она полностью подменяет типовой код, и при обновлении типовой процедуры ваше расширение не узнает об изменениях.

Способы доработки типовой конфигурации

Расширение конфигурации

Подходит для большинства доработок: формы, печатные формы, дополнительные проверки. Не меняет типовой код, обновления проходят легко. Ограничение: не все объекты и роли можно переопределить.

Подписки на события и внешние обработки

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

Изменение типового кода

Крайняя мера, когда расширение технически невозможно. Каждое изменение документируйте комментарием с маркером, чтобы находить при обновлении.

Проверка кода перед передачей в работу

Перед выкладкой доработки в рабочую базу прогоните код по минимальному чек-листу. Убедитесь, что все обращения к реквизитам защищены от пустых ссылок (ЗначениеЗаполнено()), что запросы тестировались на объёме данных, близком к реальному, и что привилегированный режим не открывает лишнего доступа.

Используйте встроенные средства платформы: конфигуратор умеет проверять модули на синтаксические ошибки в разных режимах (тонкий клиент, веб-клиент, сервер), а замер производительности в отладчике покажет, какие строки занимают основное время. Для типовых решений полезна проверка по стандартам разработки фирмы «1С» — в среде разработки EDT она выполняется автоматически.

Контрольные точки

Как проверить результат

Выполнение обработки на копии рабочей базы
Норма

Время выполнения приемлемо, данные корректны, журнал регистрации без ошибок

Тревожный признак

Обработка работает минутами, в журнале ошибки записи или блокировок

Обновление конфигурации после доработки через расширение
Норма

Обновление проходит без ручного сравнения изменённых модулей

Тревожный признак

Обновление требует разбора десятков изменённых типовых процедур

Работа под пользователем с ограниченными правами
Норма

Все функции доступны по назначенным ролям, лишнего доступа нет

Тревожный признак

Ошибки «Нарушение прав доступа» или, наоборот, доступ к чужим данным

Отдельно проверяйте поведение кода при нештатных ситуациях: пустые табличные части, незаполненные обязательные реквизиты, отмена проведения во время вашей обработки. Код, который корректно работает только на идеальных данных, в реальной базе сломается в первую неделю.

Итог

Что важно запомнить

Пишите понятные имена, заменяйте циклы запросами, оборачивайте множественные записи в транзакции, никогда не оставляйте пустых обработчиков исключений и дорабатывайте типовые конфигурации через расширения. Тестируйте на копии базы и под пользователем с реальными правами.

Частые вопросы о написании кода в 1С

Нужно ли писать код на русском языке или лучше на английском?

Встроенный язык 1С поддерживает оба синтаксиса, но в российской практике стандарт — русский: типовые конфигурации написаны на нём, и смешение языков затрудняет чтение. Английский вариант оправдан только в международных командах.

Когда оправдан запрос в цикле?

Почти никогда. Единственные допустимые случаи — когда параметры следующего запроса вычисляются сложной логикой, которую нельзя выразить в SQL, или при пакетной обработке с фиксацией транзакций порциями. В остальных случаях задачу решают соединения и временные таблицы.

Чем расширение отличается от внешней обработки?

Внешняя обработка запускается вручную или по расписанию и не меняет поведение конфигурации. Расширение подключается к конфигурации постоянно и может менять формы, добавлять подписки на события и переопределять процедуры типовых модулей.

Как найти узкое место в медленном коде?

Включите в конфигураторе режим отладки и используйте «Замер производительности» (Отладка — Замер производительности). Он покажет время выполнения каждой строки модуля и количество вызовов, что позволяет точно найти проблемный участок вместо догадок.

Опасно ли использовать Выполнить() и ОценитьВыражение()?

Да, если в строку кода попадают данные от пользователя или из внешних источников — это путь к выполнению произвольного кода в привилегированном режиме. Используйте эти методы только с полностью контролируемым текстом, а лучше заменяйте их вызовом методов по имени через структуры и соответствия.

Нужно ли комментировать каждую процедуру?

Комментируйте не «что делает код», а «почему сделано именно так»: неочевидные условия, обходы ограничений платформы, ссылки на особенности учёта. Описание экспортируемых процедур общих модулей в шапке — обязательный минимум, он же формирует подсказку в конфигураторе.