Как оптимизировать код сервиса с большим количеством однотипных роботов, чтобы избежать распухания класса?
Что проверяют
Видите ли вы, что проблема не в скорости, а в устройстве кода: один сервис знает про все типы роботов, и каждый новый добавляет ветку в switch и десяток методов. Хотят услышать, как добиться того, чтобы новый робот появлялся новым классом или строкой конфигурации, без правки общего кода. Следом спрашивают, как это ляжет на Spring.
Как отвечать
Сначала выясните, чем роботы отличаются: поведением или только параметрами. От этого зависит решение.
- только параметрами: классы не нужны вовсе. Один
Robotи описание экземпляров в конфигурации через@ConfigurationPropertiesили в базе. Сто роботов становятся сотней записей, а не сотней классов; - поведением: общий интерфейс
RobotHandlerс методамиtype()иhandle(Task), каждая реализация отдельный@Component. Spring внедряетList<RobotHandler>, при старте из него собираетсяMapпо типу, и сервис только находит обработчик. Это Strategy с реестром, новый робот добавляется без изменения сервиса; - общий скелет с разными шагами: Template Method в абстрактном классе, но композиция из мелких стратегий обычно лучше глубокой иерархии;
- сквозная логика: логирование, повторы и метрики выносятся в декоратор или аспект, а не копируются в каждый обработчик;
- закрытый набор типов:
sealed interfaceиswitchс pattern matching из Java 21. Компилятор проверит, что обработаны все варианты, и забытый робот станет ошибкой компиляции.
Проверьте и состояние: если сервис держит данные всех роботов в полях, вынесите их в объект робота или хранилище. Сервис без состояния безопасно живёт синглтоном Spring.
Где спотыкаются
Выносят switch в фабрику и считают задачу решённой. Условие по типу никуда не делось, оно переехало в другой класс, и правка всё равно нужна при каждом новом роботе.
Заводят класс на каждого робота, хотя они отличаются только числами. Получается сотня почти одинаковых файлов вместо одной таблицы настроек.
Строят наследование в пять уровней ради переиспользования. Правка базового класса задевает всех потомков, и понять, какой метод реально вызывается, становится труднее, чем в исходном раздутом сервисе.