📊 Complexity

Управление сложностью: оркестратор + исполнители

Средне
🐱 Кот Айван
Сложный код — это код, который нельзя понять за 30 секунд. Разбивай его на части: оркестратор говорит ЧТО делать, исполнители — КАК. Это как рецепт: сначала список шагов, потом детали каждого.

Принцип

Любая сложная процедура делится на два уровня:

🎯 Оркестратор

"ЧТО делаем"

  • Описывает сценарий
  • Бизнес-термины
  • Max 7 шагов
  • Без технических деталей

⚙️ Исполнители

"КАК делаем"

  • Реализация шагов
  • Технические детали
  • Циклы, запросы
  • Переиспользуемые

Оркестратор

Главная процедура читается как план действий.

Процедура ЗагрузитьИОбработатьДоговоры()
    
    ib = "Синхронизация договоров из внешней системы";
    
    // 1. Получить исходные данные
    ИсходныеДанные = ПолучитьДоговорыИзAPI(); //▶️
    
    // 2. Валидировать данные
    ВалидныеДанные = ОтфильтроватьНевалидные(ИсходныеДанные); //▶️
    
    // 3. Преобразовать в формат базы
    ПодготовленныеДанные = ПреобразоватьВФорматБазы(ВалидныеДанные); //▶️
    
    // 4. Сохранить в базу
    РезультатЗаписи = СохранитьДоговоры(ПодготовленныеДанные); //▶️
    
    // 5. Отправить уведомление
    ОтправитьОтчетОЗагрузке(РезультатЗаписи); //▶️
    
КонецПроцедуры

Характеристики хорошего оркестратора

  • Читается как бизнес-процесс
  • Нет циклов и условий (или минимум)
  • Каждый шаг — вызов функции-исполнителя
  • Понятен менеджеру проекта

Исполнители

Функции, которые скрывают техническую реализацию.

// Исполнитель: скрывает работу с HTTP
Функция ПолучитьДоговорыИзAPI()
    
    ib = "Загружаем JSON из REST API";
    
    URL = ПолучитьНастройку("URLДоговоров"); //✏
    Ответ = A1sWeb.Get(URL); //▶️ //⚡
    
    Если НЕ Ответ.Успех Тогда
        A1sLog.Error("Ошибка API: " + Ответ.Код); //▶️
        Возврат Новый Массив; //↩
    КонецЕсли;
    
    Возврат A1sJ.Parse(Ответ.Тело); //↩
    
КонецФункции

// Исполнитель: скрывает логику валидации
Функция ОтфильтроватьНевалидные(Данные)
    
    ib = "Отсеиваем записи без обязательных полей";
    
    Возврат A1sAR.On(Данные)
        .Filter("v.Номер <> """" И v.Дата <> """"")
        .Value(); //↩
    
КонецФункции

Правило 7

7
Максимум 7 шагов в оркестраторе

Человек удерживает в голове 7±2 элемента. Если шагов больше — разбей на под-оркестраторы.

Если шагов больше 7

  1. Сгруппируй логически связанные шаги
  2. Вынеси группу в отдельную процедуру
  3. Назови её по бизнес-смыслу
// Было: 10 шагов
// Стало: 4 шага (группировка)

Процедура ОбработатьЗаказ()
    
    // 1. Подготовка данных (скрывает 3 под-шага)
    Данные = ПодготовитьДанныеЗаказа(); //▶️
    
    // 2. Расчёт (скрывает 4 под-шага)
    Расчёт = РассчитатьСуммыИСкидки(Данные); //▶️
    
    // 3. Сохранение
    СохранитьЗаказ(Данные, Расчёт); //▶️
    
    // 4. Уведомления
    ОтправитьУведомления(Данные); //▶️
    
КонецПроцедуры

Полный пример

❌ До рефакторинга

Процедура ЗагрузитьТовары()
    
    // Всё в одной процедуре на 200 строк
    HTTP = Новый HTTPСоединение("api.example.com");
    Запрос = Новый HTTPЗапрос("/products");
    Ответ = HTTP.Получить(Запрос);
    
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
    Данные = ПрочитатьJSON(ЧтениеJSON);
    
    Для Каждого Элемент Из Данные Цикл
        Если Элемент.Цена > 0 И Элемент.Название <> "" Тогда
            НайденныйТовар = Справочники.Товары.НайтиПоКоду(Элемент.Код);
            Если НайденныйТовар.Пустая() Тогда
                НовыйТовар = Справочники.Товары.СоздатьЭлемент();
                // ... ещё 50 строк ...
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    // ... и так далее ...
    
КонецПроцедуры

✅ После рефакторинга

// ОРКЕСТРАТОР
Процедура ЗагрузитьТовары()
    
    ib = "Синхронизация каталога товаров из внешнего API";
    
    // 1. Загрузить из API
    ВнешниеТовары = ЗагрузитьТоварыИзAPI(); //▶️
    
    // 2. Валидировать
    ВалидныеТовары = ВалидироватьТовары(ВнешниеТовары); //▶️
    
    // 3. Синхронизировать с базой
    РезультатСинхронизации = СинхронизироватьСБазой(ВалидныеТовары); //▶️
    
    // 4. Логировать результат
    ЗаписатьРезультатЗагрузки(РезультатСинхронизации); //▶️
    
КонецПроцедуры

// ИСПОЛНИТЕЛЬ 1
Функция ЗагрузитьТоварыИзAPI()
    ib = "HTTP-запрос к API каталога";
    Возврат A1sWeb.GetJSON("https://api.example.com/products"); //↩
КонецФункции

// ИСПОЛНИТЕЛЬ 2
Функция ВалидироватьТовары(Товары)
    ib = "Фильтруем товары без цены или названия";
    Возврат A1sAR.On(Товары)
        .Filter("v.Цена > 0 И v.Название <> """"")
        .Value(); //↩
КонецФункции

// ИСПОЛНИТЕЛЬ 3
Функция СинхронизироватьСБазой(Товары)
    ib = "Создаём новые и обновляем существующие";
    // ... логика синхронизации ...
КонецФункции

Когда рефакторить

🔴

Функция > 50 строк

🔴

Вложенность > 3 уровней

🔴

Нельзя понять за 30 сек

🔴

Копипаста в коде