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