Встроенный язык платформы 1С:Предприятие 8 является объектно-ориентированным, но при этом сохраняет простоту и ясность синтаксиса, характерную для процедурных языков. При разработке конфигураций программист постоянно сталкивается с необходимостью написания подпрограмм, которые позволяют структурировать код и избегать дублирования логики. Основными строительными блоками здесь выступают две конструкции: процедура и функция.

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

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

Концептуальные различия и назначение

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

В свою очередь, функция создается для вычисления и возврата конкретного значения. Это значение может быть любого типа данных 1С: числом, строкой, ссылкой на объект или даже структурой. Функция отвечает на вопрос "сколько?" или "какое?", тогда как процедура отвечает на вопрос "что сделать?". Использование функции в качестве самостоятельной инструкции без присваивания результата переменной синтаксически возможно, но считается дурным тоном и нарушает логику читаемости кода.

1С:Предприятие строго следит за типами возвращаемых данных, если они объявлены в описании функции. Это позволяет среде разработки подсказывать разработчику доступные методы и свойства полученного результата. В процедурах такой механизм отсутствует, так как там просто нет возвращаемого значения для типизации.

⚠️ Внимание: Попытка использовать результат выполнения процедуры в выражении (например, в условии Если или при присваивании) приведет к синтаксической ошибке на этапе компиляции модуля.

💡

Используйте глаголы в названии процедур (ЗаписатьДокумент) и существительные или прилагательные в названии функций (ПолучитьСумму, ЭтоНовый), чтобы код читался как естественный язык.

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

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

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

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

Функция РассчитатьНДС(Сумма)

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

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

КонецЕсли;

Возврат 0;

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

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

☑️ Проверка корректности функции

Выполнено: 0 / 4

Обработка исключительных ситуаций

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

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

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

  • 🛑 Ошибка в процедуре может быть перехвачена внешним блоком Попытка без последствий для целостности данных, если логика это предусматривает.
  • ⚠️ Ошибка в функции, используемой в выражении присваивания, может привести к аварийному завершению скрипта, если не предусмотрен механизм "безопасного возврата".
  • ✅ Всегда проверяйте возвращаемое значение функции перед его использованием, особенно если внутри нее есть работа с базой данных или файловой системой.

⚠️ Внимание: Не используйте функции для выполнения действий с побочными эффектами (запись в базу, отправка запросов), если результат этих действий не является возвращаемым значением. Это нарушает принцип предсказуемости кода.

Почему нельзя прерывать функцию без возврата?

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

Параметры и передача данных по ссылке

Обе конструкции поддерживают передачу параметров как по значению, так и по ссылке. Механизм передачи аргументов не зависит от того, является ли подпрограмма функцией или процедурой. Ключевое слово Знач перед именем параметра указывает на передачу копии значения, что защищает исходную переменную от изменений внутри подпрограммы.

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

Функции же ориентированы на возврат одного значения. Конечно, этим значением может быть Структура или Массив, содержащий множество полей, но синтаксически это все равно один объект. Использование функций для изменения входных параметров по ссылке допустимо, но снижает читаемость кода, так как нарушает ожидание "чистоты" функции.

Характеристика Процедура Функция
Возврат значения Нет Обязательно (или Неопределено)
Использование в выражениях Запрещено Разрешено
Основная цель Действие (Command) Вычисление (Query)
Реакция на ошибку Прерывание выполнения Требует осторожности с возвратом
📊 Что вы чаще используете в своих обработках?
Только процедуры
Только функции
Смешанный подход
Зависит от задачи

Особенности вызова в разных контекстах

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

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

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

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

💡

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

Рекомендации по архитектуре кода

Для поддержания высокого качества кода в больших проектах на 1С:Предприятие 8 следует придерживаться строгих правил разделения ответственности. Функции должны быть "чистыми": они не должны менять глобальное состояние, писать в логи или модифицировать объекты базы данных, если это не является их прямым возвращаемым результатом. Это упрощает тестирование и повторное использование кода.

Процедуры же выступают в роли оркестраторов. Они вызывают функции для получения данных, принимают решения на основе этих данных и инициируют изменения в системе. Такая архитектура, известная как CQS (Command Query Separation), делает код прозрачным и легким для поддержки другими разработчиками.

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

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

Нет, синтаксис языка 1С строго запрещает использование процедуры там, где ожидается значение. Попытка написать Если МояПроцедура() Тогда вызовет ошибку компиляции.

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

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

Влияет ли тип подпрограммы на производительность?

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

Может ли функция принимать параметры по ссылке?

Да, механизм передачи параметров (по значению или по ссылке) одинаков для функций и процедур. Ключевое слово Знач работает идентично в обоих случаях.

Как правильно называть функции и процедуры?

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