← Назад к вопросам
Что такое повторное использования возвращаемых значений?
2.0 Middle🔥 121 комментариев
#Запросы и оптимизация#Стандарты разработки
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Повторное использование возвращаемых значений в 1С
Повторное использование возвращаемых значений это оптимизирующая техника, при которой результат функции или процедуры сохраняется в переменную и используется несколько раз, вместо повторного вызова функции каждый раз.
Определение
Это паттерн программирования, который:
- Вызывает функцию один раз
- Сохраняет результат в переменную
- Использует эту переменную вместо повторного вызова
- Экономит вычислительные ресурсы
Проблема: повторный вызов функций
// ПЛОХО - функция вызывается 3 раза
Процедура РассчитатьЗарплату()
Если ПолучитьОклад(Сотрудник) > 100000 Тогда
СообщитьОВысокойЗарплате();
КонецЕсли;
Налог = ПолучитьОклад(Сотрудник) * 0.13; // вызов 2
СохранитьРеестр(ПолучитьОклад(Сотрудник)); // вызов 3
// Функция вызвана 3 раза, выполнена 3 раза!
КонецПроцедуры
Решение: кеширование результата
// ХОРОШО - функция вызывается 1 раз
Процедура РассчитатьЗарплату()
// Вызовом функцию один раз и сохранить результат
Оклад = ПолучитьОклад(Сотрудник);
// Использовать результат
Если Оклад > 100000 Тогда
СообщитьОВысокойЗарплате();
КонецЕсли;
Налог = Оклад * 0.13; // используем переменную
СохранитьРеестр(Оклад); // используем переменную
// Функция вызвана 1 раз, в памяти только 1 переменная
КонецПроцедуры
Типы возвращаемых значений для кеширования
1. Скалярные значения (числа, строки)
// Функция возвращает одно число
Функция ПолучитьОклад(Сотрудник) Экспорт
Запрос = Новый Запрос(
"SELECT Оклад FROM Справочник_Сотрудники WHERE Ссылка = &Сотр"
);
Запрос.УстановитьПараметр("Сотр", Сотрудник);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат 0;
КонецЕсли;
Строка = Результат.Выбрать().Первый();
Возврат Строка.Оклад;
КонецФункции
// Повторное использование:
Оклад = ПолучитьОклад(Сотрудник); // один вызов
Зарплата = Оклад * 12; // использование из переменной
Налог = Оклад * 0.13; // использование из переменной
Премия = Оклад * 0.5; // использование из переменной
2. Коллекции (массивы, таблицы)
// Функция возвращает таблицу значений
Функция ПолучитьТовары(Категория) Экспорт
Запрос = Новый Запрос(
"SELECT * FROM Справочник_Товары WHERE Категория = &Кат"
);
Запрос.УстановитьПараметр("Кат", Категория);
ТаблицаТоваров = Запрос.Выполнить().Выгрузить();
Возврат ТаблицаТоваров;
КонецФункции
// ПЛОХО - функция вызывается 3 раза
Для каждого Товар Из ПолучитьТовары(Категория) Цикл // вызов 1
Сообщить(Товар.Наименование);
КонецЦикла;
Отчет.Заполнить(ПолучитьТовары(Категория)); // вызов 2
ЗагрузитьВТеблицу(ПолучитьТовары(Категория)); // вызов 3
// ХОРОШО - функция вызывается 1 раз
Товары = ПолучитьТовары(Категория); // один вызов
Для каждого Товар Из Товары Цикл // используем переменную
Сообщить(Товар.Наименование);
КонецЦикла;
Отчет.Заполнить(Товары); // используем переменную
ЗагрузитьВТеблицу(Товары); // используем переменную
3. Сложные объекты (структуры, соответствия)
// Функция возвращает структуру данных сотрудника
Функция ПолучитьДанныеСотрудника(Сотрудник) Экспорт
ДанныеСотр = Новая Структура();
Запрос = Новый Запрос(
"SELECT Оклад, Должность, Отдел
FROM Справочник_Сотрудники WHERE Ссылка = &Сотр"
);
Запрос.УстановитьПараметр("Сотр", Сотрудник);
Результат = Запрос.Выполнить();
Строка = Результат.Выбрать().Первый();
ДанныеСотр.Вставить("Оклад", Строка.Оклад);
ДанныеСотр.Вставить("Должность", Строка.Должность);
ДанныеСотр.Вставить("Отдел", Строка.Отдел);
Возврат ДанныеСотр;
КонецФункции
// Повторное использование структуры:
Данные = ПолучитьДанныеСотрудника(Сотрудник); // один вызов
Сообщить(Данные.Должность); // используем поля
РасчитатьНалог(Данные.Оклад);
ПроверитьОтдел(Данные.Отдел);
Примеры из практики
Пример 1: Загрузка параметров
// ПЛОХО:
Процедура ЗаполнитьФорму()
Если ПолучитьОрганизацию() <> Неопределено Тогда
Форма.Организация = ПолучитьОрганизацию(); // вызов 1
Форма.РасчетныйСчет = ПолучитьРасчетныйСчет(ПолучитьОрганизацию()); // вызов 2
Форма.Банк = ПолучитьБанк(ПолучитьОрганизацию()); // вызов 3
КонецЕсли;
КонецПроцедуры
// ХОРОШО:
Процедура ЗаполнитьФорму()
Организация = ПолучитьОрганизацию();
Если Организация <> Неопределено Тогда
Форма.Организация = Организация;
Форма.РасчетныйСчет = ПолучитьРасчетныйСчет(Организация);
Форма.Банк = ПолучитьБанк(Организация);
КонецЕсли;
КонецПроцедуры
Пример 2: Обработка больших массивов
// Функция дорогостоящая (ищет в большом массиве)
Функция НайтиЭлементВМассиве(Массив, Ключ) Экспорт
Для каждого Элемент Из Массив Цикл
Если Элемент.ID = Ключ Тогда
Возврат Элемент;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
// ПЛОХО - поиск выполняется много раз:
Если НайтиЭлементВМассиве(МойМассив, "ID123") <> Неопределено Тогда // поиск 1
Сообщить("Найдено");
КонецЕсли;
Элемент = НайтиЭлементВМассиве(МойМассив, "ID123"); // поиск 2
Данные.Заполнить(Элемент);
// ХОРОШО - поиск выполняется один раз:
Элемент = НайтиЭлементВМассиве(МойМассив, "ID123"); // один поиск
Если Элемент <> Неопределено Тогда
Сообщить("Найдено");
КонецЕсли;
Данные.Заполнить(Элемент);
Пример 3: Запросы к БД
// ПЛОХО - запрос выполняется несколько раз:
Если Справочники.Контрагенты.Количество() > 100 Тогда
Сообщить("Много контрагентов");
КонецЕсли;
ЛистОтправки.ЗаполнитьКонтрагентов(Справочники.Контрагенты.Количество());
// ХОРОШО - вызов один раз:
Количество = Справочники.Контрагенты.Количество();
Если Количество > 100 Тогда
Сообщить("Много контрагентов");
КонецЕсли;
ЛистОтправки.ЗаполнитьКонтрагентов(Количество);
Оптимизация в циклах
// ОЧЕНЬ ПЛОХО - функция вызывается в каждой итерации:
Для индекс = 1 По 1000 Цикл
Если НаходитсяВСписке(Справочники.Товары.Получить(индекс), МойСписок) Тогда
// Обработка
КонецЕсли;
КонецЦикла;
// ХОРОШО - вызвать один раз до цикла:
Товары = Справочники.Товары.Получить(индекс);
Для индекс = 1 По 1000 Цикл
Если НаходитсяВСписке(Товары[индекс], МойСписок) Тогда
// Обработка
КонецЕсли;
КонецЦикла;
Преимущества
- Производительность — уменьшение вызовов дорогостоящих функций
- Читаемость — код понятнее (не вложенные вызовы)
- Отладка — проще отладить, чем множественные вызовы
- Надёжность — одиночное значение не меняется в процессе
- Экономия памяти — если результат большой, он в памяти один раз
Минусы неправильного кеширования
// ПЛОХО - кешируем устаревшее значение:
Оклад = ПолучитьОклад(Сотрудник); // получено в начале процедуры
// Где-то в коде изменился оклад
Сотрудник.Оклад = 100000;
Сотрудник.Записать();
// Но мы используем старое значение
ПрименитьНовыйОклад(Оклад); // применяем старое значение!
// Это ошибка!
Чеклист оптимизации
- Определены дорогостоящие функции
- Результаты сохраняются в переменные
- Переменные используются вместо повторных вызовов
- Кеш не устаревает (проверить логику)
- Нет повторных вызовов в циклах
- Память не переполняется (большие массивы)
Итого: повторное использование возвращаемых значений это техника оптимизации, при которой результат функции сохраняется в переменную и используется несколько раз, экономя ресурсы на повторных вызовах.