Информация об изменениях

Сообщение Re[3]: ненормальные нормальные алгорифмы от 02.05.2026 11:26

Изменено 02.05.2026 13:34 rg45

Re[3]: ненормальные нормальные алгорифмы
Здравствуйте, Кодт, Вы писали:

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


К>А разверни тему, пожалуйста.


Пишу набросок налету, без проверок компилятором, но идея будет понятна, я думаю:

// Раскладываем сложную задачу на подзадачи
template <
   Subprocessor1 P1
,  Subprocessor2 P2
,  Subprocessor3 P3
,  Strategy1 S1
   // Можно использовать параметры по умолчанию
,  Strategy2 S2 = DefaultS1
,  Strategy3 S3 = DefaultS2
>
struct Processor {
   P1 subprocessor1;
   P2 subprocessor2;
   P3 subprocessor3;
   S1 strategy1;
   S2 strategy2;
   S3 strategy3;

   auto operator()(/* . . . */) const {
      // Имплементация логики верхнего уровня с использованием подчинённых процессоров и стратегий
   }
};

// Продакшн версия.
// Обратите внимание, что нет необходимости указывать параметры шаблона явно.
inline constexpr Processor process{
   .subprocessor1 = process1
,  .subprocessor2 = process2
,  .subprocessor3 = process3
,  .strategy1 = special_strategy
};

// Где-то в юнит-тестах
TEST(TestsSuite_01, Test) {
   // Тестовый процессор с моками.
   // Я использовал лямбды, но замокать можно чем угодно
   const Processor test_processor {
      .subprocessor1 = [](/* . . . */) {}
   ,  .subprocessor2 = [](/* . . . */) {}
   ,  .subprocessor3 = [](/* . . . */) {}
   ,  .strategy1 = [](/* . . . */) {}
   ,  .strategy2 = [](/* . . . */) {}
   ,  .strategy3 = [](/* . . . */) {}
   };
   EXPECTED_EQ((/*. . .*/), test_processor(/*. . .*/))
}


Конечно, можно было бы все мемберы класса сделать нетипизированными параметрами шаблона, но тут можно и так, и эдак, у каждого подхода свои плюсы и минусы.
Re[3]: ненормальные нормальные алгорифмы
Здравствуйте, Кодт, Вы писали:

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


К>А разверни тему, пожалуйста.


Пишу набросок налету, без проверок компилятором, но идея будет понятна, я думаю:

// Раскладываем сложную задачу на подзадачи
template <
   Subprocessor1 P1
,  Subprocessor2 P2
,  Subprocessor3 P3
,  Strategy1 S1
   // Можно использовать параметры по умолчанию
,  Strategy2 S2 = DefaultS1
,  Strategy3 S3 = DefaultS2
>
struct Processor {
   P1 subprocessor1;
   P2 subprocessor2;
   P3 subprocessor3;
   S1 strategy1;
   S2 strategy2;
   S3 strategy3;

   auto operator()(/* . . . */) const {
      // Имплементация логики верхнего уровня с использованием подчинённых процессоров и стратегий
   }
};

// Продакшн версия.
// Обратите внимание, что нет необходимости указывать параметры шаблона явно.
inline constexpr Processor process{
   .subprocessor1 = process1
,  .subprocessor2 = process2
,  .subprocessor3 = process3
,  .strategy1 = special_strategy
};

// Где-то в юнит-тестах
TEST(TestsSuite_01, Test) {
   // Тестовый процессор с моками.
   // Я использовал лямбды, но замокать можно чем угодно
   const Processor test_processor {
      .subprocessor1 = [](/* . . . */) {}
   ,  .subprocessor2 = [](/* . . . */) {}
   ,  .subprocessor3 = [](/* . . . */) {}
   ,  .strategy1 = [](/* . . . */) {}
   ,  .strategy2 = [](/* . . . */) {}
   ,  .strategy3 = [](/* . . . */) {}
   };
   EXPECTED_EQ((/*. . .*/), test_processor(/*. . .*/))
}


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