strongself / The-Book-of-VIPER

the one and the only
Other
958 stars 129 forks source link

Роль и обязанности интерактора #37

Closed CROSP closed 8 years ago

CROSP commented 8 years ago

Сервисы инжектируются в интерактор. В итоге интерактор в основном служит фасадом, взаимодействующим с сервисами и передающим полученные от них данные презентеру. Мы в команде договорились о том, что при работе с Core Data NSManagedObject’ы не выходят на уровни выше интерактора. Поэтому в интеракторах также происходит преобразование NSManagedObject в Plain Old NSObject, то есть простой наследник NSObject.

Хотел бы подробнее разобраться с ролью интерактора. Я считаю что интерактор, так же известен как use cases, application business logic, это главный человек в модуле и вообще в приложении. Это сердце/мозг всего приложения. Все логика которая отличает ваше приложение от других.

Он не должен знать ни о ком и ни о чем , он должен ставить правила, которые другие слои должны выполнять. Возьмём тот же сервис , скажите где например в описании " Рамблер Почты" упоминается сервис, то что он реально обозначает (запросы к серверу, обработка ответа ...) . Его в описании нету, то есть я считаю, что слой Interactor/Use Case описывать функционал приложения . В почтовом клиенте это отправить письмо, посмотреть входящее, просмотреть и изменить персональные данные ...

Согласен, что очень часто происходит так что интерактор всего лишь фасад, обычно это происходит потому что серверное API предоставляет возможность гибких запросов с фильтрами, ограничениями и так далее.

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

НО , интерактор не должен знать ни о каких сервисах, managed objects и других штуках. Он говорит следующее : "Я тут главный, я независимый. Хотите чтобы я что-то делал давайте мне слуг которые будут выполнять грязную работу. А я буду только заниматься важными расчетами." Таким образом мы объявляем в интеракторе основные интерфейсы , используя например паттерн Репозиторий ( в данном случае практически тоже что и сервис) , который слой данных будет реализовывать, а затем конкретная реализация будет инджектиться в интерактор.

У Вас же интерактор занимается конвертацией NSManagedObject в PONSO, я считаю что это не правильно в первую очередь потому что Вы жёстко завязываете Ваш проект на определённую платформу , у Вас каждый слой завязан на конкретной платформе. Интерактор должен легко переноситься на другой язык просто сменой синтаксиса. В данном же случае у Вас маппинг производится жёстко под платформу.

Скажите пожалуйста почему Вы приняли такое решение ?

etolstoy commented 8 years ago

Спасибо за такой развернутый вопрос! На самом деле, причина очень проста и банальна: конвертация в PONSO (у нас ее называют модным словом "понсомизация") - дорогой процесс, особенно с учетом всех связей. Только сам модуль может знать, в каком виде он будет работать с полученными моделями, нужны ли связи и с какой глубиной. Выносить это решение в сервис - нельзя, мы не должны подстраивать его интерфейс под кучу различных клиентов. Именно поэтому интерактор управляет понсомизатором, задавая специальный конфиг, описывающий глубину связей, подходящий для его конкретного случая.

AndreyZarembo commented 8 years ago

Да ну, все проще было, взяли структуру модуля и сделали её такой, чтобы была удобной для работы, а названия элементов остались. Можно их называть "медведь", "балалайка", "водка", "гусли" и т.п. )

CROSP commented 8 years ago

@etolstoy Спасибо Вам за такой быстрый ответ, даже не ожидал) Согласен, что бывают различные случаи и жестко привязываться к определенным стандартам или какой-то архитектуре не стоит, а просто рационально продумывать под нужды определенного приложения. Если у Вас в приложении там логика для работы со структурами данных и связями, то да, может это имеет смысл. Просто я за то, чтобы оставлять данный слой чистым от различных фреймворков и зависимостей. Если брать например проект Android, то я вообще этот слой Интеркатор создаю как чистый Java модуль ( в Android Studio) чтобы не было соблазна добавить зависимости из SDK.

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

В любом случае, огромное Вам спасибо за Ваш вклад в "Чистую Архитектуру", очень много полезного почерпнул из Ваших докладов и публикаций.