Хабрахабр

«Для нас уже нет смысла использовать Retrofit»: об Android-разработке в Сбербанк Онлайн

Очевидно, что каждый такой случай — уникальная история со своей спецификой, так что было бы интересно поговорить с разработчиками. У скольки российских приложений в Google Play написано «50 000 000+ установок»? А когда у такого приложения ещё и оценка 4,6, это усиливает интерес.

Весной, когда Сбербанк-Технологии участвовали в нашей конференции Mobius, он выступил там с докладом, а теперь мы решили расспросить Владимира об особенностях его работы.
Владимир Теблоев — один из людей, работающих над Android-приложением Сбербанк Онлайн.

— Для начала расскажите, чем именно занимаетесь?

Сервис доступен всем пользователям приложения — сейчас это 37 миллионов человек. — Я в приложении Сбербанк Онлайн занимаюсь сервисом «Диалоги», позволяющим пользователям переводить деньги в один клик и видеть всю историю переводов как на ладони.

А позже, когда в рамках перехода к agile стали за отдельными модулями приложения закреплять разные команды, одной из первых стала как раз команда «Диалогов», и с тех пор я в ней. Работаю в СберТехе с лета 2016-го — тогда в рамках приложения ещё не было разделения на отдельные команды.

Но в такой крупной компании, вероятно, есть ещё и внутренняя мобильная разработка? — У всех слова «Сбербанк» и «мобильная разработка» ассоциируются со Сбербанк Онлайн. Она чем-то отличается от внешней?

Я к ним отношения не имею, но знаю, что там активно используется React Native. — Да, приложения для внутреннего использования тоже есть. У внутренней разработки свои требования: нет строгого дизайн-ревью и навороченной анимации, разработка протекает быстрее с применением кроссплатформенного решения.

Хотя в том, что Сбербанк Онлайн сможет активно использовать кроссплатформенную разработку, я сомневаюсь. Когда экспертиза подрастёт, можно будет её и на «боевом» приложении применить. Там много сложностей, а когда у тебя десятки миллионов пользователей, даже редкая проблема может задеть очень многих людей.

Приходится ли сталкиваться с какими-то экзотическими проблемами, которые у приложений поменьше могут проходить под радаром? — А как это «даже редкая проблема задевает многих» сказывается на работе?

На одной кастомной, но распространённой прошивке сильно «выстрелило», и нам пришлось долго разбираться. — Порой возникают проблемы на каких-нибудь «особенных» девайсах. Оказалось, что проблема в драйвере материнской платы самого устройства — он пытался эмулировать библиотеки под ARMv5, хотя в проекте были только под ARMv7.

Если там что-то резко возрастает — тут же останавливаем раскатку и делаем хотфикс. Когда пользователей много и цена ошибки высока, это приводит к тому, что раскатывать нужно всё «по чуть-чуть», внимательно следя за отчётами. Помимо раскатки «на заданный процент пользователей», мы ещё и географически выкатываем всё по частям: в Сбербанке есть понятие «территориальный банк», и фичи могут постепенно раскатываться по регионам.

Какое у вас сейчас значение MinSdkVersion? — Пока какой-нибудь хипстерский стартап может ставить высокий MinSdkVersion и говорить «все остальные не наша аудитория», у вас другая ситуация, вы не можете махать рукой на людей.

Мы смотрим на количество клиентов с определенным SDK, и можем поднять версию, если оно становится меньше 5%. — Сейчас 16, и мы подняли его буквально в прошлом году с 14. 4 KitKat, порядка 16% — нам надо их поддерживать. Пока что у нас много пользователей на Android 4.

— А есть ли что-то из новых версий, на что вы сейчас засматриваетесь и думаете «Как только MinSdkVersion повысим, так сразу вот это используем?»

0, чтобы в полной мере использовать такие нововведения, как, например, анимация переходов, которая будет работать адекватно и везде. — Конечно, хотелось бы поднять наш минимальный API до Android 5. В целом анимации прорабатываются нашими дизайнерами, то есть это можно реализовывать вручную. Но, в принципе, это не касается написания функциональности, бизнес-логики, поэтому это не критично. Так что данный вопрос не критичен, он касается комфорта, «душевного спокойствия» разработчика.

Он по-разному работает в разных версиях Android, поэтому мы реализовываем две версии кода, для устройств Android «до 4. Есть некоторые случаи, в которых у нас проверяется версия, например, SSL pinning. 4». 4» и «от 4.

Конечно, хотелось бы «просто разрабатывать под Android P и ни о чём не думать» — но это всегда так, от этого никуда не денешься.

Очевидно, что для банка очень важны вопросы безопасности. — К упомянутому SSL pinning. А как это сказывается на вас, чем ваша работа отличается от работы над не-банковским приложением?

Какая-либо утечка — это огромные риски. — Отличается очень строгим подходом к личным данным пользователя. Если есть замечания, работа над ними переходит той команде, которая отвечает за функциональность с обнаруженной уязвимостью. У нас есть отдел безопасности, который перед каждым релизом тестирует наше приложение.

Если какие-то косяки и обнаружатся, они могут всплыть на 4pda.ru или аналогичном ресурсе. В маленьких компаниях, думаю, зачастую нет отдела безопасности, который будет пентестить приложение.

Некоторые пользователи недовольны его наличием, но внедрение антивируса дало нам очень заметное снижение мошенничества. Также к безопасности относится то, что у нас в приложении используется антивирус. Например, в нашем SMS-банке, где можно смской написать «перевести на X карту Y сумму», с антивирусом уровень фрода в данном направлении удалось снизить до минимума.

Что у Сбербанк Онлайн для рутованных устройств запрещено? — Ещё из соображений безопасности банки ограничивают функциональность в случае с рутованными смартфонами.

Сейчас всем пользователям Сбербанк Онлайн на Android доступен полный функционал. — В июне мы отказались от ограниченного функционала для владельцев устройств с root-правами. При этом защита остается на прежнем уровне благодаря системе фрод-мониторинга.

— А приходилось во имя безопасности ограничивать в чём-то не пользователей, а самих себя как разработчиков, отказываясь от того, что иначе использовали бы?

Наш отдел безопасности указал на данную уязвимость, чреватую кибератакой на банк и на риски взлома кода, так как API торчит наружу. — Когда в 2015-м мы хотели внедрить Retrofit, у него были проблемы с обфускацией, он криво работал со стандартным обфускатором. Насколько мне известно, сейчас там проблемы со стандартным обфускатором уже поправлены. Тогда мы отказались от Retrofit и до сих пор его не используем. Смысла менять его на Retrofit уже нет. Но мы с тех пор написали собственный HTTP-клиент, он работает и всех удовлетворяет, для него уже написаны много обёрток для разных команд, работающих с разными серверами.

— Неизбежный вопрос: что у вас с Kotlin?

Сложность в том, что над приложением работает сразу множество Android-разработчиков разного уровня, кто-то отлично знает Kotlin, кто-то нет. — Мы идём в его сторону, но неторопливо. Если мы все завтра резко начнём писать на Kotlin, то люди «порвутся» на реквестах. В целом непреодолимых препятствий для внедрения нет, однако сейчас у нас дефицит ревьюеров для отсматривания Kotlin-кода. Кроме того, в случае с Kotlin возникают проблемы со статическим анализатором кода, который используется в нашем пайплайне.

Так что Kotlin внедряется маленькими шажками: например, мы пишем на Kotlin тесты и используем data classes (так мы экономим время, чтобы не писать тесты на геттеры, сеттеры, equals(), hashCode() и прочее).

И параллельно хотим поднимать уровень знания Kotlin в компании: например, с помощью митапов. Сейчас это потихоньку обкатывается, а на следующем этапе хотим написать свой DSL для тестирования на Kotlin.

И поэтому интересно: а насколько вам оказываются полезны чужие решения, лазаете ли в код опенсорсных мессенджеров? — В случае с «Диалогами» вы занимаетесь мессенджингом, но не прямым аналогом WhatsApp.

У нас появился вопрос, как сделать панель с ними, и в опенсорсе увидели вариант, где всё легко решается попапом над клавиатурой. — Полезно было, когда мы захотели добавлять смайлики. Тогда и по высоте всё сходится, и бесшовно для пользователя получается.

Например, на Telegram лучше вообще не смотреть, потому что из-за огромного размера классов в исходниках их Android-приложения непросто разобраться. Но вообще смотреть на чужие решения — не всегда хорошо, эффективнее формировать собственные, учитывая опыт других. Пытаемся идти по своему пути, тем более, что взаимодействие с сервером бывает разное: в том же Telegram это MTProto, у нас — обычные WebSockets.

— Я ленивый интервьюер, поэтому решил просто взять список вещей, с которыми вы связаны по работе, и про каждый пункт спросить «расскажите, как именно обстоят дела с этим».

Про то, что приложение разделено на модули, уже говорили — а что ещё можете сказать про архитектуру? Первый пункт: вы занимаетесь «архитектурой модулей приложения».

— Она у нас развивается итерационно, ведётся версионность, сейчас мы дошли уже до 17-й версии.

Согласовали, кто за что отвечает (presentation, domain, data-слой), какие сущности и где должны использоваться, где должны быть конвертеры — в общем, расписали все архитектурные вопросы и внедрили. На 16-й внедрили Clean Architecture.

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

В презентационном слое мы ничем не ограничены. Для презентационного слоя мы выбрали стандартом MVP, но некоторые команды у нас используют MVVM. Например, мы перепилили наш чат на MVI — точнее, на свою интересную реализацию MVI, которая кардинально отличается от того, что написал разработчик Mosby.

Если пользоваться строгими определениями, то теперь наша архитектура получилась гексагональной, от Clean мы «форкнулись». Потом мы перешли на 17-ю версию архитектуры и внедрили RxJava, что повлекло за собой архитектурные изменения. Сейчас работаем над этим. Но они схожи тем, что обе работают по принципам SOLID, поэтому одно в другое довольно плавно перетекает.

Проект большой, в нём используется annotation processing, и при внесении изменений в модули «нижнего уровня» время сборки оказывается большим. В будущих версиях архитектуры хотим отказаться от фреймворка Moxy, использованного для реализации MVP, потому что он вызывает некоторые сложности. А мы стремимся облегчить жизнь наших разработчиков.

Насколько остро стоит этот вопрос, приходится ли ради пользователей со старыми устройствами постоянно о нём думать? — Вторым пунктом идёт «оптимизация работы и потребления памяти».

Необходимость заниматься этим, скорее, возникает по надобности одной из команд. — Этот вопрос находится в фокусе платформенных команд, они разрабатывают инструменты, которыми пользуются фичевые команды. Тогда пришлось закатать рукава, начать с профилировщика, просмотреть, где в приложении узкие места, разобраться с причинами их возникновения. Например, у нас в команде «Диалогов» на ранних этапах разработки чат работал очень медленно.

На этот год запланирована оптимизация графа зависимости в Dagger, чтобы ускорить холодный старт приложения. В отношении оптимизации, например, мы отказались от PNG и постепенно вычищаем их из проекта, чтобы использовать только вектор.

— Перейдём к вопросам тестирования: как оно у вас происходит?

— Я могу рассказать только про нашу команду, в других этот процесс может строиться иначе.

Впоследствии ему стало скучно просто тестировать. У нас в команде изначально был один тестировщик. Мы показали ему, как пишутся тесты на БД, на сущности, на парсинг — и таким образом он разгрузил нас, снял с нас часть работы. И он начал просить нас помочь разобраться с написанием unit-тестов. Это хорошо: и ему интересно, и нам.

Первое время проработкой UI-тестов занимались я и мой напарник, а позже к нам подключился департамент качества — наши тестировщики, которые в прошлом тестировали бэкэнд. Со временем мы пришли к тому, что нужно автоматизировать регресс, нужно писать UI-тесты. Мы вместе сели и рассмотрели решения, которые есть: Appium, Espresso, Selenium. Они знают Java, а сейчас их подключили на наш проект для автоматизации всего регресса.

Чтобы облегчить тестирование, разработали свой фреймворк, что-то наподобие Kakao. Остановились на Espresso и стали вместе разрабатывать подходы. Мы занялись этой работой в начале 2017 года, а сейчас мы имеем большой фреймворк, и большинство тестов собираются как конструктор, потому что написано много матчеров и экшенов для различных ситуаций.

Но, конечно, всё не автоматизируешь, и некоторые кейсы всё равно надо проверять вручную. Сейчас наши тестировщики активно просят нас научить их писать UI-тесты, потому что проще написать один раз тест, чем на пяти девайсах «протыкивать» одни и те же действия.

На одной из них мы пришли к мнению, что разработчики должны проводить хотя бы альфа-тестирование после того, как написали фичу. Что касается разработчиков, то в нашей команде каждые две недели проводится ретроспектива. Таким образом, разработчики тоже подключились к тестированию. Чтобы не вылезали какие-то совсем базовые баги вида «приложение падает при старте». При обнаружении бага разработчики отключаются от регресса, быстро фиксят, и по новой. Когда у нас готовится крупный релиз и нужно быстро протестировать фичу, все садятся на регресс и вместе проходят тесты по регрессу.

Тут у вас есть какая-то специфика, или «как у всех»? — Следующий пункт: код-ревью.

Когда мобильных разработчиков в компании десять, то всё могут ревьюить два-три человека. — Есть специфика, вызванная количеством разработчиков. Мы разработали «матрицу ревьюера». А как ревьюить код сотни человек? Взяли этих людей и разделили между ними все команды. Отобрали 20-30 человек, про которых мы точно знаем, что они могут хорошо проревьюить, оставить фидбэк и разрулить спорные моменты в комментариях.

Это сделано для того, чтобы у всех ревьюеров была одинаковая нагрузка. Почему матрица? У нас в команде требуется как минимум три аппрува. Как проходит ревью? Второй — от кого-то извне, от команды, которая не занимается данной функциональностью. Первый — от кого-то из команды. В нашем случае есть несколько смежных команд, и они все смотрят наш код. И третий аппрув — от кого-то из смежной команды. Таким образом у нас проходит код-ревью. Ну и, соответственно, должны собираться все билды: unit-тесты и UI-тесты должны пройти без проблем.

Насколько систематически он происходит: именно запланированными задачами, или «понадобилось внести изменения в старый код — заодно порефакторили»? — Следующий пункт — рефакторинг легаси-кода.

Но запланированный рефакторинг тоже есть. — Вообще у нас действует своеобразный «принцип бойскаута»: если тронул что-то старое — будь добр сделать как надо, ты теперь соавтор. Контактную книгу вынесли, почистили, переписали всю базу данных на Room, вынесли в отдельный модуль. Например, для «Диалогов» понадобился рефакторинг двух направлений: контактной книги, которую мы используем, и переводов. Надо сказать, выпиливание этого оказалось неприятной задачей, потому что завязок на него было много. А платежи у нас были написаны давно с помощью RoboSpice, если вы такое ещё помните, и это делало нам больно. И нужно было тонко вычищать, чтобы не сломать всем остальным функциональность.

Как выглядит обучение внутри компании? — Ещё в «Сбертехе» вы причастны к обучению программистов.

Сейчас мы уже определили круг тем по Java и Android. — С сентября планируется проводить такую программу, как переобучение внутренних сотрудников. Для них будет организована такая школа, где будет целенаправленное изучение, по расписанию и с лекциями. Например, у нас есть джаваскриптеры, джависты и аналитики, которые хотят переобучиться на Android.

Выбор тем для них не такой, как на конференциях, где обязательно нужно что-то новое и хайповое. А сейчас у нас регулярно проходят митапы. Из недавнего — один из наших разработчиков рассказывал о векторной графике. Например, если мы знаем, что у разработчиков с чем-то есть проблемы, то об этом важно рассказать. Рассказывали и про Room, и про Java concurrency, с которой у многих разработчиков проблемы, и про Dagger 2. Не просто о конкретной библиотеке, которая на Android красиво рисует векторы, а начал с того, как вообще работает векторная графика, и дальше шёл в частное.

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

— Собеседования: у вас они проходят «как у всех», или есть специфика?

По моему опыту, на рынке можно выделить три часто встречающихся подхода. — Раньше я думал, что «как у всех», но в итоге оказывается, что они всё же немного особенные. Например, я пришёл в компанию на позицию Android-разработчика, а меня рассматривают как человека, который должен отлично знать алгоритмы и синхронизацию в Java, и при этом никак не оценивают то, что я делаю супербиблиотеки. Первый — спрашивают по трём-четырём темам и оценивают исключительно по ним. Второй — когда собеседуют спустя рукава, почти что разговор за жизнь в течение 30-40 минут. Это может быть обусловлено тем, что компании нужен человек, который прекрасно должен знать какую-то узкую часть фреймворка или языка. Третий — когда на собеседовании рассказывают о проблемах компании и пытаются на месте получить какое-либо решение. Тут, скорее, дело в компетенциях и опыте интервьюера. На мой взгляд, такие подходы встречаются примерно в половине случаев. Минус этого подхода в том, что решение может не совпадать с мнением того, кто этот вопрос задаёт.

Методично вопрос за вопросом проходим по всем темам. Что касается нас, мы проработали методику рассмотрения кандидата по четырём широким направлениям: ООП, OOD (Object Oriented Design, архитектура), Java Core и Android SDK. Образно это выглядит как дерево: у нас есть корень, откуда мы заходим в каждую тему, и можем в глубину пройти на пять-семь шагов. Если кандидат в целом уверенно отвечает по теме, постепенно начинаем уходить вглубь, задавать более специфические вопросы. Если собеседование проходит быстро, то начинаем спрашивать по библиотекам, например, Dagger 2, RxJava. Потом кандидат оценивается в совокупности по всем пройденным вопросам. Таким образом, кандидат у нас оценивается в целом. Если и на это времени хватило, тогда и по Kotlin. Это значит, что за определённый срок ему следует эту тему подтянуть. Если человек не разбирается в какой-то одной теме, но хорошо знает другую, это не значит, что он плохой программист.

Тут хочется попросить конкретный пример какой-нибудь технологии, которую ревьюили. — Ещё в числе ваших рабочих задач есть «исследование и ревью новых технологий».

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

Внедрять её для того, чтобы у нас было много способов вхождения в сеть — плохая практика. Из неудачных примеров рассматривали Retrofit, о котором я уже говорил: хорошая библиотека, которая решает свои задачи, но её время для нашего проекта прошло.

Поэтому от неё отказались, поскольку если уж и «тащить» библиотеку, то только ту, которая всем подойдёт. Также рассматривали библиотеку TinyMachine для реализации стейт-машины — библиотека простая, не расширяемая, то есть одну команду она удовлетворяет, но для других не подходит. В итоге мы приняли решение написать собственную стейт-машину, благо, это не какой-то rocket science, который тяжело реализовать.

В вашем случае, когда разработчиков много и невозможно держать всё в голове, без аккуратного документирования вообще никуда? — И последнее: ведение документации.

Первый вид документации — это Java-доки. — Да. Сейчас разработчики уже понимают, что каждый публичный метод, каждый класс, каждый конструктор — всё должно быть описано Java-доками. У нас есть локальный мем «проверка Прилуцкого»: нет Java-дока — пулл-реквест не проходит («Прилуцкого» — в честь одного из лидеров в команде Android-разработчиков: на всех реквестах он так часто писал о том, что должна быть описана документация к коду, и без этого код не пройдет в общую ветку, что родился такой мем). Чтобы было понятно, на что этот тест написан, чтобы не возникало, например, вопросов «Что это за payment? Весь код должен быть покрыт доками, даже тесты. Что за paymentTest?». Это payment из мессенджера или payment из платежей?

Когда я сюда приходил, гайдлайны material design у нас были описаны в облаке, и была пара-тройка статей о том, как мы работаем. Кроме того, у нас есть документация в Confluence. Например, нам нужно вставить сертификаты для доступа к репозиторию, и тот, кто это сделал, пишет статью, чтобы потом в чате не писали миллион раз, что делать в случае неработающего сертификата. Сейчас же все глобальные вещи, затрагивающие всех, обязательно описываются в Confluence. Самый простой пример: как располагать методы в классе, чтобы все было по стандарту. Ещё пример: было принято решение о внедрении RxJava и в Confluence описываются best practices — как хорошо это делать, как не нужно это делать, и ссылка на образец.

Сейчас наш Confluence вырос уже до 200 статей по разным вопросам. Эти статьи постепенно, но регулярно пишутся. Они изучают Confluence, получают представление о внутренней кухне разработки, в случае же возникновения вопросов могут самостоятельно разобраться и принять решение, не всегда привлекая к этому своего ментора. Такой инструмент помогает в том числе новопришедшим разработчикам.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть