Как избежать дублирования кода при разных условиях сравнения в 1С?

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

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

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


Для Каждого тТовар ИЗ МассивТовара Цикл
    Если Тип = 1 Тогда
        Если СокрЛП(тТовар.IDНаСайте) = "" Тогда
            Продолжить;
        Иначе
            НС = Объект.ТоварДляСинхронизации.Добавить();
            НС.Товар = тТовар;
            // ... и тут еще много кода
        КонецЕсли;
    Иначе
        Если СокрЛП(тТовар.IDНаСайте) <> "" Тогда
            Продолжить;
        Иначе
            НС = Объект.ТоварДляСинхронизации.Добавить();
            НС.Товар = тТовар;
            // ... и тут еще много такого же кода
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

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

Вариант 1: Объединение условий с помощью логических операторов

Первый и самый простой шаг к улучшению — объединить наши проверки с помощью операторов И, ИЛИ. Посмотрим на пример, как можно свести все ветвления к одному условию отсева:


Для Каждого тТовар ИЗ МассивТовара Цикл
    Если (Тип = 1) И (СокрЛП(тТовар.IDНаСайте) = "") Тогда
        Продолжить;
    ИначеЕсли (Тип <> 1) И (СокрЛП(тТовар.IDНаСайте) <> "") Тогда
        Продолжить;
    Иначе
        НС = Объект.ТоварДляСинхронизации.Добавить();
        НС.Товар = тТовар;
        // ... много полезного кода
    КонецЕсли;
КонецЦикла;

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

Вариант 2: Использование эквиваленции (сравнение булевых значений)

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

Заодно заменим устаревшую конструкцию СокрЛП(Значение) = "" на более быструю и современную функцию ПустаяСтрока():


Для Каждого тТовар ИЗ МассивТовара Цикл
    Если (Тип = 1) = ПустаяСтрока(тТовар.IDНаСайте) Тогда
        Продолжить;
    КонецЕсли;
    
    НС = Объект.ТоварДляСинхронизации.Добавить();
    НС.Товар = тТовар;
    // ... полезный код
КонецЦикла;

Этот код работает идеально: если Тип равен единице и строка пустая — итерация пропускается. Если Тип не равен единице и строка не пустая — итерация тоже пропускается. Никакого дублирования!

Вариант 3: Паттерн "Выделение метода"

Если логика заполнения данных слишком сложна, хорошей практикой считается вынос ее в отдельную процедуру или функцию. Это принцип DRY (Don’t Repeat Yourself), который делает структуру модуля более читаемой.


Для Каждого тТовар ИЗ МассивТовара Цикл
    Если Тип = 1 И НЕ ПустаяСтрока(тТовар.IDНаСайте) Тогда
        ДобавитьТоварВСинхронизацию(Объект, тТовар);
    ИначеЕсли Тип <> 1 И ПустаяСтрока(тТовар.IDНаСайте) Тогда
        ДобавитьТоварВСинхронизацию(Объект, тТовар);
    КонецЕсли;
КонецЦикла;

Где ДобавитьТоварВСинхронизацию — это отдельная процедура, в которой скрыто "много кода". Таким образом мы разделяем логику принятия решения и логику обработки.

Вариант 4: Фильтрация данных до цикла (в Запросе)

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


ГДЕ
    (ВЫБОР КОГДА &Тип = 1 ТОГДА Товар.IDНаСайте = """" 
           ИНАЧЕ Товар.IDНаСайте <> """" 
     КОНЕЦ) = ЛОЖЬ

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

Дополнительные рекомендации

В завершение рассмотрим несколько важных правил хорошего тона при написании кода:

  1. Откажитесь от "Магических чисел": В условии используется конструкция Тип = 1. Использование непонятных чисел прямо в коде усложняет поддержку. Рекомендуется использовать перечисления или переменные с "говорящими" названиями, например: ТипСинхронизации = Перечисления.ТипыСинхронизации.Полная.
  2. Правильная проверка на пустоту: Функция ПустаяСтрока() работает быстрее, чем СокрЛП() = "", так как не создает новых строк в оперативной памяти. А если поле может содержать значение NULL или пустую ссылку, используйте универсальную функцию ЗначениеЗаполнено().

Применяя эти простые подходы, вы сможете создавать красивый, легко читаемый и эффективный код в среде 1С!

← На главную