Как правильно выбрать между процедурой и функцией в 1С: стандарты чистого кода

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Принцип разделения команд и запросов (CQS)

Рассмотрим фундаментальный принцип программирования — Command-Query Separation (CQS). Согласно этому подходу, каждый метод должен быть либо командой, выполняющей действие, либо запросом, возвращающим данные. Проанализируем, как это соотносится с синтаксисом 1С:

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

Следование этому правилу делает ваш код предсказуемым. Когда другой разработчик видит вызов функции, он уверен, что данные не будут «тихо» изменены внутри метода.

Сравнение подходов: возврат значения vs изменение параметров

Разберем пример, предложенный автором темы. Существует два способа получения скидки. Проанализируем их с точки зрения читаемости и надежности.

Вариант 1: Использование функции (Рекомендуется)


&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    ТекущаяСтрока.Скидка = ПолучитьСкидкуНоменклатуры(ТекущаяСтрока.Номенклатура);
КонецПроцедуры 

&НаСервереБезКонтекста
Функция ПолучитьСкидкуНоменклатуры(Знач Номенклатура)
    Возврат Номенклатура.ОсновнаяСкидка;
КонецФункции

Вариант 2: Изменение параметра в процедуре (Антипаттерн)


&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
    Номенклатура = Элементы.Товары.ТекущиеДанные.Номенклатура; 
    ПолучитьСкидкуНоменклатуры(Номенклатура);
    // Теперь в переменной "Номенклатура" внезапно оказалось число (скидка)
    Элементы.Товары.ТекущиеДанные.Skidka = Номенклатура;
КонецПроцедуры 

&НаСервере
Процедура ПолучитьСкидкуНоменклатуры(Номенклатура)
    Номенклатура = Номенклатура.ОсновнаяСкидка; 
КонецПроцедуры 

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

Использование структур для возврата множества значений

Иногда методу требуется вернуть не одно значение, а несколько (например, цену, процент скидки и вид налога). Вместо того чтобы создавать процедуру с пятью выходными параметрами, рассмотрим более изящное решение — использование объекта Структура.

Проанализируем пример универсальной функции, которая возвращает результат выполнения и описание ошибки:


Функция РассчитатьПараметрыПродажи(Номенклатура, Количество) Экспорт
    Результат = Новый Структура;
    Результат.Вставить("Успех", Ложь);
    Результат.Вставить("Цена", 0);
    Результат.Вставить("Сумма", 0);
    Результат.Вставить("СообщениеОбОшибке", "");

    Если Номенклатура.Пустая() Тогда
        Результат.СообщениеОбОшибке = "Не выбрана номенклатура";
        Возврат Результат;
    КонецЕсли;

    // Логика расчета...
    Результат.Успех = Истина;
    Результат.Цена = 100;
    Результат.Сумма = 100 * Количество;

    Возврат Результат;
КонецФункции

Этот подход позволяет легко расширять возвращаемые данные без изменения сигнатуры (количества параметров) метода. Вызывающий код становится чище, так как работа с результатом идет через обращение к свойствам структуры.

Ключевое слово Знач и безопасность данных

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

Рассмотрим преимущества Знач:

Стандарты именования

Для того чтобы выбор между процедурой и функцией был понятен с первого взгляда, придерживайтесь стандартов именования фирмы «1С»:

  1. Для процедур: Начинайте имя с глагола в неопределенной форме (РассчитатьНалоги(), ЗаполнитьПоУмолчанию(), УдалитьВременныеФайлы()).
  2. Для функций: Используйте существительные или глаголы, подчеркивающие получение результата (ТекущаяЦена(), СформироватьСтруктуруОшибки(), ПолучитьМакетСервера()).
  3. Для логических функций: Используйте префиксы-вопросы (ЭтоНовыйДокумент(), ДокументПроведен(), ПроверитьЗаполнениеФормы()).

Когда процедура все же лучше?

Несмотря на преимущества функций, процедуры остаются незаменимыми в следующих случаях:

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

← На главную