Как переделать повторяющийся код в процедуру или функцию в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

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

Выясняем причину сложности: как вернуть несколько значений?

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

В среде 1С 7.7 эту задачу можно решить тремя основными способами:

  1. Использовать передачу параметров в процедуру по ссылке (самый простой и производительный метод).
  2. Использовать объект СписокЗначений для возврата множества значений из функции.
  3. Использовать объект ТаблицаЗначений, если требуется возвращать строки данных.

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

---

Способ №1. Использование процедуры и передача параметров по ссылке (Рекомендуемый)

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

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

Рассмотрим пример кода такой процедуры в Глобальном модуле:


Процедура глРазобратьАдрес(Знач ВхАдрес, Индекс, Область, Город, Улица, Квартира) Экспорт
    
    // Подготавливаем строку адреса, заменяя запятые на разделители строк
    АдресСтрока = СтрЗаменить(ВхАдрес, ",", РазделительСтрок);
    
    Если ПустоеЗначение(АдресСтрока) = 1 Тогда
        Индекс   = " ";
        Область  = " ";
        Город    = " ";
        Улица    = " ";
        Квартира = "";
    ИначеЕсли ПустоеЗначение(СтрПолучитьСтроку(АдресСтрока, 1)) = 1 Тогда
        Индекс   = СтрПолучитьСтроку(АдресСтрока, 2) + ", ";
        Область  = СтрПолучитьСтроку(АдресСтрока, 3) + ", ";
        Город    = СтрПолучитьСтроку(АдресСтрока, 5) + ", ";
        Улица    = СтрПолучитьСтроку(АдресСтрока, 7) + " " + СтрПолучитьСтроку(АдресСтрока, 8) + ", ";
        Квартира = "кв. " + СтрПолучитьСтроку(АдресСтрока, 9) + СтрПолучитьСтроку(АдресСтрока, 10);
    Иначе
        Индекс   = СтрПолучитьСтроку(АдресСтрока, 1) + ", " + " ";
        Область  = СтрПолучитьСтроку(АдресСтрока, 2) + ", " + " ";
        Город    = СтрПолучитьСтроку(АдресСтрока, 3) + ", " + " ";
        Улица    = СтрПолучитьСтроку(АдресСтрока, 4) + " " + СтрПолучитьСтроку(АдресСтрока, 5) + ", " + " ";
        Квартира = СтрПолучитьСтроку(АдресСтрока, 6);
    EndIf;
    
КонецПроцедуры

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

Как теперь вызвать этот код в ваших 6 процедурах?

Вместо огромного блока кода теперь достаточно написать всего несколько строк:


// 1. Объявляем переменные, куда процедура запишет результат
Перем ТекИндекс, ТекОбласть, ТекГород, ТекУлица, ТекКвартира;

// 2. Получаем строку адреса из нашей таблицы значений
СтрокаАдреса = ТЗ.ПолучитьЗначение(стр, 1).ЮрАдрес;

// 3. Вызываем нашу глобальную процедуру
глРазобратьАдрес(СтрокаАдреса, ТекИндекс, ТекОбласть, ТекГород, ТекУлица, ТекКвартира);

// 4. Всё! Переменные заполнены и готовы к использованию
// Например:
Сообщить("Город: " + ТекГород);

---

Способ №2. Использование функции и объекта СписокЗначений

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

Рассмотрим реализацию такой функции в Глобальном модуле:


Функция глРазобратьАдресВСписок(Знач ВхАдрес) Экспорт
    
    // Создаем объект списка значений
    РезультирующийСписок = СоздатьОбъект("СписокЗначений");
    
    АдресСтрока = СтрЗаменить(ВхАдрес, ",", РазделительСтрок);
    
    // Внутренние переменные для расчетов
    ВрИндекс = ""; ВрОбласть = ""; ВрГород = ""; ВрУлица = ""; ВрКвартира = "";
    
    Если ПустоеЗначение(АдресСтрока) = 1 Тогда
        ВрИндекс   = " ";
        ВрОбласть  = " ";
        ВрГород    = " ";
        ВрУлица    = " ";
        ВрКвартира = "";
    ИначеЕсли ПустоеЗначение(СтрПолучитьСтроку(АдресСтрока, 1)) = 1 Тогда
        ВрИндекс   = СтрПолучитьСтроку(АдресСтрока, 2) + ", ";
        ВрОбласть  = СтрПолучитьСтроку(АдресСтрока, 3) + ", ";
        ВрГород    = СтрПолучитьСтроку(АдресСтрока, 5) + ", ";
        ВрУлица    = СтрПолучитьСтроку(АдресСтрока, 7) + " " + СтрПолучитьСтроку(АдресСтрока, 8) + ", ";
        ВрКвартира = "кв. " + СтрПолучитьСтроку(АдресСтрока, 9) + СтрПолучитьСтроку(АдресСтрока, 10);
    Иначе
        ВрИндекс   = СтрПолучитьСтроку(АдресСтрока, 1) + ", " + " ";
        ВрОбласть  = СтрПолучитьСтроку(АдресСтрока, 2) + ", " + " ";
        ВрГород    = СтрПолучитьСтроку(АдресСтрока, 3) + ", " + " ";
        ВрУлица    = СтрПолучитьСтроку(АдресСтрока, 4) + " " + СтрПолучитьСтроку(АдресСтрока, 5) + ", " + " ";
        ВрКвартира = СтрПолучитьСтроку(АдресСтрока, 6);
    КонецЕсли;
    
    // Заполняем список значений. 
    // Первый параметр - само значение, второй параметр (строка) - его идентификатор (ключ)
    РезультирующийСписок.ДобавитьЗначение(ВрИндекс, "Индекс");
    РезультирующийСписок.ДобавитьЗначение(ВрОбласть, "Область");
    РезультирующийСписок.ДобавитьЗначение(ВрГород, "Город");
    РезультирующийСписок.ДобавитьЗначение(ВрУлица, "Улица");
    РезультирующийСписок.ДобавитьЗначение(ВрКвартира, "Квартира");
    
    Возврат РезультирующийСписок;
    
КонецФункции

Как вызвать функцию и получить из нее данные?

В вызывающем модуле мы принимаем возвращаемый список значений и извлекаем из него данные по их порядковому номеру:


СтрокаАдреса = ТЗ.ПолучитьЗначение(стр, 1).ЮрАдрес;

// Получаем заполненный список из функции
АдресСп = глРазобратьАдресВСписок(СтрокаАдреса);

// Извлекаем значения по порядку добавления
Индекс   = АдресСп.ПолучитьЗначение(1);
Область  = АдресСп.ПолучитьЗначение(2);
Город    = АдресСп.ПолучитьЗначение(3);
Улица    = АдресСп.ПолучитьЗначение(4);
Квартира = АдресСп.ПолучитьЗначение(5);

---

Важные рекомендации по оптимизации алгоритма разбора

Проанализируем текущую логику разбора адреса, которую использует автор. Метод получения строк по жестко заданным номерам СтрПолучитьСтроку(адрес, 5) таит в себе серьезную опасность.

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

Для повышения надежности работы алгоритма рекомендуем придерживаться следующих правил:

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

← На главную