February 6th, 2020

Book

Абстрактная фабрика синглтонов-2

Поскольку все ответы были в стиле кармановского пункта 6 https://www.atraining.ru/trainers/karmanov/hint/ - "Разбираться в проблеме не нужно, ... – надо просто неправильное заменить на правильное", я сформулирую одновременно более абстрактно и более предметно.

Есть компонент А создающий и дёргающий компонент Б, а компонент Б запускает ракеты и возвращает слово из трёх букв.

Для компонента А надо написать тест, но такой, чтобы ракеты не запускались. Требований к тому, чтобы это был юнит-тест, нету - ну то есть не надо мокать вообще все зависимости всегда, а только те, которые"запускают ракеты". Ну то есть нужны интеграционные тесты для системы в целом и для крупных подсистем.

Классическое решение - сделать, чтобы в тесте компонент А дёргал компонент Б', который будет просто возвращать ожидаемое компонентом А слово из трёх букв, никаких "ракет" при этом не "запуская".

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

Вариант 1 - пусть компонент А не создает объект Б, а принимает его параметром.

В системе будет A(Б), а в тесте A(Б'). Но тут есть недостаток - например если компонент А создаёт Б не напрямую, а создаёт С, который уже создает Б - то С тоже придётся параметризовать.

Ну и для того чтобы этого размножения параметров избежать - используется старый трюк "передаём параметр вглубь, используя глобальную переменную". И мы подходим к варианту 2

Вариант 2 - пусть будет глобальная фабрика БFactory, которая будет производить экземпляры Б или Б'

В системе будет А и Б, без параметров. Может быть даже произвольное количество промежуточных уровней С. Но C будет использовать метод БFactory для конструирования Б. И этот метод будет разным в системе и в тестах.

Но тут недостаток что у нас будет много фабрик - для Б, потом понадобится фабрика для Х, У, ну и т.д. Ну и будут простыни конструирования этих минифабрик при старте системы и в тестах.

Это можно решить вариантом 3.

Вариант 3 - пусть будет одна большая фабрика ФабрикаВсего.

У него есть 2 подварианта

3а - мы просто добавляем в БFactory методы - makeБ, makeХ, makeУ.

3б - мы используем готовую ФабрикуВсего, которых уже написаны тучи.

В варианте 3б у нас вместо двух простыней в пункте 3а - простыни конструирования и простыни виртуальных методов - остаётся только одна простыня конструирования - "регистрация классов в фабрике".

Тут мы избавились от "параметризации всего всем", но для обепечения подменяемости, для каждого подменяемого класса Б нам нужен интефейс IБ. Ну и если у нас классы здорового человека с 1-2 методами - то появляются тучи мелких интерфейсов, ненужных для работы системы, а нужных лишь для работы тестов. Ну то есть код превращается в сплошной бойлерплейт интерфейсов, учитывая, что от бойлерплейта параметров и бойлерплейта фабрик мы избавились.

Тут на помощь (сомнительную, но будем пробовать) приходит Акка, заявляющая что нетипизированность акторов - это не недостаток, а преимущество. В данном случае оно проявляется в том, что если Б - актор, то поскольку всё общение с актором происходит через IDispatch IActor, нам не надо делать тучу этих IБ. И мы приходим к варианту 4.

Вариант 4 - фабрика всего, производящая акторы

Тут только маленькое уточнение, что поскольку для создания актора нужно передать фабрику в ActorOf, мы можем вместо фабрики, вызывающей ActorOf, использовать фабрику аргументов ActorOf, то есть фабрику фабрик. С аналогичными 2 вариантами из п. 3 - то есть наша фабрика или готовая.

Но есть ещё

Вариант 4в - трёхэтажная фабрика из прошлого поста

Она получается, если фабрику фабрик в стиле 4а конструировать готовой фабрикой в стиле 3б. Что даёт нам компактность 3а-фабрики в сочетании с конфигурируемостью 3б-фабрики.
Book

А давайте разберёмся с Desktop GUI

Каково состояние дел в современном гуестроении?
Кто круче - GTK или Qt, и почему?
Чем WPF круче предыдущих фреймворков?
Почему его не используют, а используют Web Forms?
Что появилось нового в вебе со времен RxJS - ну или реакта, я все их путаю?