Некрутов Эдуард @Not_coolEd
НеКрутой Архитектор
Information
- Rating
- Does not participate
- Location
- Москва, Москва и Московская обл., Россия
- Date of birth
- Registered
- Activity
Specialization
Mobile Application Developer, Software Architect
Lead
Java
Kotlin
Android development
Clean Architecture
DDD
Designing application architecture
OOP
JavaScript
C#
Scrum
Могу сформулировать такую мысль, для всех тех, кто считает, что интерфейсы являются излишними, хотя надеялся что получится без этого)
В определенных случаях, для некоторых бизнесов, при конкретных планах развития, интерфейсы для сущностей UseCase и FeatureCase, действительно могут являться излишними. Ваш большой опыт разработки и насмотренность на различные проекты, может позволить вам это понять. Вот только у новичков или мидл разработчков такого опыта не хватает или его вообще нету. Поэтому для них и пишутся правила так, чтобы эти абстракции были всегда.
Если вы в состоянии взвешено и рационально принять решение о том, что в вашем случае какие-то абстракции являются излишними, то это признак того, что у вас достаточно опыта, чтобы понимать различные принципы архитектуры и не задавать подобные вопросы, чтобы не вводить в заблуждение новичков. Если вы сомневаетесь в необходимости интерфейсов, то для вас интерфейсы обязательны. Хуже они не сделают точно, поэтому гораздо лучше сделать лишнюю абстракцию, чем не сделать ее там, где она окажется нужна.
Я так и не понял как связаны ресурсы и библиотека)
Работа с ресурсами происходит на View, но при этом ViewModel может знать про существование ресурсов, их id и возможно способ как их достать,
Если говорить про библиотеку, она должна проектироваться совершенно без знаний о том, где будет применяться.
Она может быть заточена под использование на конкретной платформе, например, предоставлять ui для android. Тогда это android либа, которая может иметь собственные ресурсы и способы с ними работать. При этом из библиотеки ты никак не может иметь доступ к внешним ресурсам.
Пока что я ничего не предлагаю, потому что не понимаю вопроса. Раскройте, пожалуйста, вопрос более подробно, чтобы я мог предложить вам какое-либо решение)
Отличный вопрос!) Чисто физически можно сделать и так и так. Однако, сложив все в один модуль, мы теряем преимущества модуляризации. Разбив модули по 1 интерфейсу, мы создаем излишний оверхед.
Лучшим критерием объединения модулей является общий контекст. Например:
data-api которые возвращают Chat и Message, лучше объединять, потому что это связанные сущности. Однако feature-api по работе с чатами, можно отделить от feature-api по работе с сообщениями, так как использоваться они будут в разных контекстах. При этом мы не отменяем того, что в контексте чата мы можем возвращать список чатов вместе с последним сообщением.
Только начал, поэтому не судите строго) И пока особо нету времени активно продолжить, но обещаю, что не заброшу) https://github.com/NekrutovEd/EasyFinance
Доступ к контексту есть только в 2 местах.
AppContext - при создании графа зависимостей, чтобы создавать различные библиотечные зависимости.
ActivityContext - на View, чтобы достать что-то из ресурсов. Можете почитать о том, как делаются обертки Text, которые получают значения из ресурсов при установке во View, или про то, как делают ResourceWrapper, для ViewModel.
А так, если у вас вопрос, для чего они так поступили с контекстом, то советую лучше ознакомиться с его документацией. Возможно у вас появится более хорошее архитектурное решение и нам всем станет жить легче)
В данном случае, мы можем вынести в отдельный модуль, на уровень common, view для нашего списка и модель этого списка. Они связаны 1к1. Маппинг мы не сможем сюда вынести, потому что это уровень common, а связи снизу вверх запрещены.
В 2 разных screen модулях мы можем зависеть от одних и тех же feature-api и common-my-list-ui.
В такой ситуации нам придется продублировать маппинг в каждом из screen модулей.
Важно понимать, что дублирование это не плохо. В данном случае у нас есть 2 независимых друг от друга экрана и каждый из них может измениться самостоятельно, изменив как отображение, так и логику получения данных.
К тому же, такая схема позволяет использовать ui для списка не только с этими данными, но так же и с другими данными из других предметных областей.
А дублирование, это не плохо. Бывают случаи, когда лучше 10 раз продублировать, чем после пытаться внести изменения для каких-то случаев в общий код, который мы решили не дублировать.
Большое спасибо за обратную связь, я старался)
А где этот enum лежит? Где и для чего используется? Я не очень понимаю условия вопроса. Можете, пожалуйста, предоставить более подробное описание проблемы?
В крайнем случае, можно сделать съемные колеса большего диаметра, чтобы можно было тягать массивный чемодан даже по камням. Однако причина того, что их не делали в другом. Мужчины считали не достойным тянуть за собой чемодан на веревке, вместо того, чтобы мужественно тащить его превозмогая сложности.
Эта история больше о том, что очевидные для нас вещи, не всегда являлись очевидными. Казалось бы, что может быть очевиднее коробки для бумаг или раскладывания документов по папкам и стопкам? Однако люди долгое время перевязывали стопки бумаг веревками и складывали их в кучу "как-то". На самом деле, существует достаточно много таких случаев, когда казалось бы очевидные для нас вещи, никому не приходили в голову.
Нужно понимать объем приложения. Проблемы скорости сборки ни кто не отменял для больших приложений. И одно из решений это разбиение на маленькие модули по принципу api/impl, чтобы завязка была на интерфейсы, которые имеют гораздо меньший коэффициент изменчивости, по сравнению с реализацией.
А так же интересно посмотреть, как вы разобьете функциональность на модули, не имея интерфейсов, сохранив при этом гибкость переиспользования различных компонентов.
Любая библиотека всегда находится на самом низком уровне зависимостей. То есть она априори не может быть зависима от нас. В таком случае у нас остается только вариант инверсии зависимостей. Когда библиотека выдает контракт в виде интерфейса, который мы должны реализовать и передать ей при инициализации. Это может также выглядеть как плагины, подключаемые к библиотеке или другие способы инверсии зависимостей.
В рамках текущей статьи это не имеет значения, поскольку модули feature level имеют право зависеть от публичных модулей из уровней ниже. А управление зависимостями и инициализации происходят на Application уровне.