Комментарии 68
Отсюда следующие вопросы:
1. По какому принципу выделяете модули?
2. Как с этим всем делом дружите Dagger(особенно, если речь идет о фича-модулях)?
3. Какие преимущества вы от этого получили/ожидаете получить? Было бы круто, например, увидеть разницу в скорости сборок.
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-модуль корневой знает о всех дочерних модулях?
При разработке нового приложения, какой сейчас стек технологий/библиотек выбрали бы?
Новое приложение я бы писал на привычном Kotlin, для сетевого взаимодействия выбрал бы OkHttp в паре с Retrofit, RxJava2 для поддержки reactive streams и обязательно посмотрел бы в сторону Architecture Components. MVP же заменил бы однонаправленной архитектурой (Redux, MVI).
2. Почему REST, а не GraphQL?
Когда вы перестанете использовать темные паттерны в интерфейсах?
Как только происходит открытие PullRequest инициируется параллельная серия проверок (скриншот) и ревью кода. Как только все это окрасится в зеленый цвет — происходит мердж в ветку синхронизации (develop)

Все task'и на CI — это скрипты (bash / python), лежащие в репозитории с проектом.
Скрипты запускают команды в docker контейнерах. Эмуляторы для instrumentation-тестов также живут в контейнерах.
Выполняется все это в kubernetes кластере по соседству со всем остальным CI Avito.
Для того чтобы избежать проблем со сломанным кодом после мерджа мы предварительно подмердживаем первым шагом код из develop.
Если за время проверок кто-то успел смерджится — проверки стартуют заново.
Реализовано это при помощи самописного плагина для Bitbucket Server, он стартует билды в TeamCity, отменяет неактуальные, а также может автоматически замерджить твой PR при достижении нужных кондиций (если ты его об этом попросишь)
Интересуют два вопроса:
1. Для тестов запускается эмулятор внутри контейнера? Если да — какие библиотеки/инструментарий применяете для надежного контроля его работы? По моим наблюдениям, avd-эмулятор даже обычного нексуса отличается некоторой нестабильностью.
2. Используете ли для инструментальных тестов большую сетку из различных комбинаций устройств/sdk для проверки стабильности или же прогоняете тесты на небольшом списке девайсов?
3. Какие библиотеки/плагины gradle используете для автоматической подписи и доставки приложений в Play Market?
1) Используете ли в своих приложениях чистую архитектуру, и если да, то как относитесь к хранению состояния в интеракторах (Например интерактор доавторизационной зоны с функционалом регистрации\авторизации, который на разных шагах сохраняет какие-то данные и использует их при последущих запросах)? Если негативно, то как выходите из подобных ситуаций?
2) MVP или MVVM? И можно ли контекст тащить в презентер?
1) Мы не используем “чистую архитектуру” в ее первозданном виде, скорее некую адаптацию. Интерактор сохраняет свое состояние только для кеширования результатов части запросов. В ситуации описанной вами скорее всего за это будет отвечать верхнеуровневый презентер.
2) Чаще всего в проекте используется MVP. Пристально смотрим в сторону однонаправленных архитектур и экспериментируем с ними.
Мы стараемся максимально изолировать презентеры и интеракторы от взаимодействия с android-классами. Это облегчает юнит-тестирование: тесты можно запускать без Robolectric.
У вас работает несколько(множество) независимых команд, которые ведует свои модули, но работают при этом в одном проекте. Понятно, что тут все не так просто, и существует много пересечений, но для простоты рассмотрим идеальный вариант.
Позволяете ли вы писать командам «кто во что горазд», либо спускаете «сверху» требования/гайдлайны. В первом случае, будет высокая энтропия(множество разных подходов в одном проекте, библиотеки, которые делают одно и то же, но немного по-разному, etc.), но при этом, хоть и спорно, кодовая база будет эволюционировать и инженеры будут рады, так как у них есть возможность пробовать новое. Во втором случае, обратная ситуация, проект будет иметь более или менее стройную архитектуру, но будет существовать очень много решений в статусе-кво со всеми вытекающими.
Иными словами, как вы балансируете энтропию и стагнацию в большом проекте с множеством независимых команд?
Пуш уведомления показываются "как есть" (локадизация текста), или обрабатываются на клиенте?
- Все ли разработчики знают и делают все части приложения, или каждый отвечает за определенный сделаный им функционал и не лезет не в свое?
Таким образом, клиент показывает уведомления как есть, логика по отображению на стороне клиента минимальна.
2. В основном разработчики сфокусированы на тех участках кода, которые отвечают целям команды. Получается такой негласный Code Ownership. Чтобы оптимизировать Code Review мы написали специальный плагин для определения оптимальных ревьюверов для измененных файлов.
Но в целом, во всем приложении используются похожие подходы, поэтому разобраться в другом участке кода достаточно просто.
И отслеживаете ли метрики в кодовой базе? Количество багов, smells code и т.д.
1. Для тестов запускается эмулятор внутри контейнера? Если да — какие библиотеки/инструментарий применяете для надежного контроля его работы? По моим наблюдениям, avd-эмулятор даже обычного нексуса отличается некоторой нестабильностью.
2. Используете ли для инструментальных тестов большую сетку из различных комбинаций устройств/sdk для проверки стабильности или же прогоняете тесты на небольшом списке девайсов?
3. Какие библиотеки/плагины gradle используете для автоматической подписи и доставки приложений в Play Market?
Эмуляторы достаточно стабильны уже! Удивительно сколько работы проделал 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
в 2017ом мы в основном тестировали на FirebaseTestLab, но на наших масштабах это дорого, долго (очереди на популярные девайсы), нестабильно (черный ящик и непонятные сроки решения проблем). В конце года мы полностью переехали на свои мощности. Тестируем только на эмуляторах (см конфиг для регресса выше). API выбрали как 4 самые популярные у юзеров.
- На всякий случай не буду ничего подробно расписывать (sensitive инфа как никак), скажу только что вся процедура происходит автоматически.
Как улучшаете ситуацию?
Отдельного отдела QA у нас нет, функциональные тестировщики являются членами продуктовых команд. Тестирование можно разбить на два этапа: приемочное тестирование сразу после разработки фичи и регрессионное, проводящееся перед каждым релизом. Во время разработки фичи тестировщики пишут тест-кейсы для них и, по желанию, авто-тест для проверки. Непротестированные фичи либо живут в своих ветках, либо изолированы фиче-тогглом. После прохождения ручного или автоматического приемочного тестирования фича включается в следующий релиз, а тест-кейсы связанные с ней, — в регрессионный пакет. (edited)
Мои коллеги немного поправили меня:
Тест-кейсы пишутся в процессе разработки на основании бизнес-требований или документации. Далее при получении фичи тестировщик проводит функциональное тестирование и некоторые виды нефункционального. Например, тестирование установки. тестирование на отказ и восстановление. В некоторых командах сразу же пишутся автотесты. И потом уже на перед релизом проводится регрессионое тестирование.
Каким образом вы профилируете на них производительность?
Какие курьезные баги связанные с ними у вас были?
К сожалению, пока никак. В целом мы стремимся к максимально тонкому клиенту и переносим максимум бизнес-логики на сторону сервера. То немногое, что остается на клиенте приходится писать два раза: для Android и для iOS. Очень внимательно следим за проектом Kotlin Native для шаринга кода между платформами.
Для запуска тестов мы используем внутренний форк github.com/gojuno/composer, правда переписанный уже до неузнаваемости. Там например реализован динамический шардинг и запуск всех тестов в отдельных instumentation процессах. Тоже подумаем над публикацией.
1. Кто занимается написанием новых тестов (функциональные тестировщики, или отдельная команда автоматизации, или разработчики)?
2. Кто занимается развитием и поддержкой инфраструктуры для автоматизации?
3. Если в других командах (iOS, Web) тоже есть автоматизация тестирования, стараетесь ли унифицировать (в рамках возможного) с ними наборы покрытых тестами тест-кейсов, или у каждой команды свои наборы сценариев?
4. Автотесты запускаются только на одном из этапов жизненного цикла релиза (например, при сборке свежего билда), или чаще?
5. Тестировщики запускают тесты самостоятельно, или они запускаются автоматом на определенных этапах жизни задачи/релиза?
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 с несколькими фрагментами. Пример: флоу подачи объявления.
Здравствуйте. Было бы интересно узнать, как происходит у вас обработка недовольных сообщений, да и хороших пожеланий из комментариев Google Play? Обычно пишут "Ваш вопрос передан разработчикам" и все. Интересно, что за ширмой. Если можно — по шагам. Спасибо.
Здравствуйте.
Все отзывы, вопросы и предложения внимательно анализируют продакт менеджеры. Они собирают статистику по проблемам и желаемым фичам, создают тикеты и распределяют их по соответствующим командам в зависимости от типов задач.
Например, в случаях, если пользователи пишут о неизвестном нам баге, то служба поддержки заводит тикет на QA специалистов ответственной команды. Кроме того, для разработчиков у нас настроен канал с отзывами из магазинов приложений в Slack, в который дублируются вообще все вопросы. Важно, чтобы команда видела не только информацию по своим функциональным задачам, но и картину в целом.
1)Интересует как тестируют приложение. Есть ли своя ферма девайсов? сколько всего аппаратов?
2) интересно послушать про автоматизацию сборки билдов.
3) какие данные шифруют и как
4) используется ли НДК и для чего?
5) какое соотношения кода, написанного функционально и в классическом ООП
6) используют ли они IPC и AIDL?)
- В комменте выше отвечали на подобный вопрос. Для автоматизированного тестирования используем эмуляторы, запускаем и останавливаем их с помощью Docker. QA-специалисты для ручного тестирования используют целый зоопарк реальных устройств, разных производителей и разных версий.
- В этом комменте рассказывается о нашей системе CI/CD.
- На этот вопрос не могу ответить, к сожалению. Отдел security меня за это отругает :)
- NDK в приложении не используется. Подходящих задач нету.
- В целом, у нас нет ни чистого ООП, ни чистого ФП. Весь код пишется на классах и объектах, но с сильным креном в сторону чистых функций, иммутабельных объектов и прочего.
- Для IPC и AIDL тоже нет подходящих задач.
Пока с девайсами работаем так: взял — запишись в электронную табличку. Чтобы не вписываться руками, в рамках хакатона разработали концепт системы записи по пропускам: https://habrahabr.ru/company/avito/blog/342466/ (см. “Учёт мобильных девайсов“).
Ask me anything. Avito. Android