Пример мышления в терминах процесса

В книге Арно Лоре “Проектирование веб-API” (5.3.1 Построение простой цепочки целей) есть пример API для мобильного банкинга, где клиент пытается перевести деньги бенефециару, справляясь с трудностями бизнес-логики (сумма превышает безопасный лимит; сумма превышает совокупный дневной лимит перевода; исходный счет нельзя использовать в качестве источника перевода; данный вариант назначения нельзя использовать с этим источником). На картинках рассаматривается такая эволюция целей API:

Рис. 5.14. Денежный перевод

Но разве нельзя сделать это короче и более плавно, предотвращая ошибки?

Рис. 5.15. Предотвращение ошибок в потоке денежных переводов

С помощью этой новой цели можно предотвратить три из четырех ошибок!

Рис. 5.16. Для составления списка вариантов назначения из выбранного источника требуется один вызов

Новая агрегированная цель возвращает только возможные варианты назначения для данного источника, причем источник извлекается с помощью цели «Перечислить источники». Эта новая цель упростит поток целей, и тут есть бонус! Это также предотвращает появление ошибки «Данный вариант назначения нельзя использовать с этим источником». Теперь у потребителей меньше целей для использования, и у них есть доступ ко всему, что нужно, чтобы избежать сообщений об ошибках от цели «Перевод денег».

В этом сценарии клиент последовательно вполняет три шага:

  1. Получает список источников
  2. Получает список назначений для выбранного источника
  3. Переводит выбранную сумму из выбранного источника в выбранное назначение

Псевдокод:

sources = API.getSources()
destinations = API.getDestinations(source[i])
API.makeTransfer(sources[i], destinations[j], amount)

Не смотря на то, что на рисунках приуствтует слово “цель” эволюция API движется вопросом “как?”, а не “зачем?”.

Получается API, который выглядит так, будто цель клиента при переводе денег – это избавиться от денег. Обычно переводы имеют внешнюю цель – финансовое обеспечение каких-то выгод (оплата заказов, внесение депозита). То есть они используются не для того, чтобы денег где-то не стало, а чтобы они где-то появились. Из этого следует, что изначально клиент знает назначение и сумму перевода, а источник определяется исходя из возможностей. Почему бы не использовать ценарий, в котором клиент:

  1. Получает список назначений
  2. Получает список источников для выбранного назначения
  3. Переводит выбранную сумму из выбранного источника в выбранное назначение

Псевдокод:

destinations = API.getDestinations()
sources = API.getSources(destinations[j])
API.makeTransfer(sources[i], destinations[j], amount)

Отчасти это решается “последней оптимизацией”, которая представлена ниже.

Рис. 5.17 Один вызов предоставляет все данные, необходимые для выбора источника и варианта назначения

Поскольку количество возможных комбинаций «источник вариант назначения» относительно ограничено, мы можем предоставить все возможные ассоциации «источник вариант назначения» с помощью одной цели «Перечислить варианты назначения и источники», которая объединяет цели «Перечислить источники» и «Перечислить варианты назначения для источника». Это не обязательно, но возможно.

Этот вариант предлагает получить все возможные пары (источник, назначение) и после этого перевести деньги. И он приемлем, пока источников и назначений мало. Например, при наличии трёх источников и десяти назначений количество пар может достигнуть 30. Передавать клиенту много данных без необходимости не особо хорошая идея, кроме того, это вынудит клиента решать проблемы их отображения и фильтрации (что критиковалось в 5.3.2).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *