Комментарии 9
Возможно что то и справляется со своей задачей, но это точно не Dagger. Если бы Даггер справлялся, ни Koin, ни Kodein просто не было бы. Но и проблематика статьи кмк надумана, всего пару хоткеев в IDE способны показать все места инициализации и использования зависимостей.
Мультиплатформа и куча бойлерплейта. Даже Гугл советует использовать не Dagger, а Hilt, надстройку над ним. И оба они не поддерживают KMM
Koin удобнее того же Kodein, и при этом популярнее, но имеет гораздо худшую документацию
В целом мне они оба не нравятся после прихода из мира бэкенда (работаю как раз на Спринге, тут пет для себя пилю). Но тащить всё из шейред модуля наружу или цеплять раздутый тормозной Спринг - еще хуже. Вот и приходится есть кактус с резолвами инжектов в рантайме
Даггер не юзерфрендли - если ещё не набил на нём руку, то с Koin проще разобраться и внедрить в проект за счёт его значительно более простого API. Имхо, но даггер при неумелом использовании может привести к гораздо более трудноразрешимым последствиям, нежели чем коин.
А в чем сложность написать так?
factory {
BasketPresenter(
get<BasketRepository>(),
get<Analytics>(),
get<AppResources>(),
...
)
}
И понятно что принимает конструктор и сразу видно тип + можно еще добавить именованные аргументы добавить.
Можно сделать так, но остается проблема, связанная с тем, что мы не знаем какие зависимости вообще есть в графе. То есть например у нас есть модуль Core и основной модуль App. В таком варианте мы не знаем, какие классы из Core мы можем использовать в App, либо вручную проверять, либо уже в рантайме ловить падения, если какого-то класса нет в графе.
Используя ключи мы можем заранее узнать, какие классы нам доступы, имея вот такой объект:
object CoreKoinKeys {
val DEPENDENCY_1 by koinKey<Dependency1>()
...
val DEPENDENCY_N by koinKey<DependencyN>()
}
Тогда у нас появляется следующее: мы при работе с графом видим не только какая зависимость используется в классе, но из какого модуля она поставляется.
Конечно, мы не избавились от проблемы отсутствия объявленного класса в графе, приложение спокойно соберется, если будет только ключ. К сожалению, у нас не получилось придумать как можно в нашем варианте исправить этот момент, тут уже проблема самой архитектуры коина.
если у вас одна имплементация того же AppResources, то не используйте интерфейсы, а пишите сразу класс - тогда уже на этапе компиляции словите ошибку.
И модули лучше создавать там же, где и их "бины", а не где-то типа централизованно. А в самом сервисе собирать уже модули, которые он будет использовать.
Ну и не плодиьт "сложные" классы (больше 7 зависимостей в конструкторе). Да тот же Detekt на это тоже ругается
Koin создан для простоты, так что не нужно все усложнять. Вот несколько лайф-хаков:
Хоткеем из koin-модуля можно посмотреть на конструктор (BasketPresenter) что-бы понять что нужно
Хоткеем посмотреть где вызываются конструкторы для параметров BasketPresenter, если нет в koin-модуле - значит будет падать
При написании/рефакторинге зависимостей не писать get() для того чего еще нет. Тогда будет падать не в рантайме, а будут ошибки компиляции или если немного перефразировать: при написании нового кода koin-модуль писать в последнюю очередь, при рефакторинге - в первую
Делаем работу с Koin проще