Как изменится логика приложения при добавлении бизнес-требований выбора курьера с учетом подрядчиков, стоимости и доступности
Что проверяют
Умеете ли вы встроить новое бизнес-правило так, чтобы следующее не потребовало переписывать сервис заново. Следом почти всегда спрашивают, что будет, если два заказа одновременно выберут одного курьера, и что делать, когда API подрядчика не отвечает.
Как отвечать
Начните с модели: появляются Contractor со своими условиями, тариф и доступность курьера во времени. Своих курьеров и курьеров подрядчиков удобно свести к одному интерфейсу кандидата с ценой, временем прибытия и источником.
Сам выбор разбейте на этапы:
- сбор кандидатов: свои курьеры из базы, подрядчики через адаптеры за общим интерфейсом, по адаптеру на подрядчика;
- фильтрация: цепочка правил (зона, вес, график, лимит заказов), каждое правило отдельный класс, новое добавляется без правки старых;
- ранжирование: паттерн «Стратегия», например
CheapestStrategy,FastestStrategyили взвешенная оценка. Веса и выбор стратегии лежат в конфигурации, а не в коде; - резервирование: курьер закрепляется атомарно, через оптимистическую блокировку (
@Versionв JPA), условныйUPDATE ... WHERE status = 'FREE'или бронь у подрядчика с таймаутом.
Внешние вызовы оборачиваются таймаутами, повторами и circuit breaker, например из Resilience4j. Опрашивать подрядчиков параллельно можно через CompletableFuture или виртуальные потоки Java 21. Если подрядчик не ответил вовремя, выбор идёт без него, а не падает целиком. Решение с причинами стоит логировать: бизнес обязательно спросит, почему заказ ушёл дорогому подрядчику.
Где спотыкаются
Дописывают новые if в существующий метод выбора. Через два требования его невозможно ни прочитать, ни протестировать.
Забывают про гонку: проверили, что курьер свободен, и назначили отдельным запросом. Под нагрузкой один курьер получает два заказа.
Зовут API подрядчиков синхронно и без таймаутов прямо в запросе клиента. Один медленный подрядчик тогда тормозит оформление всех заказов.