Разработка на основе сценариев использования, а не на основе API

Демистификация части чистой архитектуры

Во время одного из обсуждений «Чистой архитектуры в действии» были подняты некоторые вопросы о том, почему уровень домена (бизнес-правила) должен определять шлюз (интерфейс / протокол) для связи с уровнем данных, а не наоборот.

Вопрос: существуют API-интерфейсы для доступа к данным на сервере. Поэтому было бы просто, если бы уровень данных определял шлюз на основе API. И вариант использования может использовать интерфейс шлюза для доступа к уровню данных. Это и ежу понятно, не правда ли?

Я утверждал, что вариант использования (и уровень домена) зависит от API (и уровня данных). Чистая архитектура требует обратной зависимости - уровень данных может зависеть от варианта использования; А не наоборот.

Вот попытка объяснить, почему вариант использования не должен зависеть от API и почему шлюз определяется на уровне домена независимо от API.

Предположим, мы создаем клиентское приложение для книжного онлайн-магазина.

[Этот пост также предполагает, что читатель имеет некоторое базовое понимание чистой архитектуры и ее терминов. ]

Наша текущая задача в клиентском приложении - получить от сервера следующие данные:

1) общее количество книг в корзине

2) общая стоимость книг в корзине

И вот этот API (под API я имею в виду URL для получения данных с сервера):

ПОЛУЧИТЬ / корзину /? Детали = (цена / количество)

Передаваемые данные = цена показывает цену книг; details = count извлекает количество книг.

Подход, основанный на API:

В этом подходе API напрямую транслируется в интерфейс шлюза и, в конечном итоге, в класс варианта использования.

Будет класс использования (интерактора) GetCartDetails:

И один интерфейс шлюза для связи с уровнем данных.

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

Подход, основанный на вариантах использования:

Подумайте о структурировании наших сценариев использования - получение 1) общего количества книг и 2) общей цены - без учета структуры API.

У нас будет два класса прецедентов: один для получения общего количества книг, а другой - для получения общей стоимости книг.

И интерфейс нашего шлюза изменится примерно так:

Здесь мы увеличили один класс использования (это чистая архитектура, да!). Но мы сделали уровень домена (вариант использования и шлюз) независимым от уровня данных (API).

Почему подход, основанный на прецедентах?

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

API можно изменить следующим образом:

ПОЛУЧИТЬ / книги-цена /

ПОЛУЧИТЬ / количество книг /

Теперь в подходе, основанном на API, у нас есть 2 варианта. Первый вариант - изменить класс варианта использования также на основе API, потому что, в конце концов, наш вариант использования и шлюз построены на основе API. Второй вариант - оставить прецедент и шлюз как есть. Теперь у нас будет один класс прецедента, который фактически обрабатывает два прецедента - также с использованием двух разных API.

Мы нарушаем принцип единой ответственности. Класс usecase необходимо изменить, если требуются какие-либо изменения, чтобы получить общее количество книг или общую цену.

В подходе, основанном на прецедентах, требуется только изменение уровня данных (API). Классы вариантов использования остаются нетронутыми, и каждый вариант использования решает только один вариант использования приложения.

Было бы легко просто преобразовать ваш API в сценарий использования и шлюз, но написание вариантов использования и шлюза независимо от данных (API) делает ваш код чистым и поддерживаемым в долгосрочной перспективе.

В конце концов, это не универсальный подход. В некоторых случаях целесообразно использовать один вариант использования вместо двух. Все зависит от контекста приложения. Вот почему важно понимать причины, лежащие в основе правил в архитектуре (или просто чего-то еще).

Дополнительная информация:

Маленькая архитектура Роберта Мартина (дядя Боб).