Чтение кода на встроенном языке 1С: с чего начать и как не утонуть в чужом модуле

· 9 мин

Содержание

Чтение кода в 1С начинается не с первой строки модуля, а с ответа на три вопроса: где этот код лежит, на клиенте он выполняется или на сервере и кто его вызывает. Открыли процедуру ПриПроведении в модуле документа — значит, вы в серверном коде, который отрабатывает при записи с проведением. Эти три координаты важнее, чем понимание каждой строчки.

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

Почему код в 1С читается не как обычная программа

Главная сложность — не русский синтаксис (Если … Тогда … КонецЕсли), к нему привыкаешь за день. Сложность в модели исполнения и в том, что код физически раздроблен.

Что мешает читать 1С-код линейно:

  • 🧩 Код живёт в разных модулях. Логика справочника «Контрагенты» размазана по модулю объекта, модулю менеджера, модулю формы, общим модулям и, возможно, расширению конфигурации. Одного файла, где «всё про контрагента», не существует.
  • 🖥️ Клиент и сервер вперемешку. Одна процедура формы выполняется в браузере пользователя, соседняя — на сервере. Переход между ними стоит сетевого вызова, и это меняет смысл кода.
  • 🔁 Обработчики, а не главная функция. Точки входа тут нет. Платформа сама дёргает процедуры-обработчики событий: ПередЗаписью, ОбработкаПроведения, ПриИзмененииРеквизита. Чтобы понять «что запускается», надо знать, какое событие сработало.
  • 🏷️ Одинаковые имена в разных местах. Процедура ЗаполнитьДокумент() может быть и в модуле объекта, и в общем модуле, и в расширении. Пока не поймёте, из какого модуля идёт вызов, читаете не тот код.

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

Карта модулей: где какой код лежит

Прежде чем читать, определите тип модуля — он задаёт правила игры. Основные типы в 1С 8.3:

МодульЧто в нёмКонтекст по умолчанию
Модуль формыОбработчики событий формы и её элементовКлиент (с серверными процедурами)
Модуль объектаПередЗаписью, ОбработкаПроведения, бизнес-логика документа/справочникаСервер
Модуль менеджераМетоды уровня менеджера объекта, общие для всех экземпляровСервер
Общий модульПереиспользуемые процедуры и функцииЗависит от флагов модуля
Модуль приложения / сеансаСобытия запуска и завершения программыКлиент / сервер

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

Как быстро понять тип открытого модуля: посмотрите в дерево конфигурации слева — подсветится объект, которому модуль принадлежит. Либо загляните в заголовок окна: Конфигуратор пишет путь вроде Документы.РеализацияТоваровУслуг.МодульОбъекта.

Директивы компиляции: как отличить клиент от сервера

Перед каждой процедурой и функцией в управляемых формах стоит директива — это первое, что нужно читать:

&НаКлиенте
Процедура ЦенаПриИзменении(Элемент)
    ПересчитатьСумму();
КонецПроцедуры

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ЗаполнитьРеквизитыПоУмолчанию();
КонецПроцедуры

Что означают директивы:

  • &НаКлиенте — код работает на машине пользователя. Отсюда нельзя напрямую обратиться к базе данных.
  • &НаСервере — код работает на сервере, имеет доступ к базе, но при вызове туда-обратно передаётся весь контекст формы (это дорого по времени).
  • &НаСервереБезКонтекста — серверный код без передачи данных формы. Быстрее; его в типовых конфигурациях большинство.
  • &НаКлиентеНаСервереБезКонтекста — доступен и там, и там.

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

Ещё один маркер — инструкции препроцессора. Конструкция #Если Сервер Тогда … #КонецЕсли в общем модуле означает, что кусок кода компилируется только на сервере. Не пропускайте эти блоки: один и тот же модуль может вести себя по-разному на клиенте и сервере.

С чего начать разбор незнакомого модуля

Не читайте модуль сверху вниз как книгу — это и есть главный антипаттерн. Двигайтесь от задачи.

  1. Сформулируйте вопрос. «Почему при проведении не заполняется счёт учёта?» — конкретная цель экономит часы. Чтение «вообще» бесполезно.
  2. Найдите точку входа. Для документа это обычно ОбработкаПроведения в модуле объекта. Для поведения формы — обработчик события нужного элемента в модуле формы.
  3. Идите по вызовам вглубь. Встретили вызов ЗаполнитьСчетаУчета() — перейдите к определению этой процедуры (клавиша F12 на имени) и читайте её. Так вы разворачиваете только нужную ветку, а не весь модуль.
  4. Отмечайте границы клиент/сервер. Каждый переход между контекстами — повод остановиться и понять, какие данные передаются.
  5. Сверяйтесь с именами. Разработчики 1С называют процедуры по-русски и по делу: ПроверитьЗаполнение, СформироватьДвижения. Имя часто заменяет чтение тела.

Отдельная ветка — расширения конфигурации . Если над процедурой в основной конфигурации «ничего не происходит», проверьте, нет ли расширения, которое её переопределяет или дополняет через &Вместо или &После. Это частая причина, почему код «не тот, что читаешь».

Что проверить, прежде чем менять найденный код
Выполнено: 0 / 6

Навигация в Конфигураторе и EDT

Читать код мышкой и стрелками — медленно. Инструменты навигации ускоряют разбор в разы.

В Конфигураторе пригодятся:

  • Переход к определению — поставьте курсор на имя процедуры и нажмите F12. Откроется её тело, даже если оно в другом модуле.
  • Поиск ссылок на объект — контекстное меню на имени реквизита, справочника или процедуры. Показывает, где по всей конфигурации используется элемент. Незаменимо, чтобы понять, кто дёргает код.
  • Глобальный поиск — меню Правка → Глобальный поиск. Ищет строку по всем модулям конфигурации, а не только в открытом.
  • Синтакс-помощник — встроенный справочник по методам платформы. Поставьте курсор на метод вроде НайтиПоКоду и вызовите контекстную подсказку, чтобы увидеть параметры.
  • Контекстная подсказка — сочетание Ctrl + Пробел показывает доступные свойства и методы объекта. Заодно помогает понять, с каким типом вы работаете.
  • Группировка областями — код оформляют блоками #Область … #КонецОбласти. Сверните все области, чтобы увидеть структуру модуля целиком, потом разворачивайте нужную.

В 1C:Enterprise Development Tools (EDT) — альтернативной среде на базе Eclipse — навигация богаче: переход к объявлению по F3, поиск использований, автоматическое построение структуры модуля, подсветка, рефакторинг. Для чтения больших объёмов чужого кода EDT ощутимо удобнее Конфигуратора, хотя типовые доработки чаще ведут именно в Конфигураторе.

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

Отладка: чтение кода в движении

Статическое чтение показывает, что код делает в теории. Отладчик показывает, что он делает на самом деле и с какими данными. Это самый быстрый способ понять незнакомую логику.

Базовый сценарий разбора через отладку:

  1. Поставьте точку останова на интересующей строке — клавиша F9 или щелчок по левому полю редактора.
  2. Запустите приложение в режиме отладки — меню Отладка → Начать отладку (F5).
  3. Выполните в программе действие, которое приводит к этому коду (например, проведите документ).
  4. Когда выполнение остановится, читайте табло и локальные переменные — там реальные значения.
  5. Шагайте по коду: F10 — выполнить строку, не заходя внутрь вызовов; F11 — зайти в вызываемую процедуру; Shift + F11 — выйти из текущей.

Два инструмента, которые экономят больше всего времени:

  • Стек вызовов — показывает цепочку процедур, которая привела в текущую точку. Отвечает на вопрос «кто меня вызвал» лучше любого чтения.
  • Вычислить выражение — позволяет прямо на паузе посчитать любое выражение в текущем контексте, например Строка.Количество * Строка.Цена, и проверить гипотезу.

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

Разбор реального фрагмента

Посмотрим на простую функцию и прочитаем её так, как это делает специалист:

Функция СуммаДокумента(ТабличнаяЧасть) Экспорт
    Итог = 0;
    Для Каждого Строка Из ТабличнаяЧасть Цикл
        Итог = Итог + Строка.Количество * Строка.Цена;
    КонецЦикла;
    Возврат Итог;
КонецФункции

Как это читается по шагам:

  • Функция … Экспорт — это функция (возвращает значение), а ключевое слово Экспорт означает, что её можно вызвать из других модулей. Значит, где-то есть вызов извне — стоит поискать ссылки.
  • ТабличнаяЧасть — параметр. По имени понятно: внутрь передают табличную часть документа (например, «Товары»).
  • Для Каждого Строка Из … Цикл — обход всех строк коллекции. Строка на каждой итерации — это текущая строка таблицы.
  • Строка.Количество * Строка.Цена — обращение к колонкам табличной части по именам реквизитов. Тут же становится ясно, что у таблицы есть колонки Количество и Цена.
  • Возврат Итог — функция отдаёт накопленную сумму.

Вывод за тридцать секунд: функция считает сумму документа как количество × цену по всем строкам. Чтобы убедиться, что колонки называются именно так, достаточно открыть табличную часть документа в дереве конфигурации — читать всё тело не нужно.

Отдельно стоит язык запросов: если в коде встречается Запрос.Текст = "ВЫБРАТЬ …", это не процедурный код, а декларативный запрос к базе. Его читают по блокам ВЫБРАТЬ … ИЗ … ГДЕ …, а разбирать удобнее в конструкторе запросов (контекстное меню на тексте запроса).

Частые ошибки при чтении кода

На чём спотыкаются чаще всего:

  • ❌ Путают клиент и сервер. Читают процедуру под &НаКлиенте и ждут обращения к базе — а его там быть не может. Всегда смотрите директиву над процедурой.
  • ❌ Читают не тот модуль. Нашли процедуру с нужным именем в общем модуле, а вызывается одноимённая из модуля объекта. Сначала через стек вызовов или поиск ссылок убедитесь, что это тот самый код.
  • ❌ Не замечают расширение. Код в основной конфигурации выглядит правильным, но поведение меняет расширение через &Вместо. Проверяйте список расширений.
  • ❌ Пытаются понять всё сразу. Читают модуль целиком вместо того, чтобы идти по одной ветке вызовов от конкретной задачи.
  • ❌ Игнорируют препроцессор. Пропускают блоки #Если Сервер Тогда, не понимая, что часть кода на клиенте просто не компилируется.
  • ❌ Не пользуются F12 и поиском ссылок. Листают модули вручную вместо перехода к определению — теряют время на каждом вызове.

Если код совсем не поддаётся чтению глазами, не упорствуйте — ставьте точку останова и смотрите реальные данные. Пять минут в отладчике часто заменяют час чтения.

Частые вопросы

Нужно ли знать программирование, чтобы читать код 1С?
Базовое понимание переменных, условий и циклов необходимо. Но синтаксис встроенного языка русский и несложный — многое читается «по словам». Главное — разобраться в структуре модулей и модели клиент-сервер, а не в синтаксисе.
Где лучше читать код — в Конфигураторе или в EDT?
Для разовой доработки и быстрого просмотра хватает Конфигуратора. Для долгого разбора большого объёма чужого кода EDT удобнее: богаче навигация, поиск использований и построение структуры. Типовые изменения конфигурации чаще делают в Конфигураторе.
Как понять, кто вызывает процедуру?
Два способа. Статически — контекстное меню «Поиск ссылок на объект» по имени процедуры. Динамически — поставить точку останова и посмотреть стек вызовов в отладчике: он покажет всю цепочку вызовов до текущей точки.
Почему одна и та же процедура ведёт себя по-разному?
Чаще всего причина — расширение конфигурации, которое переопределяет метод через &Вместо или дополняет через &После. Либо вы читаете одноимённую процедуру из другого модуля. Проверьте и то, и другое.
Можно ли отлаживать серверный код в клиент-серверной базе?
Да, но отладку нужно разрешить: включить её в параметрах информационной базы и подключить предметы отладки через меню Отладка → Подключение. В файловой базе отладка доступна сразу.