Разбираем код 1С 8.3: модули, объекты, запросы и отладка

· 10 мин

Содержание

Чтобы понять код 1С, читайте его не сверху вниз, а от точки входа: найдите процедуру-обработчик, которую вызывает система (ПриПроведении, ПриСозданииНаСервере, команда формы), и двигайтесь по вызовам внутрь. Встроенный язык 1С похож на русский Паскаль: ключевые слова на русском, строки через // — комментарии, точка с запятой завершает оператор. Главная сложность не в синтаксисе, а в том, чтобы понять, где исполняется строка — на клиенте или на сервере — и откуда система дёргает этот код.

Распространённое заблуждение новичка: «весь код лежит в одном месте, как в обычной программе». На деле код 1С разбросан по десяткам модулей, привязанных к объектам конфигурации, и запускается событиями. Поэтому сначала учатся ориентироваться в структуре, а уже потом — в строках.

Где физически лежит код и когда он запускается

Код в 1С живёт не в файлах, а в модулях — текстовых контейнерах внутри конфигурации. Открываются они из дерева конфигурации в Конфигураторе или в 1С:EDT. Основные типы модулей:

  • 🧩 Модуль объекта (справочника, документа) — логика конкретного объекта: ПриЗаписи, ПриПроведении, ОбработкаПроверкиЗаполнения.
  • 📄 Модуль формы — поведение открытой формы: обработчики кнопок, событий полей, ПриОткрытии.
  • 🗂 Модуль менеджера — методы, общие для всех объектов вида (например, генерация номеров, печатные формы).
  • 🌍 Общие модули — переиспользуемый код без привязки к объекту. Именно сюда выносят библиотечные функции.
  • 🚀 Модуль приложения (управляемого и обычного), модуль сеанса — запускаются при старте, управляют инициализацией.

Чтобы быстро найти, откуда взялась процедура, в Конфигураторе удобна команда перехода к определению: установите курсор на имя метода и нажмите F12 — редактор откроет тело процедуры, даже если она в другом модуле.

Если видите имя процедуры с припиской Экспорт — её можно вызывать снаружи, из других модулей. Без Экспорт метод доступен только внутри своего модуля.

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

Клиент и сервер: директивы компиляции

Самая частая причина «не могу понять, почему код не работает так, как читается» — незнание, где он исполняется. Над каждой процедурой в модуле формы стоит директива компиляции:

ДирективаГде исполняетсяЕсть ли доступ к данным
&НаКлиентена компьютере пользователянет прямого чтения из базы
&НаСерверена сервере, с контекстом формыда, с реквизитами формы
&НаСервереБезКонтекстана сервере, без данных формыда, быстрее и легче
&НаКлиентеНаСервереБезКонтекстаи там, и тамнет

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

&НаКлиенте
Процедура ОбновитьОстаток(Команда)
    Остаток = ПолучитьОстатокНаСервере(Номенклатура);
    Сообщить("Остаток: " + Остаток);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьОстатокНаСервере(Номенклатура)
    // здесь можно работать с базой
    Возврат 0;
КонецФункции

Если не понять границу клиент/сервер, весь остальной код будет читаться неправильно. Начинайте разбор формы именно с директив.

Синтаксис и типы данных: из чего собран код

Синтаксис встроенного языка компактный. Вот минимум, без которого текст не читается:

  • Переменные объявлять заранее не обязательно — тип определяется при присваивании.
  • Комментарий — всё после // до конца строки.
  • Процедура ничего не возвращает, Функция возвращает значение через Возврат.
  • Конструкции ветвления и циклов: Если … Тогда … Иначе … КонецЕсли, Для … По … Цикл … КонецЦикла, Для Каждого … Из … Цикл, Пока … Цикл.

Типы данных делятся на три группы:

  1. Примитивные: Число, Строка, Булево, Дата, а также Неопределено, NULL и Тип.
  2. Ссылочные: ссылки на объекты базы — СправочникСсылка.Контрагенты, ДокументСсылка.РеализацияТоваровУслуг. Ссылка — это «адрес» записи, а не сама запись.
  3. Универсальные коллекции: Массив, Структура, Соответствие, СписокЗначений, ТаблицаЗначений, ДеревоЗначений.

Коллекции встречаются в коде постоянно, поэтому различайте их:

КоллекцияЧем ищем элементКогда применяют
Массивпо индексу (с нуля)простой список значений
Структурапо имени ключа (идентификатор)набор именованных полей
Соответствиепо любому ключу-значениюсправочник «ключ → значение»
ТаблицаЗначенийпо строкам и колонкамданные в виде таблицы
// Структура: ключ — это имя, его видно в коде
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Организация", ТекущаяОрганизация);
ПараметрыОтбора.Вставить("Период", ТекущаяДата());

// Массив: доступ по индексу, первый элемент — нулевой
Список = Новый Массив;
Список.Добавить("Первый");
Сообщить(Список[0]); // выведет: Первый

В коллекциях 1С индексация начинается с нуля, а не с единицы. Массив[0] — первый элемент. Это частый источник ошибок при чтении чужого кода.

Объектная модель: как код достаёт и меняет данные

Чтобы читать прикладной код, держите в голове тройку «менеджер → ссылка → объект». Это ядро объектной модели 1С.

  • Менеджер — точка входа к данным вида: Справочники.Контрагенты, Документы.РеализацияТоваровУслуг. Через него ищут и создают записи.
  • Ссылка — указатель на конкретную запись. По ссылке можно читать реквизиты, но нельзя менять.
  • Объект — «живая» запись, полученная через .ПолучитьОбъект(). Только объект можно изменить и записать.
// Нашли ссылку через менеджер
Контрагент = Справочники.Контрагенты.НайтиПоНаименованию("Ромашка");

Если Не Контрагент.Пустая() Тогда
    // Чтобы менять — получаем объект
    ОбъектКонтрагент = Контрагент.ПолучитьОбъект();
    ОбъектКонтрагент.Комментарий = "Проверен";
    ОбъектКонтрагент.Записать();
КонецЕсли;

Когда видите в коде .Пустая() — это проверка «ссылка ни на что не указывает» (запись не найдена). Метод НайтиПоНаименованию или НайтиПоКоду возвращает именно ссылку, поэтому проверка на пустоту обязательна.

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

Для Каждого СтрокаТовара Из Документ.Товары Цикл
    Сумма = Сумма + СтрокаТовара.Количество * СтрокаТовара.Цена;
КонецЦикла;

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

Язык запросов внутри кода

Большие объёмы данных в 1С читают не циклами по базе, а языком запросов. Это отдельный язык внутри встроенного — похож на SQL, но с русскими словами и своими возможностями под учётные регистры.

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

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ
    |   Товары.Номенклатура КАК Номенклатура,
    |   Товары.Количество КАК Количество
    |ИЗ
    |   Документ.РеализацияТоваровУслуг.Товары КАК Товары
    |ГДЕ
    |   Товары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    Сообщить(Выборка.Номенклатура);
КонецЦикла;

Что здесь важно для чтения:

  • Символ | в начале строк — это продолжение строкового литерала, а не часть запроса. Так в коде оформляют многострочный текст.
  • &Ссылка — параметр запроса, его значение подставляют через УстановитьПараметр. Параметры всегда начинаются с &.
  • КАК задаёт псевдоним колонки, по которому к ней обращаются в выборке.

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

Когда видите длинный запрос с ПОМЕСТИТЬ ВременнаяТаблица — это пакетный запрос: сначала собирают промежуточные данные во временную таблицу, потом используют её в следующем запросе пакета. Читается он сверху вниз по частям.

Отладка: как увидеть, что код делает на самом деле

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

  1. Поставьте точку останова — щёлкните на левом поле нужной строки или нажмите F9. Строка отметится кружком.
  2. Запустите 1С:Предприятие в режиме отладки (из Конфигуратора — зелёная стрелка «Начать отладку», F5).
  3. Выполните в программе действие, которое приводит к этому коду (проведите документ, нажмите кнопку). Выполнение остановится на точке.
  4. Дальше шагайте: F11 — зайти внутрь вызываемой процедуры, F10 — выполнить строку не заходя внутрь, F5 — продолжить до следующей точки.

Пока выполнение на паузе, значения переменных смотрят так:

  • Наведите курсор на переменную — всплывёт её текущее значение.
  • Табло — закрепите нужные переменные, чтобы видеть их постоянно.
  • Вычислить выражение (Shift+F9) — посчитайте любое выражение в текущем контексте, разверните структуры и таблицы значений.

Чтобы отладка на сервере работала, в параметрах информационной базы должна быть включена отладка (пункт «Отладка разрешена»). Для клиент-серверного варианта отладку сервера настраивают отдельно. Без этого точки останова в серверных процедурах не сработают.

Ещё один инструмент — замер производительности в Конфигураторе: он показывает, сколько раз выполнилась каждая строка и сколько заняла. Полезно, когда нужно понять не логику, а «где код тормозит».

Порядок разбора незнакомого кода
Выполнено: 0 / 6

Что сбивает с толку новичков

Несколько особенностей, из-за которых код 1С читается неправильно, даже когда синтаксис понятен:

  • 🔀 Код не линейный. Исполнение прыгает между клиентом и сервером, между модулями формы и объекта. Читать «подряд» бесполезно — идите по событиям и вызовам.
  • 0️⃣ Индексы с нуля. Первый элемент массива — [0], последний — [Массив.ВГраница()] или [Массив.Количество() - 1].
  • 🧷 Ссылка ≠ объект. По ссылке читают, объект (.ПолучитьОбъект()) меняют. Путаница здесь ломает понимание всей логики записи.
  • 📦 Невидимая бизнес-логика. Одна строка Записать() или Провести() запускает обработчики, проверки и движения по регистрам, которых в этом модуле не видно.
  • 🧵 Процедуры-обёртки. Часто вызов из формы ведёт в общий модуль, а оттуда — в ещё один. Не пугайтесь глубины: F12 проведёт по цепочке.

Отдельно про запросы: символ | в начале строк и параметры с & новички принимают за ошибки или «мусор». Это штатное оформление многострочного текста запроса.

Проверьте себя
Что означает `.Пустая()` у ссылки на элемент справочника?
Где исполняется процедура с директивой `&НаСервереБезКонтекста`?
Что делает символ `|` в начале строк текста запроса?

Где искать значение команды и документацию

Когда непонятна конкретная команда или метод, не угадывайте — смотрите справку. Основные источники:

  • 📘 Синтакс-помощник — встроенный справочник по всем объектам и методам языка. Открывается в Конфигураторе и EDT из меню Справка. Поставьте курсор на имя метода в коде и вызовите контекстную подсказку — откроется описание с параметрами и примером.
  • ⌨️ Контекстная подсказка редактора. Начните печатать имя объекта и поставьте точку — редактор предложит доступные свойства и методы. Это помогает понять, что за объект перед вами.
  • 🔎 Глобальный поиск по конфигурации. Чтобы найти, откуда вызывается процедура или где используется реквизит, ищите по всей конфигурации (поиск ссылок на объект, поиск по тексту модулей).
  • 🧭 Переход к определению (F12) и список вызывающих процедур — чтобы пройти по цепочке вызовов, не теряя нить.

Для прикладных методов конкретной конфигурации (БСП — Библиотека стандартных подсистем) описание обычно лежит в комментарии над самой процедурой: разработчики библиотеки подробно документируют параметры прямо в коде. Поэтому, встретив вызов библиотечного метода, сначала перейдите к нему через F12 и прочитайте шапку.

Нужно ли знать программирование, чтобы читать код 1С?
Чтобы просто разобраться в логике — нет. Достаточно понять структуру модулей, разницу клиент/сервер и уметь ходить по отладчику. Писать код с нуля — уже отдельный навык.
Чем язык запросов отличается от встроенного языка?
Встроенный язык — это процедуры, циклы и работа с объектами. Язык запросов — отдельный язык внутри него для выборки данных, похожий на SQL. Запрос оформляют строкой, выполняют методом Выполнить() и обходят результат циклом.
Почему код в модуле формы «не видит» базу данных?
Потому что клиентские процедуры (&НаКлиенте) исполняются на компьютере пользователя и не имеют прямого доступа к базе. Чтение данных выносят в серверные процедуры (&НаСервере, &НаСервереБезКонтекста).
Можно ли смотреть код типовой конфигурации без снятия с поддержки?
Да. Код модулей открывается на чтение в Конфигураторе и в режиме отладки в любом случае. Снятие с поддержки нужно только для изменения конфигурации, а не для чтения.
Что быстрее для понимания — читать текст или отладчик?
Для короткого фрагмента — чтение. Для запутанной логики с переходами между модулями надёжнее отладчик: он показывает реальный путь выполнения и фактические значения переменных.