Есть один вопрос который как мне кажется недостаточно освещен в технической архитектуре. Это протекание абстракций конкретной интеграции в другие области приложения. Вот например. нам надо брать файлы из скажем OneDrive и складывать их скажем в БД. У нас понятно есть класс который это оркеструет и у него есть метод возьмиОттудаПоложиТуда(...). И есть два класса отвечающие за интеграцию с OneDrive и с БД Дальше у нас есть два варианта
1) мы вот те сущности которые нам возвращает OneDrive (файловые дескрипторы) передаем напрямую в оркестратор и пусть он сам там решает что и как.
2) мы на выходе из класса которые обслуживает OneDrive приводим все к УНИФИЦИРОВАННОМУ ВИДУ и дальше оркестратор работает с абстрактными интерфейсами и сущностями. А уже класс отвечающий за OneDrive или скажем YaDisk их реализует.
подход 1 имеет очевидный минус - в оркестратор поступает совершенно ему не нужнгые ДНК OneDrive и он зависит не только от своего класса, но и от SDK OneDrive. Если нам надо добавить второй сервис - начинается месиво. Точнее месиво начинается с третьего но не важно.
плюс подхода 1 в том, что не надо долго оборачивать то что идет из OneDrive в иерархию Борщей. Что получил, то и отдал. кода меньше, в ряде подробностей можно сильно глубоко не копаться.
плюс подхода 2 в том, что все что льется в оркестратор унифицировано и новый провайдер подключается легко и понятно. нету в коде разной провайдеро специфиченой дичи, которая затрудняет чтения кода оркестратора
минус подхода 2 в том, что у нас много лохматого код который просто перекладывает всякое разное между классами. Причем если полей скажем штук 20 это очень некрасивый и ломкий код. еще минус в том, что даже если вы описали универсальную структуру и она подходит для OneDrive и YaDisk может оказаться что интеграция условно с РамблерДиском потребует передать какой-нить id живой сессии которого у вас в структуре нет и надо его для всех добавлять. В результате у вас получится либо совершенно не читаемый Франкенштейн с ногами ластами и крыльями либо у вас будет разветвленная структура классов с универсальными методами и всем тем что мы видим в проектах Джакарты. Она всем хороша, но понять ее без пол литры часто бывает очень сложно, что в свою очередь опять ведет к ошибкам. Ну и расширять ее опять же не сахар.
Вопрос как быть. В целом я как правило скорее сторонник подхода 1. Но на количестве точек интеграции >5 это товарищи полный кирдык и я сам готов это признать
На мой взгляд ответ тут нам дает как это ни банально звучит в 2022 году функциональное программирование. Решение выглядит так:
- поля между структурами не перекладывать и возвращать что есть. Т.е. подход 1
- но для разного рода действий над структурами данных определять функции (ну или что ближе всего к функции в вашем языке программирования) которые заполоняют так сказать пробелы между тем что вам досталось от OneDrive и тем что вы хотите от структуры данных.
Этот подход отличает от п2 два момента:
- структуру вы фигачите как есть, что дает прозрачность и избавляет от много кода и все такое + соотв вы избавлены от проблемы - "ой при конвертации надо еще токен доложить"
- код которые умеет что-то такое с этой структурой делать поделен на четкие группы и не мешается с сданными, что ортогонально объектному подходу, но в целом по моему опыту скорее удобно, чем нет.
Из минусов тут - спеки вот этих функций и их зацепление друг с другом на 28-ом году объектного мира мозг большинства программистов скорее всего будет проектировать с трудом.
А да, еще в плюс функций - когда вы сидите "в объекте" и пишете там код для унификации - у вас не так много контекста и часто сложно придумать унифицированную систему крючочков за которые будут цепляться обработчики и это порождает печально знаменитые фабрики классов процессоров и всякое такое.
Если смотреть из функции - то обычно в нее проще передать много разного контекста, что концентрирует полезный код внутри тельца функции а не размазывает по 10050 фабрик классов.