The Art of Rx

в 15:15, , рубрики: android, android development, java, rx, rxjava, zip, Блог компании JUG.ru Group, разработка мобильных приложений, Разработка под android, реактивное программирование

Проблема, друзья. Реактивщина везде, её слишком много и уже никому от неё не спрятаться. Мы с вами все умеем написать ASyncTask, Service или ContentProvider (я в это верю!). Все можем повернуть битмапу или сгонять на сервер за данными. Это все довольно очевидно. Но ещё МЫ ДУМАЕМ, что можем готовить реактивищну правильно. Это далеко не всегда так.

Я покажу на примерах, как делать не надо и как нужно делать обязательно.
Я расскажу, что такое контракт потока и как его соблюдать.
А также покажу, какие части внутри RxJava меня особенно радуют.

Пишу на Scala под Android, люблю функциональщину и реактивщину. Довольно консервативен в плане выбора технологий и фреймворков. Ну а раньше я работал тимлидом в 2GIS.

Так Матвей Мальков обращается на сайте конференции Mobius к будущим слушателям своего доклада. Читайте наше интервью…

image

— Добрый день. Расскажи в двух словах о себе. Где работаешь, чем занимаешься, когда начал продвигать реактивный подход?

— Привет. Меня зовут Матвей Мальков. Я Android-разработчик уже, наверное, лет 5-6. Конкретно сейчас я занимаюсь Scala-разработкой в одном стартапе. Стартап находится в Москве и о нём я говорить особо много не могу. Но суть в том, что это будет такая комьюнити-платформа, наподобие Телеграма. И её я, собственно, пишу под Android на Scala.

Первый проект, который я полностью перевел на RxJava, у меня был в компании 2GIS. Архитектура, база, работа с сетью — всё. После этого начал активно продвигать фреймворк RxJava и реактивный подход в целом на конференциях. Сейчас пишу на Scala, где использую вовсю функциональный подход, а в свободное время интересуюсь новостями реактивного мира

— Пользователи Хабрахабр наверняка в курсе концепции реактивного программирования. Расскажи про особенности этой парадигмы на Android и про реактивные потоки данных.

— В программировании под Андроид довольно много особенностей, связанных с реактивным программированием. Я как раз хотел бы сказать о том, что не все принципы реактивного программирования, о которых мы попозже подискутируем, хорошо ложатся на Андроид. Чтобы не быть голословным: есть такое понятие как масштабируемость, под которой обычно понимается масштабируемость на большое количество нод, то есть это какая-то серверная масштабируемость. В Андроиде же это всего лишь масштабируемость на треды, что не есть «настоящая» маштабируемость". И она не даёт такого большого мощного импакта на систему в целом. Хотя, конечно, всё равно даёт, но по-другому.

Ещё одна особенность заключается в том, что очень много в Андроиде завязано на императивщину. То есть на мутабельность, на изменяемость данных, и конкретно из-за неё очень сложно всё это завернуть в реактивные потоки. Это приводит к тому, что приходится делать много хаков, что всё очень усложняет. Императивность Android заставляет большое количество разработчиков использовать такие вещи, как сабжекты, которые вообще-то были задуманы и сделаны для того, чтобы сращивать мир реактивный и мир императивный. Но по факту, на самом деле, все пользуются им для того, чтобы что-то легко завернуть в Observable, Это обычно происходит в ущерб архитектуре, особенно на длинной дистанции, на больших проектах. Получается мешанина из императивщины и абы как сделанной на ней реактивщины. А всё потому, что многим людям просто лень сделать правильно или они не знают, как именно правильно.

На самом деле, это в общем-то всё, потому что в правильной архитектуре под Андроид взаимодействие с сетью, кэширование и вообще вся общая бизнес-логика не должна быть завязана на какие-то андроидные части. Поэтому собственно это просто бизнес-логика, которая работает, как и в любых других проектах. Не только в андроидных.

— Главные принципы реактивного программирования (отказоустойчивость, отзывчивость, событийная ориентированность, больше возможностей для масштабирования) были сформулированы давным-давно. Насколько ты согласен с этими принципами сейчас?

— Если говорить о принципах из реактивного манифеста, который, собственно говоря, и является фундаментом и основой идеологии реактивного программирования, то в своей статье на Хабрахабре я подробно раскрывал все эти пять принципов и проецировал их на Андроид-разработку. И безусловно да, я с ними до сих пор согласен. Это костяк, это основные принципы, основные импакты, на которые стоит рассчитывать, когда ты разрабатываешь, используя реактивный подход, и это основные вещи, за которые ты должен бороться, когда ты используешь реактивщину.

Если мы берём отказоустойчивость, то ты всегда должен думать об этом. Это довольно легко, но ты всегда должен держать это в голове. Правильно обрабатывать ошибки и спрашивать себя, все ли кейсы ты обработал и рассмотрел. Реактивщина даёт тебе удобные устройства для этого, но ты всё равно должен об этом думать. И соблюдение всех этих принципов позволяет тебе строить очень хорошие архитектуры и очень хорошие приложения. И, как я уже говорил про масштабируемость, в Андроиде она особо не даёт какой-то импакт, разве что на треды проецируется.

— Что важнее: ресурсоёмкость или надёжность? Ведь есть лимит на выдачу потоков в Android, можно выбросить бюджетные устройства за «борт», просто потому, что приложение (стало) более требовательно к ресурсам :)

— Конечно и безусловно, намного важнее надёжность, потому что сейчас в андроид-мире наметился тренд на то, что очень много устройств находится в дешёвом сегменте. В Индии запустили Android One, в Америке продают телефоны за несколько долларов. То есть появились очень дешёвые и супердешёвые андроид-смартфоны, которые безусловно не могут работать также, как Nexus 6P. Владельцев таких смартфонов становится всё больше и списывать их всех со счетов нельзя.

Но, конечно, про ресурсоёмкость забывать тоже нельзя. Она не вторична, эти два принципа должны идти параллельно друг другу. В той же реактивщине мы можем в зависимости от устройства, от количества ядер задавать разное количество потоков для операций. То есть пусть в бюджетных устройствах что-то работает медленнее, но работает точно и отрабатывает чётко. Пусть это занимает больше времени, но тем не менее. Между этими вещами стоит находить баланс, но внимание держать нужно на обоих!

— Ты сказал, что довольно консервативен в плане технологий и фреймворков. Расскажи про фреймфорк RxJava и его плюсах и минусах.

— Есть такая вещь как Framework-driven-development. Это болезнь, наверное, фронтенда в первую очередь. Да и всего андроид-мира. Представь, что ты не можешь решить какую-то задачу быстро, и тебе конечно же лень думать и ты пытаешься найти какой-то фреймворк, который написал никому не известный индус. У этого фреймворка версия 1.0.0 или 1.0.1, то есть пропатчил он его всего один раз, а написал года три назад. И он как-то удовлетворяет твои нужды. Библиотека не расширяемая, может падать, но свою работу как-то выполняет. Это очень сильно распространено и люди постоянно тянут подобные фреймворки к себе в проект. Я считаю, что так делать нельзя и поэтому везде пишу, что я довольно консервативен в этом плане.

Что можно сказать про фреймворк RxJava? Очень круто, что около него уже есть мощное комьюнити, он часто правится, баги всё время фиксятся. Прикольно, что идёт в разные стороны импрувмент RxJava, т.е. они и нацеливаются на быструю обработку каких-то событий, что очень важно для андроида, и в такой же степени они работают над тем, чтобы RxJava хорошо работала в серверной части. Например, уже была добавлена обработка backpressure, а это уже бекэндовая штука. Раньше там был только on-backpressure-buffer и on-backpressure-drop, а теперь они позволяют кастомно обрабатывать все эти backpressure. В современном Андроиде тоже приходится с этим сталкиваться — не только в высоконагруженных системах. Особенно если система построена на реактивщине, много потоков, один очень быстро пишет данные, а другой поток медленно их читает (неторопливый норвежский читатель) и тогда обработчик начинает задыхаться. И это тоже надо обрабатывать, а обычно Андроид-разработчики не очень в курсе того, что такое backpressure, и очень удивляются, когда слышат эти слова. А это важно и нужно знать в процессе Андроид-разработке.

Минусы у RxJava, безусловно, тоже есть. Дело в том, что это совершенно другой подход, если мы говорим об Андроиде. До сих пор в этой ОС больше применяется императивный подход, а RxJava – это больше функциональщина. И очень немного людей умеют правильно «готовить» RxJava. Даже я сам не супер-правильно понимаю все концепции RxJava, потому что это очень глубокая штука. Но в свою защиту могу сказать, что даже на практическом уровне не все понимают этот фреймворк. :)

Также в очевидных минусах нужно отметить то, что происходит очень много копирований объектов. К чему это приводит – понятно. Это дополнительная нагрузка на GC.

— RxJava vs Bolts: принципиальная разница между ними? Какие у тебя личные предпочтения, ну и потенциал каждого из конкретных подходов?

— Я с Bolts практически не работал, так чисто пробовал потыкать. RxJava мне кажется более родной и лаконичной в плане синтаксиса. Она хорошо выглядит и довольно удобная. Но в то же время Bolts более глубок в плане реактивного подхода. Одни только async и await доставляют, которых, кстати, в “нормальной” RxJava нет. Bolts, как мне кажется, более низкоуровневый и близок к фундаментальным вещам.

Потенциал ясен и он огромен. И одна, и другая библиотека нанесли огромный импакт на разработку. RxJava, насколько я вижу, повлиял больше, так как Bolts всё-таки меньше используется. Какой библиотекой пользоваться – выбор каждого, но мне кажется, что RxJava попроще в плане синтаксиса и понимания.

— Как ты оцениваешь современные приложения от топовых разработчиков: 2GIS, Soundcloud, Facebook и какая у них разница в подходе к парадигме?

— Это абсолютно разные приложения, начиная с того, что они про разные вещи. 2GIS про геолокацию и карты, Soundcloud про музыку, а Facebook про социальные вещи. Они интересно подобраны, потому что написаны на абсолютно разных технологиях. 2GIS написан на Qt 5 + QML, Soundcloud — джавовое приложение с использованием реактивщины RxJava, а Facebook сейчас написан на Reactive Native. Как минимум в этом уже есть принципиальная разница. Плюс есть разница в том, как они относятся к своим пользователям.

То есть, например, Facebook не соблюдает все гайдлайны и у фейсбук-мессенджера есть такая вещь, как Pop-Up или Overlay. Когда ты чатишься, у тебя прямо на рабочем столе стоит лицо того, с кем ты переписываешься. И по клику на него открывается приложение, которое перекрывает всё, что сейчас есть на экране. Так делать не очень правильно и меня лично очень раздражает.

Soundcloud старается привнести много стандартного материал-юзер-интерфейса, но тем не менее очень красиво. Все их треки, которые бегут, когда играет музыка, это всё очень круто и сложно в разработке именно фронтэнда.

Ну а 2GIS – это 2GIS. (кстати, знаете, что правильно произносить не “дубльГИС”, а “двагис”? Теперь знаете! :) У них свои запары, у них QML и они вроде как не могут особо использовать стандартные андроидовские виджеты. Суть в том, что они тоже стараются следовать стандартному материал-дизайну, но у них не всегда это получается.

Мне очень нравятся приложения типа Soundcloud или Телеграма, которые очень быстро работают. Я не знаю, как их оценивать. Приложения работают стабильно и хорошо, дизайн может кому-то нравиться, а кому-то — нет. А парадигмы у них всех разные.

— Как ты оцениваешь динамичность развития реактивного программирования и применение в сферах, отличных от мобильной разработки (Elm)?

— Про Elm ничего сказать не могу, потому что никогда не пользовался. Само же реактивное программирование сейчас, как я вижу, набирает обороты. Оно нашло очень хорошую нишу в server-side, много компаний используют его в своих серверах, что позволяет создавать хорошо маштабируемые сервисы, работающие под большими нагрузками. В BigData тоже можно легко увидеть такие вещи как Akka Streams и RxJava. Вот такой «крутой» (нагруженный, распределенный и бла-бла) сервис как Netflix написан на RxJava почти полностью.

Что касается фронтенда, то я за тенденциями веба не очень слежу. Но знаю, что пишут на ClojureScript много и что есть RxJS, который вроде как тоже нашёл свою нишу. Главное, чтобы дальше всё это продвигалось и развивалось, потому что реактивщина много где уже пригождается и будет обидно, если весь подход свалится во что-то нишевое.

— О чём будет твой доклад The Art of Rx на конференции Mobius 2016?

— О чём будет мой доклад The Art of Rx? Доклад планируется такой более философский, о том, куда идёт реактивщина и о том, как на самом деле правильно её готовить. Я рассмотрю некоторые аспекты, связанные с построением архитектуры приложений с использованием этого подхода. Язык не поворачивается совместить слова «архитектура» и «программирование». Как ни странно, эти ошибки очень многие допускают! Как я об этом узнал? Да очень просто! Я их частенько вижу на всяких форумах. А почему? Да потому что люди много чего делают неправильно в самой реактивщине и пошло-поехало: становится очень сложно всё это поддерживать и вся идея реактивного подхода как будто бы рушится. Ну а я в докладе попытаюсь рассмотреть некоторые архитектурные вещи внутри самой RxJava. А именно: как на самом деле работает тот же flatmap, покажу интересные вещи, связанные с Zip, ну и коснусь нескольких внутренних вещей, например, как создаётся Observable из Observable. В общем, интересных штук я заготовил прилично :).

Многие об этом, наверное, просто никогда даже не задумывались и я постараюсь все так преподнести, чтобы было интересно и познавательно. Самое главное – познавательно.

Видео с прошлого Mobius:

Автор: JUG.ru Group

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js