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

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

Чем отличаются функции от процедур в 1С

Разбираем отличия функций от процедур в 1С: возврат значения, контекст вызова, передача параметров, типичные ошибки и примеры кода на встроенном языке.

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

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

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

Синтаксис объявления и возврат значения

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

Критичное отличие — оператор Возврат. В функции он обязан возвращать значение: Возврат СуммаДокумента;. Если функция завершится без возврата значения, результат будет Неопределено, что часто приводит к скрытым ошибкам в вызывающем коде. В процедуре оператор Возврат используется только для досрочного выхода и пишется без значения.

Функция РассчитатьСкидку(Сумма) Экспорт

Если Сумма > 100000 Тогда

Возврат Сумма * 0.1;

КонецЕсли;

Возврат 0;

КонецФункции

Процедура ЗаполнитьКомментарий(Документ) Экспорт

Если Не ЗначениеЗаполнено(Документ.Комментарий) Тогда

Документ.Комментарий = "Создан автоматически";

КонецЕсли;

КонецПроцедуры

Как вызываются функции и процедуры

Функцию можно вставить в любое выражение: присваивание, условие, арифметическую операцию или параметр другого вызова. Например: Итого = РассчитатьСкидку(Сумма) + Доставка;. Это делает функции удобными для вычислений и проверок.

Процедура вызывается только как самостоятельный оператор: ЗаполнитьКомментарий(Документ);. Попытка использовать процедуру в выражении вида Результат = ЗаполнитьКомментарий(Документ); приведёт к ошибке компиляции модуля — конфигуратор сообщит об этом ещё до запуска.

Отдельный частый случай — вызов функции как процедуры, когда возвращаемое значение просто игнорируется: НайтиПоКоду("АБ-001");. Технически это допустимо, но такой стиль скрывает от читателя, что у вызова есть результат, и затрудняет отладку.

Типичные ошибки
01
Использование процедуры в выражении — модуль не скомпилируется, конфигурация не обновится
02
Игнорирование результата функции, которая по смыслу должна что-то вернуть (например, успех записи) — ошибки проходят незамеченными
03
Отсутствие Возврата в одной из веток функции — в вызывающий код попадает Неопределено
04
Передача результата через параметр вместо Возврат — код труднее читать и тестировать

Передача параметров: Знач и изменение данных

И функции, и процедуры по умолчанию передают параметры по ссылке: изменение параметра внутри меняет переменную вызывающего кода. Ключевое слово Знач включает передачу по значению — внутри создаётся копия, и оригинал не пострадает.

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

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

bsl
Функция РазобратьСтроку(Строка) Экспорт
    Результат = Новый Структура;
    Результат.Вставить("Код", Лев(Строка, 6));
    Результат.Вставить("Наименование", Сред(Строка, 8));
    Возврат Результат;
КонецФункции

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

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

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

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

Как выбрать: функция или процедура

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

Именование помогает закрепить выбор. Функции называют так, чтобы имя читалось как значение: ПолучитьОстаток(), ЭтоПроведённыйДокумент(), РассчитатьНДС(). Процедуры называют глаголом действия: ЗаполнитьПоОснованию(), УстановитьДоступность().

Маршрут решения

Как выбрать действие

Нужно вычислить и вернуть одно значение (сумма, признак, ссылка)Используйте функцию с Возврат
Нужно вернуть несколько значенийФункция, возвращающая структуру или массив
Нужно выполнить действие без результата (заполнить, установить, вывести)Процедура
Это обработчик события формы или объектаПроцедура — платформа ожидает именно её
Нужен обмен данными между клиентом и сервером с результатомСерверная функция в общем модуле с вызовом сервера

Проверка результата и отладка

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

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

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

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

Все ветки функции завершаются Возврат со значением
Норма

На каждом пути выполнения есть Возврат

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

Есть ветка, где функция завершается молча

Тип возвращаемого значения
Норма

Вызывающий код получает ожидаемый тип (число, строка, ссылка)

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

Приходит Неопределено или значение другого типа

Вызов процедуры
Норма

Вызов оформлен отдельным оператором

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

Процедура стоит в выражении — ошибка компиляции

Побочные эффекты
Норма

Функция не меняет неожиданно переданные объекты

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

После вызова функции изменились данные вызывающего кода

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

Можно ли вызвать функцию и не использовать её результат?

Да, синтаксис это позволяет: вызов записывается как обычный оператор, а возвращаемое значение отбрасывается. Но если функция спроектирована так, что результат важен (например, признак успешной записи), игнорирование результата — источник скрытых ошибок. Лучше явно присвоить результат переменной и проверить его.

Что вернёт функция, если в ней нет оператора Возврат?

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

Может ли процедура изменить переданный ей параметр?

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

Почему обработчики событий в 1С — процедуры, а не функции?

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

Что лучше для возврата нескольких значений — процедура с параметрами или функция?

Функция, возвращающая структуру с именованными полями. Такой вариант читается на месте вызова, легко расширяется новыми полями и не ломает существующий код. Процедуры с «выходными» параметрами затрудняют чтение, потому что изменение переменных не видно в строке вызова.

Отличается ли скорость работы функций и процедур?

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

Итог

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

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