company_banner

Разбираем iOS-приложение Avito: Ask Me Anything

    Привет! Сегодня в нашем блоге мы проводим уже традиционную секцию вопросов и ответов Ask Me Anything. (До этого были АМА по бэкенду и по android-разработке). Продолжаем хорошую традицию. На этот раз речь пойдёт о разработке под iOS в целом и об особенностях приложения Авито в частности.



    Как работается с приложением самого популярного сайта объявлений в России? Спросите у нас! Мы ответим на все комментарии первого уровня, которые появятся здесь до полудня 6 июня по московскому времени. Под катом я представляю семь моих коллег, которые будут с вами на связи, рассказываю немного об iOS-разработке в Авито и о возможных темах диалога.


    UPD: Официально мы закрываем АМА, но по возможности обещаем отвечать на комментарии. Спасибо всем за участие!


    Участники АМА


    Евгений Суворов kokax


    image
    «Руководитель команды мобильной архитектуры, которая отвечает за техническое качество продукта, удовлетворенность разработчиков разработкой и развитием/поддержкой внутренних инструментов разработчиков. В разработке под iOS с 2011 года, в Авито стал первым мобильным разработчиком в 2014».


    Алексей Шпирко truealex


    image
    «Руководитель команды, занимающейся ускорением релизов мобильных приложений, построением CI/CD в мобильных приложениях, разработкой инструментов для UI-тестов. В Авито с 2014 года. Про то, чем я занимаюсь, можно подробнее узнать, посмотрев мой доклад для Mobius 2018 по ссылке».


    Иван Бондарь ivanbondar


    image
    «Руководитель группы разработки мобильных приложений, занимаюсь разработкой под iOS с 2012 года, присоединился к команде Авито 2,5 года назад. Совмещаю роли iOS-разработчика, скрам-мастера и руководителя небольшой кросс-функциональной команды. Помимо iOS немного пишу backend, помогаю другим командам».


    Артем Разинов artyom-razinov


    image
    «iOS-разработчик, в iOS с 2011 года, в Авито чуть более трёх лет. Занимался всем, в последнее время на 100% погружен в UI-автотестирование — инструменты, CI/CD и все такое. Мои хобби и увлечения: автотестирование, диплинкинг, гибкое API, кодогенерация, хаки, трюки и обманы».


    Алексей Кудрявцев WEStor


    image
    «iOS-разработчик юнита Мессенджер, мейнтейнер проекта SwiftyVK, звукарь подкаста Podlodka. В Авито с января 2017 года. За это время успел поработать над разными частями iOS-приложения в нескольких юнитах. До Авито работал в небольших стартапах, делал pet-project’ы под iOS и MacOS. Помимо разработки люблю в свободное время побегать, покатать на велосипеде или что-нибудь почитать».


    Тимур Юсипов fizmatchel


    image
    «iOS-разработчик юнита Mobile Architecture. Разрабатываю под iOS с 2012 года. В Avito почти 3 года. Занимался за это время много чем, прошел путь от фичовой разработки до платформенной.
    В последнее время занимаюсь:


    • модуляризацией монолита (разбили таргет с 2000+файлами на 40+ модулей),
    • оптимизацией сборки путем упрощения графа зависимостей между модулями,
    • созданием и сопровождением переиспользуемых разработчиками утилит: обертки над UICollectionView, инструмента для навигации, инструмента для диплинкинга, своих правил Swiftlint, Xcode-шаблонами для быстроты написания нового кода и прочей инфраструктурой,
    • автоматизацией замеров различных технических характеристик (скорость запуска, скорость чистой сборки, утилизация CPU на чистой сборке, размеры модулей, количество контрибьюторов модулей, …).
      Увлекаюсь футболом, коньками и роликами, пляжным волейболом, велосипедом, палаточными походами».

    Вадим Смаль vadimsmal


    image
    «iOS-разработчик юнита Mobile Architecture. Разрабатываю под MacOS / iOS с 2012 года. В Авито уже 1.5 года. Занимаюсь разработкой решений для увеличения скорости разработки и поддержания качества приложения: toggle, DI, система отправки аналитики, автоматизированные замеры метрик, различные проверки состояния проекта и прочее.
    Интересуюсь изучением новых технологий, таких, как Machine learning и blockchain. Изучаю новые платформы, подходы и языки, например, микросервисы на Go».


    Немного фактов про iOS-разработку в Avito


    • Мы в Avito уделяем много внимания мобильным приложениям. И планируем сохранять этот тренд.
    • Команда iOS-разработчиков использует Swift. Он заменил Objective-C в наших продуктах.
    • Мы инвестируем в развитие и продвижение инженерных практик — CI, CD, Code Review, автоматизация тестирования.
    • Важная особенность iOS-разработки в Avito — модульная архитектура, позволяющая нескольким группам разработчиков развивать крупный проект без коллизий и оперативно реагировать на нужды пользователей.

    Возможные вопросы и темы для обсуждения


    • Как устроено наше приложение.
    • Как мы ведём разработку нашего iOS-приложения большой командой.
    • Монорепозиторий для кода: «боли» и профиты
    • Рабочие процессы: код-ревью, пулл реквесты, запуск тестов, проверки.
    • CI/CD.
    • Автоматизированное тестирование.
    • Легаси: как мы с этим боремся.
    • Внутренние решения для разработки: навигация, кодогенерация, feature-toggle, networking, решение для построения списков, DI, аналитика, deep links.
    • Замеры и оптимизация метрик: время сборки/запуска, размер приложения, количество зависимостей, утилизация CPU на сборке.
    • Продуктовая разработка, кросс-функциональность, A/B тестирование.

    Материалы о разработке под iOS с участием сотрудников Avito



    Ждём ваших вопросов в комментариях!

    Авито
    257.44
    У нас живут ваши объявления
    Share post

    Comments 23

      +2
      Определение товара по фото на ML построенно?
        +2
        Да, основано на ML, определение работает на бэкенде. Модель постоянно совершенствуется, обучаясь на всех объявлениях, размещаемых на нашей платформе.
        +1
        Не у всех есть регистрация на Хабре, но вопросы приходят и в наши соцсети/из чатиков. Буду их сюда копировать.

        >Слышал, что вы разрабатываете свой фреймворк для UI тестов. Можете рассказать подробнее, да и вообще раскрыть тему, почему это лучше юнит-тестов?
          +2
          В конце прошлого года начали заниматься End-to-end UI тестами. В ближайшее время выложим в Open Source.

          Что же лучше, юнит тесты и UI тесты? Одно не лучше другого. Они дополняют друг друга.

          Мы исповедуем прагматичный подход, мы занимаемся UI тестами, потому что они нам помогают минимизировать ручное тестирование. Фактически сейчас мы релизимся чаще раза в 2 недели, релизим две платформы, релизим приложение с огромным количеством сценариев использования. Перед релизом мы проводим регрессионное тестирование. У нас много сценариев в регрессионном тестировании, мы планируем закрыть их на 100%. То есть основная задача наших E2E тестов — минимизировать ручное тестирование. В основном UI тесты пишут тестировщики. Юнит тесты же пишут только разработчики для проверки своего кода.

          По фреймворку. Мы написали фреймворк, удобный для написания тестов, мы используем XCUI, но абстрагировались от него, да и вообще от многого. Например, одни и те же тесты можно запускать с EarlGrey и c XCUI. Если чего-то в XCUI не хватает, мы свободны тестировать в обход XCUI. Чуть подробнее рассказывал на Cocoaheads: youtu.be/036qVHFtNxc
          +3
          На Авито iOS был доклад про сбор метрик в мобильном приложении, какие технические или продуктовые решения получилось с помощью них сделать, принесли они какой-то профит?
            +1
            Профит есть, и он состоит в поддержании качества приложения.

            Сбор метрик позволил несколько раз заметить увеличение времени запуска приложения, найти причину и исправить.
            Также они позволяют быстро проверять и валидировать наши эксперименты по улучшениях тех или иных характеристик.
            В частности во время процесса модуляризации ( разделения `монолита` на множество модулей ) мы тщательно мониторили технические метрики для достижения оптимальной скорости компиляции, времени запуска и размера.

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

              А можно подробнее про скорости компиляции. Как было, как стало? На каких машинах разработка ведется?
                +1
                Все замеры проводятся на mac mini (2 физических + 2 логических ядра), а разработка ведется на MacBook Pro (4 логических + 4 логических), так что у разработчиков все собирается быстрее.

                Время чистой сборки на mac mini сократилось с 600 секунд до 390. А вот инкрементальная сборка с изменением самого тяжелого модуля сократилось с 200 секунд до 25.

                С недавнего времени стали собирать статистику по утилизации CPU — какой процент времени xcode собирает фреймворки параллельно на всех ядрах. Это позволяет понять, какие части приложения мешают компилироваться других частям.
          0
          Вопрос из чатика.
          >Какая архитектура используется на презентейшн слое?
            +1
            Мы используем VIPER. Presenter отвечает за связь модели (Interactor — фасад для модели) и отображения (View — фасад для UI). Стараемся делать стейтлесс. Обычно все события идут в одностороннем потоке. Например, View -> Presenter -> Interactor -> Presenter -> View.

            View не знает про модели из Interactor, Interactor также изолирован от источника данных. Intractor — это фасад, он использует лишь абстракции.

            Также Presenter умеет работать с Router — абстракцией над навигацией в приложении. Presenter изолирован от UIKit, нам в этом очень сильно помогает библиотека Marshroute (https://github.com/avito-tech/Marshroute). Видео по теме: выступление Тимура Юсипова, автора Marshroute, на РИТ++ по навигации в iOS: youtu.be/h6c4IkZxFZY
            +1
            Касательно монорепо.
            1) У вас один проект — Авито? Или есть другие приложения, лежащие в этом репо?
            2) Если проектов несколько, какая у вас структура? Заведены ли воркспейсы для каждого из приложений, или в одном воркспейсе несколько таргетов для каждого приложения?
            3) Вы же используете cocoapods development pods для внутренних модулей (фичи, кор слой)?
            Как происходит процесс изменения чего-либо в кор слое? Или изменения медиатора? От них же зависит не только сам проект, но и почти все эти компоненты. А dependency в podspec можно выставлять только через версию, то есть path-ом не получится воспользоваться.
              +2
              1.) В монорепозитории один продукт — Авито. Так же в нем есть другие приложения, которые используются в качестве демок для более быстрой работы над проектом, так как демки содержат меньше кода и собираются быстрее.

              2.) Для демок заведены отдельные таргеты в том же воркспейсе, что дает быстрый доступ ко всем демкам.

              3.) Так как все наши зависимости живут в монорепозитории, то они объявлены как “development pod” и прописаны в “podfile” статическими путями. Они не версионируются, опять же потому, что все живет в одном репозитории и вся кодовая база проекта синхронизирована сама по себе. Изменения core-слоя происходят достаточно редко и они минимальны, так как мы стараемся делать простые интерфейсы, а на случай больших изменений у нас всегда есть фича тоглы)

              Почему мы используем такую схему работы с проектом? Около года назад у нас были репозитории для каждого отдельного модуля/слоя, но это замедляло разработку, так как при изменении зависимости тебе нужно было сделать минимум 2 пулл реквеста и, скорее всего, порешать конфликты. Было долго и мучительно. Так как проект у нас один и он не шарит код с другими аппами, то схема с монорепой убрала всю боль и не принесла новой. В общем, нам это хорошо зашло)
              0
              По какому принципу выделяли модули из монолита? Есть модули без презентейшен слоя?
                +1
                Без презентационного слоя у нас только утилитки (Core слой), и так случилось, что все они были вынесены наружу из монолита задолго до того, как он начал требовать распила. Можно сказать, что когда такие утилитки появлялись (на замену легаси коду), они сразу оформлялись в виде отдельных модулей (а до перезда в монореп и в виде отдельных репозиториев)

                В монолите же лежали только модули экранов, то есть модули с презентационным слоем (хотя модулями их было трудно назвать, монолит же =)).

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

                Например, все экраны платных услуг выделили в отдельный cocoapod. За эти экраны ответственна определенная группа разработчиков

                Другие примеры фич — главная страница + экраны поисковой выдачи, экраны выбора локации, экраны поисковых фильтров, экраны публичного профиля пользователя, экраны приватного профиля пользователя, экраны по работе с картой, экраны по работе с веб-контентом

                При этом мы старались придерживаться результатов наших ресерчей, согласно которым с точки зрения параллельности сборки и результирующего размера приложения оптимально разбивать монолит на фичи по 5-10 экранов.
                0
                написал мимо ветки)
                  0
                  Для демок заведены отдельные таргеты в том же воркспейсе, что дает быстрый доступ ко всем демкам.

                  1. Какого порядка число таргетов? Демка — это тоже самое приложение с реализацией фичи/фикса или только сама фича?


                  2. Как вы собираете, версионируете и распространяете (внутри команды) демки и фичи? Расскажите подробнее про используемые CI/CD.
                    +1
                    Про CI/CD. Демки — это отдельные маленькие приложения, связанные, как правило, с фичами конкретного юнита и используются внутри юнита и поэтому их распространять на всех не нужно.
                    Что касается распространения приложения Авито внутри компании — мы используем Testflight (заливаем туда сборки с помощью fastlane), куда добавлены как internal users(тестировщики) так и external testers(все заинтересованные в компании). Также вместе с Авито у нас распространяется отдельное приложение с фича-таггламм, которое позволяет включать фичи в приложении Авито для различных конфигураций(напр: debug, adhoc, release).
                    Мы собираем сборки для тестирования каждые 2 часа из develop, также есть возможность у разработчика собрать сборку для тестирования на своей ветке.
                    Подробнее про флоу CI/CD у нас — youtu.be/r3rUedCbe7Q
                      +1
                      Так же могу дополнить, что демок больше десятка. Демо — это приложение с подключенными к нему необходимыми модулями и необходимой для них частью core-слоя. Ничего лишнего, только нужный юниту функционал.
                      0
                      пулл реквесты, легаси, feature-toggle…
                      а сайт тяжелый — крутится много всего совершенно не нужного для пользователей
                        0
                        Добрый день, чем пользуетесь при кодогенерации?
                          +1
                          Sourcery используем для генерации Swift кода на основе Swift кода.
                          github.com/krzysztofzablocki/Sourcery

                          У нас довольно много кода им генерируется, поэтому у нас есть обвязки, оптимизирующие это. Кодогенерация запускается в Pre-Action при билде, занимает на горячую порядка секунды. Очень мощный инструмент, довольно стабилен. Случаются казусы, но оно у нас работает почти без нареканий, это даже удивительно.

                          Кодогенерацией делаем конструкторы, функции сравнения, генерируем тесты на DI, генерируем различные списки, типа списка поддерживаемых методов API. Всего сейчас использется 26 Stencil шаблонов.

                          SwiftGen используем для генерации Swift кода на основе ассетов.
                          github.com/SwiftGen/SwiftGen

                          Помогает избавится от строковых литералов, добавляет автокомплит, фактически в компайл тайме проверяется правильность использования ассетов. Очень легко встраивается и поддерживает кастомные шаблоны.

                          Jinja2. Есть код на Python3 для генерации скелета тестов UI тестов на основе описания тесткейсов ручного регресса. Также Jinja2 используется для генерации отчетов на CI.
                          0
                          А если не секрет, что используете для проверки уязвимости кода? Используете ли статические анализаторы?

                          Only users with full accounts can post comments. Log in, please.