Среди Android-разработчиков Артём Зиннатуллин пользуется таким уважением, что про него можно сочинять аналог «фактов о Чаке Норрисе» — что-нибудь такое:
- Артём так суров, что при его виде гитхаб сам зеленеет (кто из нас может похвастаться таким графиком contributions?)
- Артём так суров, что для него git — это мессенджер.
- Артём так суров, что в его приложениях context — это подкаст.
Когда на нашей конференции Mobius мы брали у него интервью, оно предназначалось для онлайн-трансляции. Но увидев, как на него ссылаются в Android-чате, мы решили, что на Хабре оно тоже может многих заинтересовать, и сделали для вас текстовую версию (видеозапись также прилагаем).
Как жить с проектом на миллион строк кода? В чём недостаток корутин Kotlin? А в чём неправ Google? Чем разработка в Сан-Франциско отличается от российской? Чему был посвящён доклад на Mobius? Под катом — обо всём этом.
Евгений Трифонов: На этом Mobius я пропустил ваш доклад «Android builds at Lyft», но после него в дискуссионной зоне видел толпу желающих задать вопрос. И захотелось уточнить: но ведь большинство зрителей работают не в гигантском проекте вроде Lyft, для них всё равно оказался релевантен этот опыт?
Артём: Это интересная вещь. Изначальный план доклада в моей голове, и то, как я в итоге его реализовал, сильно отличаются благодаря вашему классному программному комитету.
Изначально я собирался рассказать, с чего у нас в Lyft все начиналось, почему мы пришли к определённым техническим решениям. Рассказывал два часа Сергею Боиштяну из программного комитета, он послушал и говорит: «Классно, конечно, но это ты кейноут сделал». И в итоге я понял, что такой доклад, конечно, интересно послушать, но он действительно мало для кого релевантен.
И тогда я переделал его, сместив акцент на принципиальные инженерные подходы к выбору системы сборки, других систем. У меня не было цели рассказать, какие инструменты используем конкретно мы. Я не хочу, чтобы кто-то взял и слепо начал их использовать, а потом писал мне грозные письма, что не всё работает так, как я рассказывал. Хотелось донести именно инженерные практики о том, как делать выбор, и что важно по моему (естественно, субъективному) мнению. Поэтому я надеюсь, что в итоге опыт оказался релевантен большему числу людей, а не просто «чувак из Lyft вышел и что-то рассказал».
Олег olegchir Чирухин: А есть какие-то необычные выборы Lyft, которые другим сделать сложно?
Артём: Да, конечно. У нас в проекте одновременно две билд-системы, абсолютно никому не рекомендую (смеётся).
Очень больно поддерживать: постоянно гоняешься за двумя зайцами, в обеих что-то не работает до конца. Но это наше текущее состояние, так исторически сложилось, потому что одна билд-система начала затыкаться на части задач, пришлось заводить вторую. Я рассказывал о том, как этого избежать и правильно смигрировать на одну из них.
Олег: А что за билд-системы?
Артём: Мы используем Gradle и Buck, а я рассказывал про то, как прийти к Bazel от Google.
Олег: Это какое-то движение в сторону зла: от няшного Gradle к Bazel, в котором даже зависимостей по-нормальному нет.
Артём: Сейчас уже более-менее есть. Ну да, конечно, есть трейд-оффы, и, конечно, у Gradle есть свои достоинства. Всё зависит от типа проекта. Некоторым Gradle подойдет больше, чем Buck и Bazel, потому что у них есть принципиальные моменты, по которым они в рамках одного модуля не будут собирать инкрементально, а Gradle будет, и многим это очень важно. И классно, что Gradle так может.
Другое дело, что когда вы добавляете модули — больше, больше модулей, восемьсот, тысячу, — Gradle так задизайнен, что он будет линейно замедлять сборку в некоторых местах. Но мне кажется, Gradle может всё это пофиксить, если на них комьюнити надавит — что, может быть, я и делаю. Посмотрим. (прим.: спустя несколько дней после этого интервью Артём написал большой пост о проблемах Gradle)
Олег: То есть Bazel только потому, что хочется поддерживать большое количество модулей?
Артём: Скажем так, в нашем случае не «хочется», но разделение проекта на модули позволяет нашему бизнесу двигаться быстрее. В основном, насколько я понимаю, это изоляция, чтобы не получалось спагетти, которое потом сложно поддерживать. Модули дают больше контроля над тем, какие части кода с какими взаимодействуют. У нас почти миллион строк кода. Если бы это было в одном модуле, пришлось бы спагеттизировать. Потому что поверх языка — Java, Kotlin — надо будет что-то накручивать, чтобы запрещать вызовы между пакетами, между которыми никто их не ожидал. Плюс там возникнет вопрос, что и Gradle не вывезет такое количество кода в одном модуле. Он не будет его параллельно, инкрементально собирать внутри модуля.
У каждого решения есть трейд-оффы. В нашем случае, мне кажется, это правильное решение, но есть и проблема — в том, что мы на данный момент поддерживаем две системы сборки.
Олег: А что лучше для сотен модулей: монорепо или много репозиториев?
Артём: Это очень больной вопрос. Наверное, один репозиторий лучше с той точки зрения, что не надо думать про версионирование и нет этого dependency hell, когда ты ходишь и клонируешь десяток репозиториев, чтобы сделать одно изменение, а потом открываешь один pull request и еще десяток после него. Из системы убирается «трение», и люди не боятся менять код. Для них возникает атомарность изменений: все закоммичено в один проект, и изменения одного модуля автоматически переносятся в другие без их явного согласия. При этом все проверки, которые вы автоматически написали на CI, выполнятся и проверят, что код компилируется, тестируется и все вот это.
Олег: А не придёшь ли ты в результате к тому, что у тебя, как в каком-нибудь Chrome, ветки будут меняться по две минуты, пока ты пьёшь чай?
Артём: Да, конечно, есть вероятность. Но тут, наверное, вопрос уже в размере продукта: а нужно ли Chrome держать в себе столько кода? Может быть, стоит выделять какие-то части в отдельные инструменты, которые они будут периодически подтягивать, когда в них будут происходить мажорные изменения? Это, наверное, вопрос к организации проекта. Классный пример, кстати. У меня есть похожий: переписка с чуваками из Яндекс.Браузера, где у них тоже большие затыки.
Chrome можно разбить на несколько составляющих, и если взять какой-нибудь V8 — я не большой специалист, но насколько я понимаю, он мог бы быть вообще отдельным проектом, правильно? И зачем тогда графическому интерфейсу знать про движок, каждый раз пересобирать его и думать о том, что исходники должны валяться где-то рядом? Bazel, кстати, это тоже поддерживает.
Вообще сейчас все большие системы сборки — что Gradle, что Buck, что Bazel — поддерживают такую вещь, как композитные билды, когда ты ссылаешься, например, на другую Bazel-сборку. Это хитрая ситуация, но, тем не менее, такое работает, это позволяет убрать часть файлов из репозитория, сократить размер. IDE, например, с ума сойдёт индексировать все эти файлы, поэтому хочется как-то отделять их от общей составляющей проекта.
Но мы пока далеко от этого. Мне кажется, нам можно ещё лет пять спокойно фигачить. В двухминутный checkout мы пока вряд ли упрёмся. У нас не так много людей.
Евгений: А в Lyft есть ещё своя специфика, помимо двух систем сборки?
Артём: Да, там есть пара нетипичных историй. Так сложилось, что люди, которые пришли в компанию (из Google, Facebook, отовсюду), ненавидят монорепозитории. В итоге у нас в Lyft есть три монорепозитория: Android, iOS и L5 (это наши автономные автомобили).
А всё остальное — это больше 1500 git-репозиториев: у всех микросервисов, у всех библиотек по отдельному. Так исторически сложилось. У этого есть своя огромная цена, которую мы платим: протаскивать сквозь них изменения реально сложно. С другой стороны, при работе с каждым из них у тебя мгновенный git clone, мгновенный git push, всё очень быстро, IDE индексирует за секунду. Могу сказать, что это действительно интересная часть. От чуваков из Сан-Франциско я бы ожидал монорепозитория.
Олег: А когда один из этих отдельных репозиториев обновляется — меняется API, например — как это изменение распространяется на всю остальную компанию?
Артём: Больно. (смеётся) Ну, я не бэкенд-разработчик в том плане, что я не пишу feature-бэкенды, я пишу инфраструктурные бэкенды — они, как правило, достаточно автономные в этом отношении.
Как правило, это просто куча митингов, кросс-взаимодействие и потом планирование.
Олег: То есть митинги являются частью системы сборки? (смеются)
Артём: Да, сначала надо собрать митинг, потом собрать репозиторий. Плюс, к сожалению, исторически сложилось так, что у нас многие из этих микросервисов — это Python, который тоже со своими приколами.
Олег: Проскользнула какая-то нелюбовь к Python.
Артём: Скорее нелюбовь к динамической типизации. Python, не Python — без разницы, а вот динамическая типизация — это больная штука.
Евгений: А ещё проскользнуло «для компании из Сан-Франциско», и любопытно спросить вот что: а чем с точки зрения разработки компании из Сан-Франциско отличаются от компаний из России, есть заметная разница?
Артём: Очень большая разница. Я не большой любитель так классифицировать, но мне кажется, что здесь более правильная инженерная школа.
Олег: Здесь — это где?
Артём: В России, в странах бывшего СССР. Люди уделяют больше внимания техническим аспектам работы компонентов их системы. А в Штатах часто бывает так, что какая-то библиотека решает задачу, и люди даже не смотрят, как она реализована. Им, как правило, абсолютно неважно, что она тормозит или что они используют её неправильно.
Я там очень много собеседую людей, потому что это часть работы, и общий уровень знаний, пожалуй, пока что ниже. Там есть что изменить. Каждый раз, когда приходит человек из восточной Европы, на собеседованиях становится интереснее, потому что люди не боятся чему-то воспротивиться, где-то поспорить. В то время как кандидаты из США очень часто могут вообще не отвечать на вопросы или отвечать «Не помню, когда я последний раз это использовал». На вопросы вроде «Как работает HTTP-запрос?» или «Какой формат данных ты выберешь?» они не могут дать нормальных инженерных ответов, а говорят: «Ну, я вот это использовал последние лет пять». Круто, конечно, но на сеньора не тянет.
С другой стороны, есть проекты, которые ушли на годы по сравнению с тем, что мы здесь делаем. Люди делают более массовые продукты, и там попросту больше масштаб. Например, Chrome или Uber — у них там уже больше тысячи модулей. Это просто масштаб проблем. Скажем, в Uber под триста Android-разработчиков. Возникает вопрос: зачем? (смеётся) Но, тем не менее, они умудрились заставить эту махину работать, постоянно релизиться. Я бы сказал, такие вопросы здесь решаются реже.
Вот Яндекс — хороший пример. У меня есть друг в Яндекс.Картах: Android-приложение делают десять человек. В Google, скорее всего, сотня сидит. И при этом у Яндекс.Карт больше функционала. Вот и разница, на мой взгляд.
Евгений: Помимо этого, Долина ассоциируется ещё и со стартапами, а у них подход «move fast and break things», и кажется, что это на разработке тоже должно сказываться: жить на bleeding edge, использовать всё самое новое. Это правда?
Артём: Я не работал в стартапах, Lyft сложно так назвать: там уже тысячи три человек, где-то больше тысячи из них инженеры. То есть это уже сформировавшаяся компания.
Именно cutting edge-технологии используют достаточно редко. Если технология раскручена, тогда да. Если технология нишевая, но крутая — очень часто нет. Пока про неё на всех конференциях не поговорят, очень мало людей будет её использовать.
Но при этом что я очень люблю (в Сан-Франциско и частично в Долине) — очень многие вопросы решаются за счёт того, что компании физически близко. Очень часто ты пишешь кому-нибудь в чатике: «Давайте пообедаем вместе у нас или у вас в офисе и решим, продвинем какой-нибудь вопрос», а потом раз — и появляется опенсорс-проект или pull request в другой проект, что-то фиксится.
Что интересно: люди очень часто обсуждают вещи, которые вообще-то не должны обсуждать по NDA. Но так двигается вся Долина, в итоге все понимают, куда двигаются остальные, и вся индустрия идёт вместе. Скажем, мобильщики Lyft и Uber постоянно общаются про технические вещи, потому что мы используем опенсорс из Uber. И, конечно, там есть прямо хардкорные специалисты по каким-то технологиям. Это тоже классно: с ними можно просто пересечься.
Я такое люблю, и мне этого не хватало в некоторых городах, где я жил. Вот в Питере была очень классная Java User Group (я уже не знаю, как там сейчас): приходишь после работы, а тебе Шипилёв выносит мозг, и чего-то хорошо!
А там опять такое появляется: например, там тоже есть своя Java User Group, и туда часто приходят чуваки, скажем, из Oracle, которые запилили какой-нибудь новый Reactive JDBC. И вы сидите, спорите, потому что там же сидит какой-нибудь лид Project Reactor или лид Reactive в Spring, идёт прямо горячее обсуждение, и это классно.
Олег: Спрошу о другом: я посмотрел на репозиторий Mainframer, и там используется Rust. Почему всё это написано не на благословенной Джавке, а на каком-то Расте?
Артём: Я в последнее время упоролся в сторону того, что программа должна есть минимальное количество ресурсов. То есть хочется быть очень близко к тому, как железо переваривает байты. А в Java очень много всего происходит вокруг (это я даже не говорю про сборку мусора), то есть JIT и всё вот это. Мне очень нравится, что Java сейчас идёт в сторону того, что там будет ещё и ahead-of-time compilation. Мне кажется, будет очень круто, например, начать запуск микросервиса с того, что ты скачиваешь с кэша его ahead-of-time compilation, который изначально произошёл на каких-то других машинах, и стартуешь его очень быстро, без прогревов. Это классно, но у Java есть цена. Я не могу просто так попросить людей, которые собирают iOS-проект, иметь Java в системе.
Изначально Mainframer был написан на диалекте Bash. Но хотелось переписать его на системном языке, чтобы получить нормальную многопоточность, возможность писать нормальные юнит-тесты, а не просто интеграционные тесты поверх утилиты…
Олег: И можно было бы взять, например, Python.
Артём: Да. Но тогда возник бы вопрос с тем, что, во-первых, это динамическая типизация, а, во-вторых…
Олег: Так в Bash же тоже динамическая типизация.
Артём: Так вот и хотелось переписать. А кроме этого, есть проблема с тем, что Python сейчас два: в macOS по умолчанию второй, а почти во всех в Линуксах сейчас третий. Возникают всякие такие приколы. Если мне понадобится какую-то зависимость связать, что я, буду просить людей запустить pip? Или мне придется её бандлить?
Хотелось взять системный язык, который требует ноль зависимостей, чтобы я мог поставить бинарник, который будет весить, условно, меньше мегабайта, и работал с минимальными накладными расходами.
Олег: Можно было взять Golang, там хотя бы есть garbage collector.
Артём: Вот как раз по этой причине и хотелось попробовать Rust. И заработало. Плюс в Golang как-то грустновато с дженериками.
Евгений: Раз начали обсуждать языки… В контексте Android-разработки вопрос «Kotlin или Java» уже надоел, но всё-таки задам его для того, чтобы дальше перейти к следующему вопросу.
Артём: Ну, Kotlin, конечно.
Евгений: Теперь тот вопрос, который по-настоящему интересует. Недавно в Kotlin корутины стали stable, и слышны голоса «ура, давайте уйдём от RxJava». Поэтому, когда вижу перед собой человека, которому RxJava очень близка, сразу хочется спросить его мнение о корутинах.
Артём: Я был очень негативен по отношению к корутинам. В принципе, до сих пор по большей части негативен, но это отчасти изменил очень долгий разговор с Ромой Елизаровым, который работает над ними.
Как пользователь программ я хочу, чтобы они были максимально неблокирующими, максимально правильно использовали ресурсы. Под этим я имею в виду и параллельность, и то, чтобы они использовали правильные API операционных систем для неблокирующих обращений к сети или файлам — с этим в операционных системах очень много проблем, но, тем не менее, такие API есть. Чем именно это решается? Мне как пользователю не важно — лишь бы разработчики решили эту проблему так, чтобы им было комфортно. С этим у меня больших проблем нет. А в этом и есть видение Ромы Елизарова. После этого разговора меня как-то попустило.
До этого мне, как и моему другу Артуру Дрёмову, после нескольких лет использования Java в продакшне это казалось шагом назад: код снова становится императивным, нечистым, в нём теряется понимание пайплайна, он снова становится месивом, которое компилятор за тебя превращает в асинхронное месиво.
Я не использую корутины, но все примеры, которые я сейчас наблюдаю, перешли к структурированному подходу, когда ты вообще не видишь, какой кусок кода из этого является корутиной. Мне, если честно, очень страшно на это смотреть. Потому что я открываю pull request на GitHub, там вызываются какие-нибудь методы для загрузки картинки и профиля, один из них сходит в сеть, а другой — в локальный SQLite, и вот локальный SQLite спокойно может оказаться блокирующим. В коде я этого не вижу, потому что корутины сделаны так, чтобы ты этого не видел. Может, это хорошо, но для меня это пока что минус дизайна, потому что в Rx-подходах это очень явно: ты понимаешь, это часть синхронного пайплайна или нет.
Пожалуй, это единственная моя претензия к корутинам: я хочу видеть, когда у меня происходит асинхронность, а когда нет. В идеале я хочу, чтобы люди писали более функциональный код, когда есть маленькие переиспользуемые или хотя бы тестируемые кусочки, которые комбинируются с другими. А мы обратно приходим к тому, что инлайним это всё в логику, а компилятор потом это просто перешинковывает.
Олег: Дай я немножко пооппонирую. Легаси-кода куда больше, чем нового. И если мы берём какие-то вещи типа работы с сетью, работы с файлами и так далее, то никто не будет по-быстрому переписывать всё это, например, с использованием RxJava. А если у нас есть автокорутины, то мы можем, например, отследить все syscall'ы, автоматически их обернуть и отправить на блокировку туда, на паркинг.
Артём: Правда, в любом случае придётся вызывать функции из контекста корутин. Но это интересная мысль, да.
Олег: Может, их как-то сочетать? Верхнеуровневый API будет на RxJava, а низкоуровневый — на корутинах.
Артём: Да, есть сейчас такие подвижки. Но тогда возникает вопрос, потому что на данный момент RxJava может делать всё, что делают корутины, а корутины не могут делать всё, что делает RxJava. То есть первая технология может поглотить вторую, а вторая первую — нет. И поэтому, скорее всего, будут подвижки к тому, что на корутинах будет какой-нибудь кроссплатформенный Rx на Kotlin. Но это другое мышление. Это как можно взять forEach и погнали делать какой-нибудь map, а можно взять стримы и написать на них. И, кажется, даже энтерпрайзное Java-комьюнити уже одобрило и стало писать стримы, потому что это более выразительно. А с корутинами мы сейчас идём в обратную сторону.
И ещё кажется, что для Kotlin корутины — это дополнение. Насколько я понимаю, для языков вроде Go это основа, изначально часть системы типов, и все API, которые они предоставляют, так и работают: там стандартная библиотека очень сильно использует корутины. И в твоей, Олег, ситуации получается, что ты пишешь код, который может быть для тебя legacy, но он асинхронный, и это круто. А то, что мы сейчас получим в Java и в Kotlin — это legacy, и ты уже не понимаешь, асинхронный он или не асинхронный. Лучше уж одно, чем другое. Лучше иметь какое-то понимание, что происходит.
Но, как я и сказал в начале, как пользователь программ я рад. Чем больше инструментов, которые больше подходят большему количеству людей, даются им для того, чтобы писать более правильные программы — тем больше я рад. Поэтому здесь у меня абсолютно никаких претензий.
Евгений: И последний вопрос, довольно общий. После критики корутин, которыми многие очень довольны, хочется спросить: а в чём главные проблемы современной Android-разработки? Интересно, окажется ли и это идущим вразрез с чужими мнениями.
Артём: Интересный вопрос… Сложно ответить. Я бы сказал, что в принципе в Android-разработке особых проблем нет. Есть очень большое количество инструментария, который можно использовать и получить великолепное качество программы. Есть проблема в том, что его сложно масштабировать на большую команду: людям надо правильно понимать, как этот инструмент используется. И в этом RxJava очень сильно проигрывает корутинам, потому что её очень легко задействовать абсолютно неправильно: использовать для каких-то маленьких асинхронных вещей и не выражать везде логику в стримах. В этом плане корутины, скорее всего, зайдут лучше.
Мне кажется, здесь интересно сравнить с iOS. Мне стыдно это говорить, но у нас в Lyft iOS-разработчики только в этом году внедряют dependency injection и RxSwift. А сейчас подходит 2019-й. Я точно знаю iOS-команды, в которых это не так, давно используют современные подходы, clean, вот это всё. Но мне кажется, Android в этом плане — далеко не самая плохая платформа.
Пожалуй, единственное, что мне не нравится — что сейчас делает Google. Долгое время их позицией было «мы не opinionated, используйте всё, что хотите: вот вам фреймворк, а как вы его используете, нам не особо важно». Часть сообщества их долгое время за это пинала — и, на мой взгляд, зря.
Это было золотое время, когда ты мог сказать «RxJava — это решение, потому что...» А сейчас приходят люди и говорят: «Нет, мы будем использовать LiveData». Начинаешь расспрашивать, почему — она проигрывает по всем параметрам и RxJava, и корутинам, и чему угодно. Но, тем не менее, в Google посчитали, что сообществу это важно.
Многие из сообщества сейчас скажут: «Классно, что Google продвигает MVVM». И для них уже третий вопрос то, что этот MVVM абсолютно кривой и неправильный и, на мой взгляд, нарушает все принципы того, каким MVVM должен быть. И многие проекты уже перешли на то, что сейчас рекомендует Google.
Мне кажется, у них нет правильного ощущения, где заканчивается scope проектов. Очень часто неправильная архитектура в итоге разлетается по нескольким проектам.
Но при этом есть и очень классные работы: например, Room очень правильно сделан и вообще очень классная библиотека. А какие-нибудь Architecture Components — очень спорный набор вещей, которые уже были реализованы в сообществе пять лет назад. Зачем Google пришёл так поздно, да ещё и с кривым решением? Вот такие моменты меня напрягают.
Евгений: Подозреваю, что к этому месту у многих возникло жгучее желание возразить. Ну, можно тогда сделать это в комментариях. Спасибо за ответы!
Артём: Очень интересные вопросы.
Следующий Mobius состоится в Петербурге 22-23 мая. Сейчас его программа ещё не оглашена, зато это самый выгодный момент для покупки билета: уже 1 февраля цены на билеты вырастут. А также, раз программа пока не завершена, момент подходит ещё и для того, чтобы самому в неё попасть: мы вовсю принимаем заявки на доклады. Вся информация о конференции и билеты — на сайте.
Комментарии (8)
FirsofMaxim
30.01.2019 09:10Было тоже самое, когда не нашел простого аналога Dagger для iOS, но организация мультипоточности мне нравится больше в iOS.
Arseny_Info
30.01.2019 11:43+1Для любителей бодрых холиваров есть пост с критикой mainframer
Artem_zin
30.01.2019 13:12+2Привет Арсений, столетстозим
читал и улыбался, спасибо, что пошарил)
Пост стоит прочитать, прошу не оскорблять Айседа в комментариях, спасибо
Bringoff
Желание-то возникло, но немного неясно, чему возражать. Потому что конкретных аргументов против Architecture Components как-то не увидел. Поэтому возражу с тем же уровнем аргументации — LiveData и ViewModel с компонентов идеально подпирают вековые костыли андроида.
Artem_zin
Конкретных аргументов против Architecture Components не было тк короткое интервью и это был завершающий вопрос на засыпку, по сравнению, скажем, с корутинами.
Я еще и в новогоднем выпуске AndroidDev подкаста наговорил про половину библиотек из androidx, тоже без аргументации) может потом будет отдельный выпуск про это, но это к nekdenis
Попробую кратко сформулировать аргументы сейчас:
ViewModel Factory в arch components как-то очень "весело" дружится с DI, вот пример, который копируют почти во все тестовые задания, что я видел на собеседованиях, это какая то дичь и люди не могут объяснить как это работает
LiveData это, пожалуй, самая странная часть arch components. Это как писать на всё рксовых сабжектах или EventBus. Зачем это нужно когда есть Rx непонятно, харкодится на main поток, просто жесть)
Что хуже, LiveData рекомендуется к использованию с ViewModel и люди пихают в проекты и LiveData, и RxJava и сейчас еще и корутины, ад, спасибо что без AsyncTask)
На момент представления ViewModel в сообществе уже были матерые MVP, MVVM, MVI, etc библиотеки и куча статей о том, как делать кастомные варианты подобного дизайна
MVI/Redux убирает необходимость во ViewModel, люди миксуют их, но имхо там достаточно ретейнить текущий стейт объект и запускать редюсер с этим стейтом после поворота, посмотрим как оно приживется
Room чёткий, у меня никаких претензий, возможно, сейчас я бы сказал что SQLDelight это всё таки более интересный вариант, но Room кажется более декларативным (а еще есть StorIO, спасибо Диме Никитину)
то что сказал в интервью
dmdev
Добавлю что LiveData внутри завязана на Handler, и как прогонять unit-тесты?
Самое неприятное, что теперь решение ViewModel + LiveData считается де-факто стандартом. Большинство доверяют только Гуглу и смотреть в сторону намного лучших MV*-решений даже не хотят. Тот же PM или MVVM несложно реализовать на RxJava.
sergeyfitis
LiveData полностью совместима с Unit тестами