Олег Годовых «Страх и ненависть в event bus»

32
СТРАХ И НЕНАВИСТЬ В EVENT-BUS Олег Годовых

Upload: devday

Post on 14-Jun-2015

364 views

Category:

Software


3 download

DESCRIPTION

У нас было 500 страниц спецификаций, 40000 строк кода, 2 офиса, полдюжины разработчиков, а также целое множество андроидов всех сортов и расцветок. Не то, чтобы это был необходимый запас для приложения крупной торговой сети. Но если начал собирать софт, становится трудно остановиться. Единственное, что вызвало у меня опасение — это сетевая библиотека. Нет ничего более беспомощного, безответственного и испорченного, чем писать AsyncTask на каждый вызов. Я знал, что рано или поздно мы перейдём на Event Bus.

TRANSCRIPT

Page 1: Олег Годовых «Страх и ненависть в Event Bus»

СТРАХ И НЕНАВИСТЬ В EVENT-BUSОлег Годовых

Page 2: Олег Годовых «Страх и ненависть в Event Bus»
Page 3: Олег Годовых «Страх и ненависть в Event Bus»
Page 4: Олег Годовых «Страх и ненависть в Event Bus»

AT FIRST IT WAS LIKE THIS

Page 5: Олег Годовых «Страх и ненависть в Event Bus»

BUT THEN I UMLD…

Page 6: Олег Годовых «Страх и ненависть в Event Bus»

МАГАЗИНЧИК

• 500 страниц документации.

• В том числе 200 страниц описания API.

• Большое количество сложных use-cases.

• Разветвлённая логика и схема зависимостей.

Page 7: Олег Годовых «Страх и ненависть в Event Bus»

МАГАЗИНЧИК

• 4 человеко-года на каждую платформу (iOS, Android).

• 6 разработчиков в команде Android.

•Общий размер команды — до 27 человек.

•≈40000 строк кода.

Page 8: Олег Годовых «Страх и ненависть в Event Bus»

ОСОБЕННОСТИ

• Android 4.0+

•Одно действие — один запрос.

• Настройками кэширования занимается сервер.

• Ссылки для последующих запросов приходят с сервера.

Page 9: Олег Годовых «Страх и ненависть в Event Bus»

ПРОБЛЕМЫ

•Много разнородных запросов (около 100 в последней версии API).

• Компонент-инициатор != компонент-получатель.

• Инициаторов может быть несколько.

• Получателей тоже!

Page 10: Олег Годовых «Страх и ненависть в Event Bus»

КАК ДЕЛАТЬ ЗАПРОСЫ

• In-place AsyncTask.

• AQuery и иже с ними.

• Сервисы, контент-провайдеры, броадкасты…

• Реактивное программирование.

Page 11: Олег Годовых «Страх и ненависть в Event Bus»

ЧЕМ ПЛОХИ ASYNCTASK

•Очень сложно переиспользовать.

•Очень много boilerplate-кода.

• Гроб, гроб, кладбище, утечка контекста.

requestDataTask = new AsyncTask<Void, Void, JSONObject>() { @Override protected JSONObject doInBackground(Void... params) { final String requestResult = apiService.getData(); final JSONObject json = JsonUtils.parse(requestResult); lruCache.cacheJson(json); return json; } };

Page 12: Олег Годовых «Страх и ненависть в Event Bus»

AsyncTask

Понятность +

Удобство -1

Переиспользование —

Пацаны так делают? —

Page 13: Олег Годовых «Страх и ненависть в Event Bus»

ПОЧЕМУ НЕ КАТИТ AQUERY

• Слишком локальное применение.

•Опять же — много повторяющегося кода.

• Сложно прикручивать другие библиотеки.

aq.ajax("http://example.com", String.class, CACHE_TIME, new AjaxCallback<String>() { @Override public void callback(String url, String object, AjaxStatus status) { Type listType = new TypeToken<List<User>>() {}.getType(); List<User> list = new Gson().fromJson(object, listType); listener.onResponse(list); } });

Page 14: Олег Годовых «Страх и ненависть в Event Bus»

AsyncTask AQuery

Понятность + +

Удобство -1 2

Переиспользование — —

Пацаны так делают? — ≈

Page 15: Олег Годовых «Страх и ненависть в Event Bus»

ДАВАЙТЕ ПОСЛУШАЕМ GOOGLE IO

• Храним в БД

• Скачиваем сервисом

•Отдаём через ContentProvider

Page 16: Олег Годовых «Страх и ненависть в Event Bus»

ЧТО НЕ ТАК С CP

• Дважды конструируем объект (при разборе результата запроса и при десериализации из БД).

• Нужно инвалидировать данные. Зачем нам SQL?

Нам SQL не нужен

Page 17: Олег Годовых «Страх и ненависть в Event Bus»

AsyncTask AQuery Service + CP

Понятность + + ≈

Удобство -1 3 2

Переиспользование — — +

Не делаем лишнего — + —

Пацаны так делают? — ≈ +

Page 18: Олег Годовых «Страх и ненависть в Event Bus»

ГОТОВЫЙ ФРЕЙМВОРК

• Сильная связность

• Есть явная «точка сопряжения»

final Subscription subscription = createApiRequestObservable() //создали Observable с запросом .timeout(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS) //поставили таймаут .retry(RETRY_COUNT_FOR_REQUEST) //поставили кол-во повторов .onErrorResumeNext(createRequestErrorHandler()) // назначили обработчик ошибки .map(createJsonMapOperator()) //модифицировали Observable, чтобы получать JSONObject .onErrorReturn(createJsonErrorHandler()) //возвращаем в случае ошибки то, что ожидаем .doOnNext(createCacheOperation()); //кэшируем JSONObject .subscribeOn(Schedulers.newThread()) //трудоёмкое в отдельном потоке .observeOn(AndroidSchedulers.mainThread()) // обработка результата - в main thread .subscribe(subscriber); //обработчик результата

Page 19: Олег Годовых «Страх и ненависть в Event Bus»

AsyncTask AQuery Service + CP RxJava

Понятность + + ≈ ≈

Удобство -1 3 2 4

Переиспользование — — + +

Не делаем лишнего — + — ≈

Пацаны так делают? — ≈ + +

Page 20: Олег Годовых «Страх и ненависть в Event Bus»
Page 21: Олег Годовых «Страх и ненависть в Event Bus»

VOLLEY

• Несколько уровней кэширования.

• Абстрагируемся от HTTP насколько возможно.

•Очень гибкое управление очередью.

Page 22: Олег Годовых «Страх и ненависть в Event Bus»

ТИПИЧНАЯ СХЕМА ДЕЙСТВИЙ

• Создаём по действию новый запрос

• Добавляем его в очередь

• Забываем

•…

•ОТВЕТ СЕРВЕРА!!!

Page 23: Олег Годовых «Страх и ненависть в Event Bus»

ОТВЕТ СЕРВЕРА

• Распространяется через event bus.

• Все желающие его получают.

• Не страшно, если никому он уже не нужен.

Page 24: Олег Годовых «Страх и ненависть в Event Bus»

НИ КАПЕЛЬКИ НЕ СТРАШНО

Page 25: Олег Годовых «Страх и ненависть в Event Bus»

OTTO

• Подписка на события через аннотации.

• Подписались на то, что не приходит — не страшно.

• Приходит то, на что не подписывались — не беда!

public class BaseFragment extends Fragment { protected Bus bus = AzbukaApplication.getBus();

@Override public void onResume() { super.onResume(); bus.register(this); NetworkFacade.cancelOldRequests(this); }

@Override public void onPause() { super.onPause(); bus.unregister(this); NetworkFacade.markToCancel(this); }

Page 26: Олег Годовых «Страх и ненависть в Event Bus»

ЧЕМ МАНИПУЛИРУЕМ

• BaseRequest — инкапсулирует парсинг и рассылку сообщений

• BaseResponse — bean + id

public static class PutUserNickRequest extends BaseRequest<PutUserNickResponse, NewUserNick, PutUserNickError> { /** * API v0.36 p. 74, Change user password (4.10.4) * @param url - POST /user/<user-id>/phone * @param nick - typed nick */ public PutUserNickRequest(String url, String nick) { super(Method.PUT, url, PutUserNickResponse.class, PutUserNickError.class, new NewUserNick(nick)); } }

Page 27: Олег Годовых «Страх и ненависть в Event Bus»

ПОДПИСКА

• Нам не важно, кто отправил.

• Нам нужно лишь уметь обрабатывать данный тип ответа.

• Кто на экране — тот и главный!

@Subscribepublic void onResponse(BasketRequest.BasketContentResponse basketContentResponse) { loadWelcome();}

@Subscribepublic void onError(OtherError error) { if (TextUtils.isEmpty(error.getMessage())) { Toast.makeText(getActivity(), getString(R.string.failed), Toast.LENGTH_LONG).show(); } else { Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show(); }}

Page 28: Олег Годовых «Страх и ненависть в Event Bus»
Page 29: Олег Годовых «Страх и ненависть в Event Bus»

LET IT CRASH

• Есть одна точка получения данных об ошибке.

• Есть один общий workflow обработки ошибки.

• При особой надобности — можем подписаться на ошибки конкретного класса.

Page 30: Олег Годовых «Страх и ненависть в Event Bus»

ПОДВОДНЫЕ КАМНИ

• Event bus хорош, когда всё в нём хорошо.

•Отладка — снежный ком.

Page 31: Олег Годовых «Страх и ненависть в Event Bus»

ПЛЮСЫ И ПЛЮШКИ

• Лёгкая проверка работоспособности back-end.

• Часть приложения сделана как конечный автомат на основе Event Bus.

• Архитектура «непривязанных запросов» отлично ложится почти на любое приложение.

Page 32: Олег Годовых «Страх и ненависть в Event Bus»

СПАСИБО ЗА ВНИМАНИЕ

А ещё я в твиттере есть, меня @0leGG зовут, там 0 как нолик, а не как Олежка.