Рассмотрим классическую задачу, с которой часто сталкиваются разработчики при написании алгоритмов загрузки или обработки данных. Проанализируем ситуацию: у нас есть цикл, который обходит массив товаров. В зависимости от некоего флага (например, переменной Тип), нам нужно проверять заполненность идентификатора товара на сайте. Если условие выполняется, итерация пропускается, а если нет — выполняется большой блок кода по созданию и заполнению нового объекта.
В первоначальном виде алгоритм может выглядеть громоздко и содержать дублирование:
Для Каждого тТовар ИЗ МассивТовара Цикл
Если Тип = 1 Тогда
Если СокрЛП(тТовар.IDНаСайте) = "" Тогда
Продолжить;
Иначе
НС = Объект.ТоварДляСинхронизации.Добавить();
НС.Товар = тТовар;
// ... и тут еще много кода
КонецЕсли;
Иначе
Если СокрЛП(тТовар.IDНаСайте) <> "" Тогда
Продолжить;
Иначе
НС = Объект.ТоварДляСинхронизации.Добавить();
НС.Товар = тТовар;
// ... и тут еще много такого же кода
КонецЕсли;
КонецЕсли;
КонецЦикла;
Очевидно, что огромный блок кода внутри условий полностью дублируется. Это усложняет чтение, поддержку и дальнейшую модификацию программы. Разберем по шагам несколько способов, как сделать этот код красивым, профессиональным и оптимальным.
Первый и самый простой шаг к улучшению — объединить наши проверки с помощью операторов И, ИЛИ. Посмотрим на пример, как можно свести все ветвления к одному условию отсева:
Для Каждого тТовар ИЗ МассивТовара Цикл
Если (Тип = 1) И (СокрЛП(тТовар.IDНаСайте) = "") Тогда
Продолжить;
ИначеЕсли (Тип <> 1) И (СокрЛП(тТовар.IDНаСайте) <> "") Тогда
Продолжить;
Иначе
НС = Объект.ТоварДляСинхронизации.Добавить();
НС.Товар = тТовар;
// ... много полезного кода
КонецЕсли;
КонецЦикла;
Этот подход уже избавляет нас от дублирования основного тела, так как мы сначала отсекаем ненужные варианты (используя Продолжить), а затем единожды выполняем нужную логику.
Так как в языке 1С мы можем свободно сравнивать булевы значения (Истина или Ложь), наше громоздкое условие можно превратить в одну короткую и элегантную строку. Выясним причину: выражение (Тип = 1) возвращает булево значение, как и проверка на пустоту. Нам нужно пропустить итерацию, когда оба эти условия совпадают (оба Истина или оба Ложь). Следовательно, мы можем приравнять их друг к другу.
Заодно заменим устаревшую конструкцию СокрЛП(Значение) = "" на более быструю и современную функцию ПустаяСтрока():
Для Каждого тТовар ИЗ МассивТовара Цикл
Если (Тип = 1) = ПустаяСтрока(тТовар.IDНаСайте) Тогда
Продолжить;
КонецЕсли;
НС = Объект.ТоварДляСинхронизации.Добавить();
НС.Товар = тТовар;
// ... полезный код
КонецЦикла;
Этот код работает идеально: если Тип равен единице и строка пустая — итерация пропускается. Если Тип не равен единице и строка не пустая — итерация тоже пропускается. Никакого дублирования!
Если логика заполнения данных слишком сложна, хорошей практикой считается вынос ее в отдельную процедуру или функцию. Это принцип DRY (Don’t Repeat Yourself), который делает структуру модуля более читаемой.
Для Каждого тТовар ИЗ МассивТовара Цикл
Если Тип = 1 И НЕ ПустаяСтрока(тТовар.IDНаСайте) Тогда
ДобавитьТоварВСинхронизацию(Объект, тТовар);
ИначеЕсли Тип <> 1 И ПустаяСтрока(тТовар.IDНаСайте) Тогда
ДобавитьТоварВСинхронизацию(Объект, тТовар);
КонецЕсли;
КонецЦикла;
Где ДобавитьТоварВСинхронизацию — это отдельная процедура, в которой скрыто "много кода". Таким образом мы разделяем логику принятия решения и логику обработки.
В парадигме 1С:Предприятие выполнять сложную логику и отсев данных внутри цикла не всегда оправдано, особенно при работе с большими массивами. Если ваши данные формируются запросом к базе, правильнее всего перенести условия прямо в текст запроса.
ГДЕ
(ВЫБОР КОГДА &Тип = 1 ТОГДА Товар.IDНаСайте = """"
ИНАЧЕ Товар.IDНаСайте <> """"
КОНЕЦ) = ЛОЖЬ
Используя такое условие, в результирующую выборку попадут только те элементы, которые действительно необходимо обрабатывать, и ветвления с Продолжить в коде вообще не понадобятся.
В завершение рассмотрим несколько важных правил хорошего тона при написании кода:
Тип = 1. Использование непонятных чисел прямо в коде усложняет поддержку. Рекомендуется использовать перечисления или переменные с "говорящими" названиями, например: ТипСинхронизации = Перечисления.ТипыСинхронизации.Полная.ПустаяСтрока() работает быстрее, чем СокрЛП() = "", так как не создает новых строк в оперативной памяти. А если поле может содержать значение NULL или пустую ссылку, используйте универсальную функцию ЗначениеЗаполнено().Применяя эти простые подходы, вы сможете создавать красивый, легко читаемый и эффективный код в среде 1С!