Pull to refresh

Comments 68

Привет, друзья :) Первый мой вброс-вопрос будет про модульную архитектуру приложения, насколько знаю вы в эту сторону, как минимум смотрели.

Отсюда следующие вопросы:
1. По какому принципу выделяете модули?
2. Как с этим всем делом дружите Dagger(особенно, если речь идет о фича-модулях)?
3. Какие преимущества вы от этого получили/ожидаете получить? Было бы круто, например, увидеть разницу в скорости сборок.
1. Стараемся выделять по принципу микросервисов. Каждый модуль в идеале должен быть самодостаточным: содержать все необходимое в себе и решать некую «бизнес-задачу». К сожалению, этого достичь невозможно, и приходится выносить переиспользуемый код: работа с сетью и базой.
2. Используем единый верхнеуровневый dagger-компонент, в который добавляем субкомпоненты с помощью Subcomponent Builder. Gradle-модули содержат в себе субкомпоненты и модули dagger.
3. Хотим получить большую независимость в поддержке кода. Как правило, gradle-модуль поддерживает небольше число команд (в идеале одна), код более независим.
Ускорение сборки хотим получить за счет кэширования и параллелизации сборки различных модулей. Нагляднее всего это можно посмотреть в отчете от gradle build scan. Мониторим текущее состояние, измеряя время сборки в разных сценариях с gradle-profiler. Проверяем гипотезы в том числе на тестовом проекте, смотрим различные конфигурации модулей.
Вот проблемы, с которыми мы столкнулись.
— Android Studio и gradle требуют больше памяти.
— Sync в IDE идет дольше.
— Ошибки при кэшировании модулей, особенно имеющих annotation processing (kapt).
— Повышение порога входа. Нужно понимать какие модули подключать.
2. Используем единый верхнеуровневый dagger-компонент, в который добавляем субкомпоненты с помощью Subcomponent Builder. Gradle-модули содержат в себе субкомпоненты и модули dagger.


2.A. Сколько строк занимает сгенерированный код для верхнеуровнего компонента?
2.B. Как вы планируете решать проблему необходимости регенерации этого компонента при любом изменении в сабкомпонентах?
2.C. Получается, что gradle-модуль корневой знает о всех дочерних модулях?
2a. Не могу сказать.
2b. По-видимому, полностью решить можно только отказом от dagger. Практически весь код из корневого модуля вынесен, поэтому компиляция будет быстрой, результат сборки модулей закэширован.
2c. Обо всех фича-модулях.
Всем, привет!
При разработке нового приложения, какой сейчас стек технологий/библиотек выбрали бы?

Новое приложение я бы писал на привычном Kotlin, для сетевого взаимодействия выбрал бы OkHttp в паре с Retrofit, RxJava2 для поддержки reactive streams и обязательно посмотрел бы в сторону Architecture Components. MVP же заменил бы однонаправленной архитектурой (Redux, MVI).

1. Чтобы выбрали для локального хранилища?
2. Почему REST, а не GraphQL?
  1. Сильно зависит от приложения и структуры данных в нем. Если бы выбор пал на реляционную БД, то в качестве ORM использовал бы Room.
  2. GraphQL выглядит более интересным решением для фронтенда, но требует смены парадигмы в клиент серверном взаимодействии.
Я уже устал задавать этот вопрос, но все-таки задам его тут, хотя он и не совсем по теме.

Когда вы перестанете использовать темные паттерны в интерфейсах?
Что делает дизайнер в посте для программистов?
Здравствуйте, хотелось бы в деталях узнать, как в Avito организован CI для Android-приложений, в частноти:
Кажется, что недописали вопрос, ждём его полную версию :)
Набор сервисов у нас довольно типичный: JIRA/TeamCity/BitbucketServer

Как только происходит открытие PullRequest инициируется параллельная серия проверок (скриншот) и ревью кода. Как только все это окрасится в зеленый цвет — происходит мердж в ветку синхронизации (develop)



Все task'и на CI — это скрипты (bash / python), лежащие в репозитории с проектом.
Скрипты запускают команды в docker контейнерах. Эмуляторы для instrumentation-тестов также живут в контейнерах.

Выполняется все это в kubernetes кластере по соседству со всем остальным CI Avito.

Для того чтобы избежать проблем со сломанным кодом после мерджа мы предварительно подмердживаем первым шагом код из develop.
Если за время проверок кто-то успел смерджится — проверки стартуют заново.
Реализовано это при помощи самописного плагина для Bitbucket Server, он стартует билды в TeamCity, отменяет неактуальные, а также может автоматически замерджить твой PR при достижении нужных кондиций (если ты его об этом попросишь)

Кажется, у меня встал.
Простите.

Да, случайно не ту комбинацию нажал :)
Интересуют два вопроса:
1. Для тестов запускается эмулятор внутри контейнера? Если да — какие библиотеки/инструментарий применяете для надежного контроля его работы? По моим наблюдениям, avd-эмулятор даже обычного нексуса отличается некоторой нестабильностью.
2. Используете ли для инструментальных тестов большую сетку из различных комбинаций устройств/sdk для проверки стабильности или же прогоняете тесты на небольшом списке девайсов?
3. Какие библиотеки/плагины gradle используете для автоматической подписи и доставки приложений в Play Market?
Как у вас реализована обработка ошибок? Текст ошибок возвращает сервер или все на клиенте?

Мы стремимся в backend-driven UI, и абсолютное большинство текстов в приложении нам присылает сервер. На руку здесь нам играет то, что наше приложение поддерживает только русский язык и не надо заморачиваться с локализацией.

Привет, вопросы из насущного:)
1) Используете ли в своих приложениях чистую архитектуру, и если да, то как относитесь к хранению состояния в интеракторах (Например интерактор доавторизационной зоны с функционалом регистрации\авторизации, который на разных шагах сохраняет какие-то данные и использует их при последущих запросах)? Если негативно, то как выходите из подобных ситуаций?
2) MVP или MVVM? И можно ли контекст тащить в презентер?

1) Мы не используем “чистую архитектуру” в ее первозданном виде, скорее некую адаптацию. Интерактор сохраняет свое состояние только для кеширования результатов части запросов. В ситуации описанной вами скорее всего за это будет отвечать верхнеуровневый презентер.


2) Чаще всего в проекте используется MVP. Пристально смотрим в сторону однонаправленных архитектур и экспериментируем с ними.
Мы стараемся максимально изолировать презентеры и интеракторы от взаимодействия с android-классами. Это облегчает юнит-тестирование: тесты можно запускать без Robolectric.

И, если позволите, еще один вопрос. Он вытекает из моего первого вопроса, но уже с организационной точки зрения.

У вас работает несколько(множество) независимых команд, которые ведует свои модули, но работают при этом в одном проекте. Понятно, что тут все не так просто, и существует много пересечений, но для простоты рассмотрим идеальный вариант.

Позволяете ли вы писать командам «кто во что горазд», либо спускаете «сверху» требования/гайдлайны. В первом случае, будет высокая энтропия(множество разных подходов в одном проекте, библиотеки, которые делают одно и то же, но немного по-разному, etc.), но при этом, хоть и спорно, кодовая база будет эволюционировать и инженеры будут рады, так как у них есть возможность пробовать новое. Во втором случае, обратная ситуация, проект будет иметь более или менее стройную архитектуру, но будет существовать очень много решений в статусе-кво со всеми вытекающими.

Иными словами, как вы балансируете энтропию и стагнацию в большом проекте с множеством независимых команд?
Выстраивать вертикаль нецелесообразно: команды были организованы как независимые с точки зрения бизнеса, чтобы иметь широкую свободу действий. Фактор ограничения — технологический. Дорого держать бесчисленное число фреймворков в угоду удобству команд. Это влияет на пользователей — рост размера приложения, потенциальная нестабильность различных частей приложения, рост потребления памяти, CPU. Стараемся достигать технических компромиссов как можно раньше на уровне android community по образцу техрадара. Правильным решением видим бюджетирование ресурсов. Для этого нужен широкий мониторинг. Сейчас мы в начале этого пути.
  1. Пуш уведомления показываются "как есть" (локадизация текста), или обрабатываются на клиенте?


  2. Все ли разработчики знают и делают все части приложения, или каждый отвечает за определенный сделаный им функционал и не лезет не в свое?
1. Текст (title и message), а также дополнительные параметры, влияющие на отображение, приходят с сервера. Так как Avito полностью на русском языке, локализация не требуется.
Таким образом, клиент показывает уведомления как есть, логика по отображению на стороне клиента минимальна.

2. В основном разработчики сфокусированы на тех участках кода, которые отвечают целям команды. Получается такой негласный Code Ownership. Чтобы оптимизировать Code Review мы написали специальный плагин для определения оптимальных ревьюверов для измененных файлов.
Но в целом, во всем приложении используются похожие подходы, поэтому разобраться в другом участке кода достаточно просто.
Много еще пользователей на 4ых версиях? Планируете повышать minSdk?

По старым версиям:
Android 4.4 ~12%
Android 4.0-4.3 ~10%


Повышать minSdk (как бы этого ни хотелось :) ) пока не планируем, ориентируемся в этом вопросе на пользователей.

Близок ли тот день, когда нужно будет переписывать приложение с нуля? Если не близок, то как удаётся поддерживать стройную архитектуру, красивый код, радующий глаз каждого разработчика?

Очень надеемся, что такой день не наступит никогда :) Наше приложение достаточно большое.
Стараемся поддерживать архитектуру частыми рефакторингами, испытанием новых подходов, частыми обсуждениями. Также помогают дотошное Code Review и периодические ретроспективы.

Как и чем отслеживаете различные метрики в приложении? Имеются в виду не только краши, но и быстродействие, потребление траффика батареи и т.д..

И отслеживаете ли метрики в кодовой базе? Количество багов, smells code и т.д.
Для понимания общей картины используем Android vitals. Более специфичные метрики собираем в наши системы аналитики. Подробнее про их устройство в бекенде можно почитать здесь.
Каждая команда вправе выбирать для себя специфичные метрики кодовой базы. С нашей стороны планируем обеспечить инфраструктурную поддержку.
Продублирую, ибо написал не в корне.
1. Для тестов запускается эмулятор внутри контейнера? Если да — какие библиотеки/инструментарий применяете для надежного контроля его работы? По моим наблюдениям, avd-эмулятор даже обычного нексуса отличается некоторой нестабильностью.
2. Используете ли для инструментальных тестов большую сетку из различных комбинаций устройств/sdk для проверки стабильности или же прогоняете тесты на небольшом списке девайсов?
3. Какие библиотеки/плагины gradle используете для автоматической подписи и доставки приложений в Play Market?
  1. Эмуляторы достаточно стабильны уже! Удивительно сколько работы проделал google за последнее время в этом направлении.
    Чтобы избавиться от потенциальных проблем мы запускаем эмуляторы перед самим тестированием и роняем контейнеры после. Никакого специального тулинга для стабилизации здесь не требуется на данный момент. У нас есть программа на питоне, которая принимает yaml конфиг и стартует особым образом эмуляторы.
    конфиг выглядит например вот так:


    configuration:
    network: CI
    image: <local-registry>/android-emulator:<tag>
    environments:
    default:
      - 'animations_disabled'
      - 'spell_checker_disabled'
      - 'ime_hard_keyboard'
    
    functional-19:
        api: 19
        replicas: 10
    
    functional-22:
        api: 22
        replicas: 10
    
    functional-23:
        api: 23
        replicas: 10
    
    functional-24:
        api: 24
        replicas: 10

  2. в 2017ом мы в основном тестировали на FirebaseTestLab, но на наших масштабах это дорого, долго (очереди на популярные девайсы), нестабильно (черный ящик и непонятные сроки решения проблем). В конце года мы полностью переехали на свои мощности. Тестируем только на эмуляторах (см конфиг для регресса выше). API выбрали как 4 самые популярные у юзеров.


  3. На всякий случай не буду ничего подробно расписывать (sensitive инфа как никак), скажу только что вся процедура происходит автоматически.
Насколько медленно собирается проект?
Как улучшаете ситуацию?
Сценарии разные измеряем. Вот данные за год по ключевым:
image
clean :app:assembleDebug
— Инкрементальная сборка после изменений в коде

Оптимизации довольно очевидны:
— Разбиваем проект на более мелкие gradle-модули
— Экспериментируем с настройками gradle и компилятора
— Используем mirakle для разгрузки рабочих машин
Как построен процесс тестирования? и работа с отделом QA?

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

Мои коллеги немного поправили меня:


Тест-кейсы пишутся в процессе разработки на основании бизнес-требований или документации. Далее при получении фичи тестировщик проводит функциональное тестирование и некоторые виды нефункционального. Например, тестирование установки. тестирование на отказ и восстановление. В некоторых командах сразу же пишутся автотесты. И потом уже на перед релизом проводится регрессионое тестирование.
Многие пользователи нашей необъятной родины пользуются дешевыми китайскими безымянным смартфонами.
Каким образом вы профилируете на них производительность?
Какие курьезные баги связанные с ними у вас были?
Пока профилирование на устройствах не проводим, но у нас есть целый арсенал старых слабеньких устройств, на которых мы прогоняем регрессионное тестирование.
Буквально пару месяцев назад был случай, когда на планшете Lenovo TB3-710i все сетевые запросы падали с ошибкой или проходили не сразу, а websocket и вовсе отказывался подниматься. После проверки нескольких сборок обнаружилось, что проблема появилась после включения D8 (а он тогда был в beta). Может быть, проблема не в D8, но после его отключения все починилось.

К сожалению, пока никак. В целом мы стремимся к максимально тонкому клиенту и переносим максимум бизнес-логики на сторону сервера. То немногое, что остается на клиенте приходится писать два раза: для Android и для iOS. Очень внимательно следим за проектом Kotlin Native для шаринга кода между платформами.

Почему в подкасте Podlodka Android всегда стоит на втором плане? =)
Мы стараемся стать лучше! :) А вообще – обусловлено изначальным бэкграундом всех трех ведущих. Я, Стас и Глеб были iOS разработчиками (хотя я лет шесть назад начинал с андроида).
На каком фреймворке организовано автоматизированное тестирование?
У нас своя обертка (набор костылей), вокруг espresso + uiautomator2 одновременно. Я надеюсь что в феврале доберусь и опубликую ее на github.com/avito-tech.
Для запуска тестов мы используем внутренний форк github.com/gojuno/composer, правда переписанный уже до неузнаваемости. Там например реализован динамический шардинг и запуск всех тестов в отдельных instumentation процессах. Тоже подумаем над публикацией.
А можете немного подробнее рассказать про автоматизированное тестирование?
1. Кто занимается написанием новых тестов (функциональные тестировщики, или отдельная команда автоматизации, или разработчики)?
2. Кто занимается развитием и поддержкой инфраструктуры для автоматизации?
3. Если в других командах (iOS, Web) тоже есть автоматизация тестирования, стараетесь ли унифицировать (в рамках возможного) с ними наборы покрытых тестами тест-кейсов, или у каждой команды свои наборы сценариев?
4. Автотесты запускаются только на одном из этапов жизненного цикла релиза (например, при сборке свежего билда), или чаще?
5. Тестировщики запускают тесты самостоятельно, или они запускаются автоматом на определенных этапах жизни задачи/релиза?
1. Все занимаются. У меня нет под рукой статистики, но очень грубо треть всех автотестов под андроид написали функциональные тестеровщики, треть андроид разработчики, треть QA-dev, видел немного тестов от бекендеров и фронтендеров (изучали видимо как у нас оно устроено). Есть еще порядка шестисот компонентных UI тестов(больше изоляции чем у end-to-end), они почти все написаны разработчиками

2. У нас для этого отдельная команда, вот мы как раз с nnesterov оттуда. На нас релиз продукта и инфрастуктура вокруг этого.

3. Да, автоматизация тестрования есть почти во всех проектах. У каждой команды свой набор сценариев, хотя iOS и Android очевидно сильно пересекаются. Мы наоборот ушли от унификации всего автотестирования к решениям которые затачиваются под платформу.

4. Все возможные тесты запускаются на каждый пуш в рамках PullRequest. Работаем над оптимизацией при помощи Impact анализа на основе диффов: это уже работает в юнит тестах, в ближайшее время сделаем для UI

5. Все запускается автоматом, периодически появляются issue на ручной запуск, но я старательно резолвлю их с Won't Fix :), т.к. считаю что это плохая практика
Очень круто, спасибо большое за развернутый ответ =)

Так алё, давайте шлите пулл реквесты обратно в Composer)


а то понафоркают и сидют там со своими наработками!


Еще надо бы вам засинкаться с Juno по поводу стабильности эмуляторов на CI, каждый релиз эмуляторов/имеджей огромная боль. Можно в AndroidDev подкасте cc nekdenis, я бы тож пришел послушать/поговорить, хоть и последние полгода особо эмуляторы палкой не тыкаю, но могу рассказать про Firebase и Genymotion Cloud

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

Я не говорил что апдейт имаджей не проблема :) Однако если с образом все хорошо собралось, то нестабильности в дальнейшем не наблюдаем.
В подкаст зовите, с удовольствием поучаствую

До появления отчетов? Это ж было v0.1, едрить вы эрли-адоптеры…


в отдельных instumentation процессах

Это через Orchestrator? Если да, то на это есть таска https://github.com/gojuno/composer/issues/90


Про динамический шардинг тоже есть таска https://github.com/gojuno/composer/issues/66


Надо делать PRы, замержимся)

Когда использовать Actvity, а когда Fragment? Или лучше одно Actvity и много Fragment-ов?

Универсального решения по поводу количества Activity и Fragment нет. Все зависит от специфики приложений и желания разработчиков. Кому-то больше по душе использовать только Activity, кому-то очень нравится подход Single Activity Application. Наша команда находится где-то посередине. Логически связанные куски оформляются в виде отдельной Activity с несколькими фрагментами. Пример: флоу подачи объявления.

Распространяется ли механизм фичетоглов на продакшн версию приложения? Если да, через что реализован этот механизм? Используется ли поэтапная «раскатка» фичетоглов?
Реализация самописная. Выделяем разные типы фичатоглов. Многие из них используются на этапе разработки для стабилизации и мало полезны в продакшн версии. В ней обычно переключаем логику для split-тестирования.
Поэтапная раскатка фичи используется по необходимости в каждой команде. В идеале, в бекенде включаем функциональность, без явной поддержки фичатогла в приложении.

Здравствуйте. Было бы интересно узнать, как происходит у вас обработка недовольных сообщений, да и хороших пожеланий из комментариев Google Play? Обычно пишут "Ваш вопрос передан разработчикам" и все. Интересно, что за ширмой. Если можно — по шагам. Спасибо.

Здравствуйте.
Все отзывы, вопросы и предложения внимательно анализируют продакт менеджеры. Они собирают статистику по проблемам и желаемым фичам, создают тикеты и распределяют их по соответствующим командам в зависимости от типов задач.
Например, в случаях, если пользователи пишут о неизвестном нам баге, то служба поддержки заводит тикет на QA специалистов ответственной команды. Кроме того, для разработчиков у нас настроен канал с отзывами из магазинов приложений в Slack, в который дублируются вообще все вопросы. Важно, чтобы команда видела не только информацию по своим функциональным задачам, но и картину в целом.

Привет. Сейчас в нашем проекте около 10 тысяч junit-тестов и чуть больше тысячи instrumentation-тестов.
С флаки instrumentation-тестами боремся перезапуском тестов. Либо на стороне composer, либо с помощью Rule.

1)Интересует как тестируют приложение. Есть ли своя ферма девайсов? сколько всего аппаратов?
2) интересно послушать про автоматизацию сборки билдов.
3) какие данные шифруют и как
4) используется ли НДК и для чего?
5) какое соотношения кода, написанного функционально и в классическом ООП
6) используют ли они IPC и AIDL?)

  1. В комменте выше отвечали на подобный вопрос. Для автоматизированного тестирования используем эмуляторы, запускаем и останавливаем их с помощью Docker. QA-специалисты для ручного тестирования используют целый зоопарк реальных устройств, разных производителей и разных версий.
  2. В этом комменте рассказывается о нашей системе CI/CD.
  3. На этот вопрос не могу ответить, к сожалению. Отдел security меня за это отругает :)
  4. NDK в приложении не используется. Подходящих задач нету.
  5. В целом, у нас нет ни чистого ООП, ни чистого ФП. Весь код пишется на классах и объектах, но с сильным креном в сторону чистых функций, иммутабельных объектов и прочего.
  6. Для IPC и AIDL тоже нет подходящих задач.
Здравствуйте, только ли JSON единственный вариант для взаимодействия с React сервером и андроид приложением? К примеру как реализовать и какие библиотеки использовать для передачи как изображений, и других документов так и отправка объектов по сети? Какие ещё варианты? Или придётся писать SOAP сервер?
Как у вас осуществляется контроль девайсов? Может взять кто угодно и нужно потом бегать спрашивать всех, у кого нужный тебе девайс? Или есть какая-то система контроля?

Пока с девайсами работаем так: взял — запишись в электронную табличку. Чтобы не вписываться руками, в рамках хакатона разработали концепт системы записи по пропускам: https://habrahabr.ru/company/avito/blog/342466/ (см. “Учёт мобильных девайсов“).

Как вы работаете с нотификациями на аппаратах, у которых стоят autostart, где пользователю в ручную нужно заносить приложение в белый лист, что б получать нотификации?
Sign up to leave a comment.