В экосистеме 1С:Предприятие создание качественного и поддерживаемого кода невозможно без четкого понимания архитектуры подпрограмм. Начинающие разработчики часто сталкиваются с путаницей, когда пытаются выбрать между созданием процедуры или функции. Это фундаментальное различие определяет не только то, как будет выглядеть ваш код, но и то, как платформа будет обрабатывать результат выполнения блока команд.
Основное различие кроется в назначении этих подпрограмм. Если вам нужно выполнить серию действий, которых не требует немедленного использования в выражении (например, запись данных в базу или вывод сообщения), используется один тип. В случае, когда необходимо получить вычисленное значение для дальнейших расчетов, применяется другой механизм. Ключевое отличие — наличие возвращаемого значения у функции и его полное отсутствие у процедуры.
Понимание этих нюансов позволяет писать более читаемый код, избегать лишних переменных и соблюдать стандарты разработки платформы. В этой статье мы детально разберем синтаксические особенности, правила вызова и сценарии использования обоих типов подпрограмм в модулях конфигурации.
Синтаксические различия и объявление подпрограмм
В языке 1С:Предприятие объявление любой подпрограммы начинается с ключевого слова, определяющего её тип. Для процедур это слово Процедура (или Procedure в английском синтаксисе), а для функций — Функция (Function). Это первое, на что обращает внимание компилятор при разборе модуля.
Структура объявления функции обязательно подразумевает наличие возвращаемого значения. Даже если вы не планируете использовать результат, синтаксис требует указать имя функции как переменную, которой присваивается результат перед завершением работы. В теле процедуры такое присваивание имени самой процедуре вызовет ошибку компиляции, так как у неё нет возвращаемого значения.
Рассмотрим базовый пример объявления. В процедуре мы просто выполняем действия, а в функции обязательно должна быть строка с возвратом результата. Это строгое правило платформы, нарушение которого приведет к тому, что код просто не запустится.
Процедура ВывестиСообщение(Текст)
Сообщить(Текст);
КонецПроцедуры
Функция РассчитатьНДС(Сумма)
Результат = Сумма * 0.20;
Возврат Результат;
КонецФункции
Механизм возврата значений и область видимости
Главная миссия функции — вернуть значение в точку вызова. Это позволяет использовать её непосредственно в выражениях, присваиваниях или условиях. Например, вы можете написать условие Если РассчитатьНДС(100) > 20 Тогда, и платформа корректно обработает этот вызов, подставив полученное число.
Процедура же работает по принципу «сделал и забыл». Она не возвращает значение, поэтому её нельзя использовать в правой части оператора присваивания или в условиях. Попытка написать Переменная = МояПроцедура приведет к ошибке выполнения, так как интерпретатор не поймет, что записывать в переменную.
Используйте функцию, если результат вычислений нужен для дальнейшей логики. Используйте процедуру, если важно само действие (запись, отправка, удаление).
Однако, процедура может изменять значения переменных, переданных ей по ссылке. Если в параметрах процедуры указать ключевое слово Знач отсутствует, то изменение параметра внутри процедуры повлияет на переменную, переданную извне. Функции также могут менять переданные параметры, но их основной целью остается формирование возвращаемого значения.
Функция возвращает значение через оператор"Возврат", процедура выполняет действия и завершает работу без явного возврата данных.
Правила вызова и использование в коде
Способ вызова подпрограммы напрямую зависит от её типа. Функцию можно вызывать двумя способами: как отдельную инструкцию (если вам не важен результат, хотя это считается дурным тоном) или как часть выражения. Процедура вызывается только как отдельная инструкция.
При вызове функции в качестве параметра другой функции или процедуры, вычисления происходят мгновенно. Это создает цепочки вызовов, которые могут быть мощным инструментом, но требуют осторожности. Если функция вызывает другую функцию, которая вызывает третью, стек вызовов растет, что может повлиять на производительность при глубокой вложенности.
- 🔹 Вызов процедуры:
ОбновитьРеквизиты(Документ) - 🔹 Вызов функции в присваивании:
Итог = ПолучитьСумму(Заказ) - 🔹 Вызов функции в условии:
Если ПроверитьПрава(Пользователь) Тогда..
Если выражение становится слишком громоздким, лучше разбить его на несколько шагов с использованием промежуточных переменных. Это упростит отладку и понимание логики работы программы.
Передача параметров: по значению и по ссылке
Оба типа подпрограмм поддерживают гибкую работу с параметрами. По умолчанию параметры в 1С передаются по ссылке. Это означает, что подпрограмма получает доступ к ячейке памяти исходной переменной. Любое изменение параметра внутри процедуры или функции изменит и исходную переменную.
Для предотвращения случайного изменения исходных данных используется модификатор Знач. При его указании создается копия значения, и работа ведется уже с этой копией. Исходная переменная остается неизменной. Это критически важно при работе с объектными типами данных, такими как СправочникОбъект или ДокументОбъект.
⚠️ Внимание: При передаче объектов по ссылке (без слова"Знач") изменение реквизитов объекта внутри подпрограммы сохранится после её завершения. Если вы не планировали менять объект, обязательно используйте модификатор.
Использование необязательных параметров также доступно для обоих типов. Вы можете задать значение по умолчанию в скобках при объявлении. Это позволяет делать код более универсальным и сокращает количество перегруженных версий одних и тех же подпрограмм.
Сравнительная таблица характеристик
Для быстрого ориентирования в различиях удобно использовать сводную таблицу. Она наглядно демонстрирует, где и как применяются различные конструкции языка 1С:Предприятие.
| Характеристика | Процедура | Функция |
|---|---|---|
| Ключевое слово объявления | Процедура |
Функция |
| Возврат значения | Нет | Обязательно (оператор Возврат) |
| Использование в выражениях | Запрещено | Разрешено |
| Основное назначение | Выполнение действий | Вычисление результата |
| Присваивание имени подпрограммы | Ошибка компиляции | Формирует результат |
Как видно из таблицы, различия носят системный характер. Платформа строго разделяет эти сущности на этапе компиляции модуля. Понимание этих различий помогает избегать типовых ошибок, таких как попытка присвоить результат процедуры переменной.
Тонкости работы с Неопределено
Функция может вернуть значение Неопределено, если оператор Возврат вызван без параметра или поток выполнения дошел до КонецФункции без явного возврата. Процедура в этом плане ведет себя предсказуемо — она просто завершается.
Рекомендации по выбору типа подпрограммы
Выбор между процедурой и функцией должен диктоваться логикой задачи. Если ваша подпрограмма должна ответить на вопрос «Сколько?» или «Какой?», это однозначно функция. Если же она отвечает на вопрос «Что сделать?», то следует использовать процедуру.
Частой ошибкой является создание функций, которые ничего не возвращают, а только выполняют действия. Такой код вводит в заблуждение других разработчиков, которые ожидают получить результат. И наоборот, использование процедур там, где нужно вычисление, заставляет создавать лишние глобальные переменные или параметры-ссылки для получения результата.
☑️ Чек-лист выбора подпрограммы
Соблюдение чистоты кода требует, чтобы функции не имели побочных эффектов. Идеальная функция принимает данные, вычисляет результат и возвращает его, не меняя глобальных переменных или параметров (если они не переданы специально для изменения). Процедуры же часто предназначены именно для изменения состояния системы.
⚠️ Внимание: Избегайте вызова функций, изменяющих данные в базе, внутри условий отборов запросов или вычисляемых полей. Это может привести к непредсказуемому поведению и блокировкам.
Частые ошибки и лучшие практики
Одной из распространенных проблем является чрезмерная вложенность. Когда функция вызывает другую функцию, которая вызывает третью, цепочка становится непрозрачной. Старайтесь держать уровень вложенности под контролем. Если функция становится слишком большой, разбейте её на несколько более мелких подпрограмм.
Также стоит упомянуть о рекурсии. И процедуры, и функции могут вызывать сами себя. Однако в 1С глубина стека ограничена. Бесконечная рекурсия быстро приведет к ошибке «Превышена глубина рекурсии». Всегда предусматривайте условие выхода из рекурсивного вызова.
- ✅ Называйте функции глаголами совершенного вида с существительным (например,
ПолучитьСумму). - ✅ Называйте процедуры глаголами повелительного наклонения (например,
ЗаписатьДанные). - ✅ Избегайте скрытых зависимостей от глобальных переменных внутри подпрограмм.
Использование префиксов в именах помогает мгновенно определить тип подпрограммы при чтении кода. Это особенно полезно в больших конфигурациях, где над одним модулем работают несколько разработчиков. Стандартизация именования — признак зрелости команды разработки.
Можно ли вызвать процедуру внутри выражения?
Нет, это вызовет ошибку компиляции. Процедура не возвращает значения, поэтому платформа не может подставить результат в выражение. Используйте только как отдельную инструкцию.
Что будет, если в функции не написать оператор Возврат?
Функция завершит работу и вернет значение Неопределено. Это не является ошибкой компиляции, но может привести к логическим ошибкам в коде, который ожидает конкретный тип данных.
Влияет ли тип подпрограммы на производительность?
Сами по себе процедура и функция работают с одинаковой скоростью. Разница в производительности возникает только от логики, которую вы в них закладываете, и от количества передаваемых параметров.
Может ли функция изменять переданные параметры?
Да, если параметры не объявлены с ключевым словом Знач. Они передаются по ссылке, и любые изменения внутри функции отразятся на исходных переменных.