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

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

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

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

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

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

Рассмотрим пример функции, которая рассчитывает итоги по документу и возвращает не только сумму, но и количество позиций, а также статус проверки. Мы создаем новую структуру, заполняем её и возвращаем одним оператором.

Функция РассчитатьИтогиДокумента(ДокументОбъект)

СуммаИтого = 0;

КоличествоСтрок = 0;

ЕстьОшибки = Ложь;

Для Каждого СтрокаТовары Из ДокументОбъект.Товары Цикл

СуммаИтого = СуммаИтого + СтрокаТовары.Сумма;

КоличествоСтрок = КоличествоСтрок + 1;

Если СтрокаТовары.Цена = 0 Тогда

ЕстьОшибки = Истина;

КонецЕсли;

КонецЦикла;

Результат = Новый Структура;

Результат.Вставить("Сумма", СуммаИтого);

Результат.Вставить("Количество", КоличествоСтрок);

Результат.Вставить("Статус", ЕстьОшибки);

Возврат Результат;

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

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

💡

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

💡

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

Применение Массива для однородных данных

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

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

  • 📦 Идеально подходит для возврата списка объектов одного типа, например, списка ошибок валидации.
  • 🔢 Эффективен для передачи координат или числовых наборов, где важен порядок (X, Y, Z).
  • ⚡ Требует строгой дисциплины: изменение порядка добавления элементов в функцию сломает вызывающий код.

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

Функция ПолучитьГабариты(Номенклатура)

Габариты = Новый Массив;

// Индекс 0: Длина

Габариты.Добавить(Номенклатура.Длина);

// Индекс 1: Ширина

Габариты.Добавить(Номенклатура.Ширина);

// Индекс 2: Высота

Габариты.Добавить(Номенклатура.Высота);

// Индекс 3: Вес

Габариты.Добавить(Номенклатура.Вес);

Возврат Габариты;

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

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

Особенности работы с массивами в 1С

В 1С индексация массивов начинается с нуля, как и в большинстве языков программирования (C#, Java, JavaScript). Попытка обратиться к элементу по индексу, который еще не был добавлен, приведет к ошибке выполнения.

Выходные параметры через аргументы функции

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

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

Рассмотрим синтаксис функции с выходным параметром. Здесь мы явно указываем, что второй аргумент не является значением, а служит контейнером для возврата данных. Это позволяет получить статус операции как результат функции, а детализацию — через параметр.

Функция ПроверитьКонтрагента(ИНН, ОписаниеОшибки)

// Второй параметр не имеет модификатора"Знач", значит он передается по ссылке

Если ПустаяСтрока(ИНН) Тогда

ОписаниеОшибки ="ИНН не заполнен";

Возврат Ложь;

КонецЕсли;

// Имитация сложной проверки

Если Лев(ИНН, 1) ="0" Тогда

ОписаниеОшибки ="Некорректный формат ИНН";

Возврат Ложь;

КонецЕсли;

ОписаниеОшибки ="";

Возврат Истина;

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

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

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

📊 Какой метод возврата данных вы используете чаще всего?
Структура
Массив
Выходные параметры
Глобальные переменные

Сравнительный анализ методов возврата

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

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

Критерий Структура Массив Выходные параметры
Читаемость кода Высокая (именованные ключи) Низкая (числовые индексы) Средняя (требует изучения сигнатуры)
Типы данных Разнородные Любые (чаще однородные) Любые
Риск ошибки порядка Отсутствует Высокий Средний
Производительность Высокая Высокая Максимальная

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

☑️ Критерии выбора метода

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

Обработка типовых ошибок и исключений

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

Одной из распространенных ошибок является возврат Неопределено вместо ожидаемой структуры. Это приводит к тому, что при попытке обратиться к свойству Результат.Сумма возникает системное исключение. Гораздо безопаснее возвращать структуру с признаком ошибки внутри.

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

Функция БезопасныйРасчет(Данные)

// Инициализируем структуру с дефолтными значениями

Ответ = Новый Структура("Успех, Сообщение, Данные", Ложь,"", Неопределено);

Попытка

// Основная логика

Если Не Данные.Заполнен Тогда

Ответ.Сообщение ="Входные данные пусты";

Возврат Ответ;

КонецЕсли;

Ответ.Успех = Истина;

Ответ.Данные = ВыполнитьСложныйАлгоритм(Данные);

Исключение

Ответ.Сообщение = ОписаниеОшибки;

КонецПопытки;

Возврат Ответ;

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

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

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

Оптимизация и лучшие практики разработки

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

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

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

  • 📝 Комментируйте структуру возвращаемых данных, если используете Массив.
  • 🛡 Всегда возвращайте объект того типа, который ожидает вызывающий код, даже при ошибке.
  • 🔄 Избегайте побочных эффектов при использовании выходных параметров, если это не оговорено явно.

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

Можно ли вернуть результат запроса и количество строк одновременно?

Да, это частая задача. Лучший способ — поместить результат запроса (объект Выборка или ТаблицаЗначений) и число строк в одну Структуру. Например: Новый Структура("Таблица, Количество", ТабРез, ТабРез.Количество).

В чем разница между возвратом Массива и Таблицы Значений?

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

Как передать структуру в другую функцию без изменений?

При передаче структуры в функцию она передается по ссылке. Если вы хотите защитить её от изменений, используйте модификатор Знач в параметрах принимающей функции или создайте копию структуры перед передачей.

Что быстрее: Структура или Массив?

В большинстве сценариев разница в производительности между Структурой и Массивом в 1С пренебрежимо мала. Выбор должен основываться на удобстве чтения и поддержки кода, а не на микро-оптимизации.

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

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