Ставлю курсу твердую четверку.
Что понравилось:
1) понравились некоторые интересные технические тонкости, которые интересно было "пощупать" через реальный код + вариант реализации паттерна Outbox
2) примеры с VM-фабриками были тоже очень познавательными.
3) примеры с combine да, очень хорошие - в коммерческих приложениях это главная "рабочая лошадка" :)
Что не понравилось:
1) В паре мест автор дает идею и тут же отказывается от нее. Если идти по курсу последовательно, то в коде остаются ошибки, которые нужно исправлять самостоятельно.
Так, например, было в SyncWorker, где автор попала в тупик собственного подхода - отказа от DI + хранения основных data-классов приложения (репозиториев) в MainActivity.
Как мне кажется, курс смотрелся более выигрышно, если бы репозитории, БД и классы сетевого слоя хранились бы в отдельном Application-классе с ленивой инициализацией, а SyncWorker получал бы нужную ссылку через отдельный SyncWorkerFactory, например, так:
class SyncWorkerFactory(
private val repository: SyncRepository,
) : WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): ListenableWorker? {
return when (workerClassName) {
SyncWorker::class.java.name -> {
SyncWorker(appContext, workerParameters, repository)
}
else -> null
}
}
}
а Application-класс определили бы как Configuration.Provider и добавили бы туда код:
val syncRepository by lazy {
SyncRepository(
db = db,
api = api,
)
}
override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(SyncWorkerFactory(syncRepository))
.build()
Ну и в целом, собирать конгломерат классов с ЖЦ уровня приложения внутри MainActivity - это не очень хороший пример. Учитывая, что курс могут проходить начинающие разработчики, я бы все-таки переработал код курса, чтобы плохие практики не перенимали ученики.
2) В проекте сделана не очень хорошая штука - классы распределяются по пакетам по типам, а не по функциональности.
Например, VM-ки - в отдельный пакет "viewModel", dao-классы - в DAO и т.д.
В крупных коммерческих приложениях так не делают никогда, потому что:
а) Код пишут несколько команд и за каждым пакетом закрепляется свой оунер. Все кодоунеры перечислены в классе CODOWNERS и на код-ревью при изменении кода, закрепленного за отдельной командой, бот будет "тегать" именно того человека, который имеет отношение к измененном пакету в проекте.
Если все VM-ки будут в одном пакете, начнется хаос - бот будет тегать всех подряд, включая людей из совсем других команд.
б) фича не всегда пишется "на века". Например, сегодня в приложку добавили таблицу "leaderboard", а завтра у менеджмента зачешется левая пятка и скажут, что фича не востребована пользователями и ее нужно выпилить. Конкретно в случае этого проекта весь код удаляемой фичи нужно будет собирать по разным пакетам и удалять. А если фича хранится в отдельном модуле или пакете, то удаление для остальных команд будет максимально простым - просто дропнули нужный каталог и все.
3) В коде в нескольких местах есть ошибки + нет импортов, что делает менее удобным добавление кода - приходится тратить дополнительное время на ненужную работу.