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

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

1С: что лучше — функция или процедура

Функция или процедура в 1С: в чём разница, когда что выбирать, типичные ошибки и примеры кода. Практическое руководство для разработчиков 1С.

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

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

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

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

Синтаксически разница минимальна. Функция объявляется ключевым словом «Функция» и завершается «КонецФункции», внутри обязан быть хотя бы один оператор «Возврат <значение>». Процедура объявляется словом «Процедура», завершается «КонецПроцедуры» и может содержать «Возврат» без значения — только для досрочного выхода.

Ключевое поведенческое отличие — место использования. Функцию можно вставить в выражение: присвоить результат переменной, передать в другой метод, использовать в условии «Если». Вызов процедуры — всегда отдельный оператор, его нельзя включить в выражение.

1c
Функция РассчитатьСуммуСНДС(Сумма, СтавкаНДС) Экспорт
	Возврат Сумма + Сумма * СтавкаНДС / 100;
КонецФункции

Процедура ЗаписатьДокумент(ДокументОбъект) Экспорт
	ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры

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

Когда выбирать функцию

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

Типичные сценарии для функций:

  • расчёты: суммы, налоги, скидки, остатки;
  • поиск и получение данных: найти контрагента по ИНН, получить курс валюты, выбрать остатки по складу;
  • проверки условий: «МожноПровестиДокумент», «ЭтоПолноправныйПользователь» — функции, возвращающие Булево;
  • формирование коллекций: массив ссылок, таблица значений, структура настроек.

Функции, возвращающие Булево, особенно удобны в условиях: «Если ПроверитьЗаполнение() Тогда». Такой код читается как фраза на естественном языке. Процедура с аналогичной логикой заставила бы заводить лишнюю переменную-флаг или передавать параметр по ссылке.

Когда выбирать процедуру

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

Характерные примеры процедур:

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

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

Как вернуть несколько значений: функция со структурой или процедура с параметрами

Частая дилемма: метод должен вернуть несколько результатов. В 1С функция возвращает одно значение, но это может быть составной тип — структура, массив или соответствие. Это предпочтительный путь: «Возврат Новый Структура("Успешно, ТекстОшибки, Ссылка", ...)" даёт вызывающему коду весь результат одним объектом.

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

Сравнение вариантов возврата нескольких результатов

Функция, возвращающая структуру

Прозрачно и удобно: все результаты в одном объекте, вызов можно встроить в выражение. Ограничение — нужно знать ключи структуры.

Процедура с параметрами по ссылке

Подходит для обработчиков платформы и совместимости со старым кодом. Минус — неочевидность: параметры меняются неявно, вызов нельзя встроить в выражение.

Функция, возвращающая Булево + параметр-результат

Компромисс для проверок: функция говорит «успешно/нет», детали уходят в параметр. Использовать умеренно.

Ограничения в клиент-серверном режиме и на форме

В управляемых формах директивы компиляции («&НаКлиенте», «&НаСервере», «&НаСервереБезКонтекста») применяются и к процедурам, и к функциям одинаково. Различий по производительности между ними нет — обе одинаково вызывают серверный вызов, если серверный метод вызывается с клиента.

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

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

Как проверить, что выбор сделан правильно

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

Второй тест — имя метода. Функции принято называть так, чтобы имя отвечало на вопрос «что вернёт»: «ПолучитьКурс», «РассчитатьСкидку», «НайтиКонтрагента». Процедуры — глаголом действия: «ЗаполнитьТабличнуюЧасть», «ЗаписатьДанные», «ВывестиСообщение». Если имя метода звучит как действие, но метод возвращает значение, стоит либо переименовать, либо пересмотреть тип метода.

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

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

Вызов метода в коде
Норма

Результат функции присваивается или используется; процедура вызвана отдельным оператором

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

Результат функции игнорируется постоянно — возможно, это должна быть процедура

Тело метода
Норма

Функция всегда завершается возвратом значения на всех ветках

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

Есть ветки без «Возврат» — функция вернёт Неопределено неявно

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

Функция только вычисляет, процедура только действует

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

Функция записывает данные или открывает диалоги

Типичные ошибки при выборе

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

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

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

FAQ

Может ли процедура в 1С вернуть значение?

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

Что быстрее работает — функция или процедура?

Разницы в производительности практически нет: оба вида методов компилируются и выполняются одинаково. На скорость влияют серверные вызовы, обращения к базе данных и объём обрабатываемых данных, а не вид метода.

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

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

Что лучше для обработчиков событий формы?

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

Как вернуть из метода массив или таблицу значений?

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

Нужно ли писать «Экспорт» у функций и процедур?

Ключевое слово «Экспорт» работает одинаково для обоих видов: оно делает метод видимым из других модулей. Добавляйте его только тем методам, которые являются программным интерфейсом модуля; вспомогательные методы оставляйте без «Экспорт».

Итог

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

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