Разработка и Конфигурация · 10 мин
Процедуры и функции во встроенном языке 1С: в чём разница и как выбрать
Разбираем отличия процедур и функций во встроенном языке 1С: возвращаемое значение, контекст вызова, параметры, типичные ошибки и рекомендации по выбору.
Во встроенном языке 1С:Предприятие существуют два способа оформить повторно используемый блок кода — процедура и функция. Синтаксически они почти идентичны: обе объявляются в модуле, обе могут принимать параметры и содержать любые операторы. Принципиальное отличие одно: функция возвращает значение, а процедура — нет. Из этого единственного различия вытекают все правила вызова, ограничения контекста и рекомендации по выбору.
Ошибка в выборе между процедурой и функцией не всегда приводит к аварийному завершению, но почти всегда делает код менее читаемым и провоцирует ошибки у тех, кто будет использовать ваш метод позже. Например, если метод по смыслу вычисляет итог по табличной части, но оформлен как процедура с параметром-результатом, его нельзя использовать в выражении — придётся писать лишние строки и промежуточные переменные.
Ниже разобраны синтаксис объявления, правила вызова, поведение параметров, контекстные ограничения и практические критерии выбора, а также типичные ошибки начинающих разработчиков 1С.
Как объявляются процедуры и функции
Объявление начинается с ключевого слова Процедура или Функция, за которым следует имя и список параметров в круглых скобках. Завершается блок ключевыми словами КонецПроцедуры или КонецФункции соответственно. Если метод должен быть доступен из других модулей, после списка параметров добавляется ключевое слово Экспорт.
Функция РассчитатьСуммуСНДС(Сумма, СтавкаНДС) Экспорт
Возврат Сумма + Сумма * СтавкаНДС / 100;
КонецФункции
Процедура ЗаполнитьТабличнуюЧасть(ДокументОбъект) Экспорт
// действия с объектом
КонецПроцедуры
Имя метода должно быть уникальным в пределах модуля: нельзя объявить процедуру и функцию с одинаковым именем в одном модуле. Платформа проверяет это при сохранении модуля и выдаёт ошибку компиляции. Параметры у обоих видов методов описываются одинаково: через запятую, с возможностью указать значение по умолчанию и модификатор Знач.
Директивы компиляции (&НаКлиенте, &НаСервере, &НаСервереБезКонтекста и другие) ставятся перед объявлением и одинаково применимы к процедурам и функциям. Они определяют, в каком контексте код будет исполняться, и не зависят от вида метода.
Возвращаемое значение — главное отличие
Функция обязана вернуть значение оператором Возврат. Если оператор указан без выражения (Возврат;) или выполнение дошло до КонецФункции без оператора возврата, функция вернёт значение Неопределено. Это частый источник скрытых ошибок: код не падает, но результат вычисления неожиданно пустой.
Процедура тоже может содержать оператор Возврат;, но только без выражения — он используется для досрочного выхода из метода. Попытка написать Возврат Результат; внутри процедуры вызовет ошибку компиляции.
Из-за возвращаемого значения функцию можно встраивать в выражения: присваивать результат переменной, передавать как аргумент другого метода, использовать в условии Если. Процедура в выражении стоять не может — это ошибка синтаксиса.
Правила вызова: где допустимы процедуры, а где функции
Процедура вызывается отдельным оператором: имя, скобки с аргументами, точка с запятой. Функция может вызываться так же, как процедура, — отдельным оператором без использования результата. Платформа это разрешает, возвращаемое значение просто отбрасывается. Однако злоупотреблять таким вызовом не стоит: если метод спроектирован как функция, игнорирование результата часто означает, что вы теряете информацию об ошибке или итоге операции.
Обратное невозможно. Строка Результат = МояПроцедура(Параметр); не скомпилируется, потому что процедура не является выражением и не производит значения.
// Корректно
Итог = РассчитатьСуммуСНДС(10000, 20);
ЗаполнитьТабличнуюЧасть(Объект);
// Тоже допустимо, но результат потерян
РассчитатьСуммуСНДС(10000, 20);
// Ошибка компиляции
Итог = ЗаполнитьТабличнуюЧасть(Объект);
Отдельный случай — обработчики событий форм и объектов. Подписки на события и обработчики ожидания всегда оформляются процедурами, потому что платформа вызывает их как действие и не ожидает возвращаемого значения. Если назначить функцию обработчиком оповещения, результат её работы будет проигнорирован.
Параметры и передача данных
Механизм параметров у процедур и функций идентичен. По умолчанию параметры передаются по ссылке: изменения значения внутри метода видны в вызывающем коде. Модификатор Знач заставляет платформу передать копию значения, и изменения внутри метода не затронут исходную переменную.
Важное ограничение: при вызове серверного метода с клиента параметры должны быть сериализуемыми — нельзя передать, например, объект типа ДокументОбъект, допустимы ссылки, примитивные типы и структуры. Это правило одинаково для процедур и функций, но для функций добавляется требование: возвращаемое значение с сервера на клиент также должно быть сериализуемым.
Поскольку параметры передаются по ссылке, технически процедура может «вернуть» результат через параметр. Такой подход допустим, когда нужно вернуть несколько значений, но для единственного результата предпочтительнее функция — она делает намерение кода очевидным.
Контекст выполнения и директивы компиляции
В тонком клиенте и веб-клиенте код распределяется между клиентом и сервером. Директивы &НаСервереБезКонтекста применимы только к методам модуля формы и одинаково работают для процедур и функций. Различий в доступности директив между видами методов нет — ограничения задаёт контекст, а не вид метода.
Асинхронная модель тоже не делает различий: и процедуры, и функции могут быть объявлены с ключевым словом Асинх и содержать оператор Ждать. Асинхронная функция возвращает значение через механизм обещаний, асинхронная процедура просто выполняет действия.
Как выбрать: процедура или функция
Основной критерий — смысловой. Если метод отвечает на вопрос и производит результат (вычисляет сумму, проверяет условие, подбирает данные), это функция. Если метод выполняет действие над объектом или системой (записывает, заполняет, устанавливает признаки, выводит сообщения), это процедура.
Как выбрать вид метода
Именование помогает поддерживать дисциплину: функции принято называть так, чтобы имя читалось как результат (ПолучитьОстаток, ЭтоПроведённыйДокумент), процедуры — как действие (ЗаписатьДокумент, УстановитьВидимость). Такое соглашение упрощает чтение чужого кода и снижает вероятность неправильного вызова.
Проверка результата и отладка
После написания функции проверьте все ветки исполнения: условия Если, Попытка/Исключение, циклы с досрочным выходом. Убедитесь, что на каждом пути есть возврат осмысленного значения. Удобный приём — объявить переменную результата в начале функции, заполнять её по ходу логики и вернуть один раз в конце.
Для проверки вызовов используйте синтаксическую проверку модуля в конфигураторе: она ловит попытки использовать процедуру в выражении и несоответствие количества параметров. Логические ошибки — например, проигнорированный результат функции — синтаксическая проверка не обнаружит, их выявляет только тестирование сценария.
Как проверить результат
Каждый путь исполнения завершается Возврат с выражением
Есть ветка, где функция завершается без возврата значения
Результат присваивается переменной или используется в выражении
Функция вызывается как процедура и результат теряется
Параметры и возвращаемое значение — ссылки, примитивы, структуры
Передаются объекты данных или таблицы значений
Часто задаваемые вопросы
Можно ли вызвать функцию как процедуру, не используя результат?
Да, платформа это разрешает: функция, вызванная отдельным оператором, выполнится, а возвращаемое значение будет отброшено. Однако если функция возвращает признак успешности операции или код ошибки, такой вызов скрывает важную информацию. Используйте этот приём осознанно, только когда результат действительно не нужен.
Что вернёт функция, если в ней нет оператора Возврат?
Значение Неопределено. Ошибки компиляции не будет, поэтому такая ситуация опасна: вызывающий код получит пустой результат и продолжит работу. Проверяйте, что возврат есть во всех ветках логики, включая обработчики исключений.
Может ли процедура вернуть несколько значений?
Напрямую — нет, процедура вообще не возвращает значений. Но поскольку параметры по умолчанию передаются по ссылке, процедура может изменить несколько переданных переменных, и вызывающий код увидит новые значения. Альтернатива — оформить метод функцией, возвращающей структуру с несколькими полями: это нагляднее и позволяет использовать результат в выражении.
Чем отличается экспортная функция от обычной?
Ключевое слово Экспорт делает метод видимым из других модулей конфигурации. Без него функция или процедура доступна только внутри своего модуля. Экспортными следует делать только те методы, которые составляют осознанный программный интерфейс модуля, — лишняя видимость затрудняет сопровождение.
Можно ли назначить функцию обработчиком события формы?
Технически платформа позволяет выбрать функцию в палитре событий, но возвращаемое значение будет проигнорировано, а в ряде случаев (например, обработчики ожидания и оповещения) сигнатура обработчика строго фиксирована. Правильная практика — оформлять все обработчики событий процедурами.
Есть ли разница в производительности между процедурой и функцией?
Практически нет. Возврат значения — очень дешёвая операция, и выбор вида метода следует делать по смыслу, а не по скорости. Реальное влияние на производительность оказывают клиент-серверные вызовы и объём передаваемых данных, а не вид метода.
Что важно запомнить
Функция возвращает значение и работает в выражениях, процедура выполняет действие и вызывается отдельным оператором. Параметры, директивы компиляции и контекст у них общие. Выбирайте вид метода по смыслу: вычислить — функция, сделать — процедура; обработчики событий — всегда процедуры.