Save 37% off PRO during our Black Friday Sale! »

Катастрофически полезные последствия модуляризации (в мире iOS и непрерывной интеграции) - Артём Лоенко, Badoo

5d08ba0cd07942f2ddbf82e5b21ba5e7?s=47 FunCorp
February 15, 2020

Катастрофически полезные последствия модуляризации (в мире iOS и непрерывной интеграции) - Артём Лоенко, Badoo

5d08ba0cd07942f2ddbf82e5b21ba5e7?s=128

FunCorp

February 15, 2020
Tweet

Transcript

  1. Артем Лоенко · 15 февраля КАТАСТРОФИЧЕСКИ ПОЛЕЗНЫЕ ПОСЛЕДСТВИЯ МОДУЛЯРИЗАЦИИ в

    мире iOS и непрерывной интеграции
  2. Всем привет, меня зовут Артем Лоенко tech.badoo.com/ru/ github.com/dive @justsitandgrin 2

  3. Модуляризация Подготовка Вызванные изменения Мониторинг Вступительная часть План доклада Заключение

    3
  4. Какие проблемы мы решали • Масштабирование разработки • Экономия времени

    и ресурсов • Синергия между приложениями • Качество кода Вступительная часть Начало 4
  5. МОДУЛЯРИЗАЦИЯ 5

  6. Модуляризация — процесс разбиения кодовой базы на небольшие, специализированные и

    готовые к повторному использованию части или модули Вводная часть Что? 6
  7. Вводная часть Как это выглядит Платформа (10) Функциональные модули (80)

    Внутренние модули Внутренние модули 7
  8. Вводная часть Как это выглядит Сеть Аналитика Proto Buffer Логирование

    Обработка ошибок … Функциональные модули (80) Внутренние модули Внутренние модули 8
  9. Вводная часть Как это выглядит Платформа (10) Функциональные модули (80)

    Внутренние модули Внутренние модули 9
  10. Вводная часть Как это выглядит Платформа (10) Функциональные модули (80)

    Внутренние модули Sign In with Apple 10
  11. Вводная часть Как это выглядит Платформа (10) Функциональные модули (80)

    Внутренние модули Внутренние модули 11
  12. Вводная часть Как это выглядит Платформа (10) Регистрация Чат Навигация

    Платежи … Внутренние модули Внутренние модули 12
  13. Вводная часть Как это выглядит Платформа (10) Функциональные модули (80)

    Внутренние модули Внутренние модули 13
  14. Вводная часть Как это выглядит Сеть Регистрация Sign In with

    Apple Видеостриминг Платежи Аналитика Чат 14
  15. Где мы находимся сейчас • 100 модулей и 7 приложений

    • Независимые компонентные команды • Отсутствие дублирования функционала • Быстрая интеграция между приложениями • Все мыслят модулями. От менеджеров по продуктам до отдела непрерывной интеграции Вступительная часть Начало 15
  16. ПОДГОТОВКА 16

  17. С чего начать Подготовка 17

  18. Наш выбор — эксперимент Подготовка С чего начать 18

  19. Как мы доказывали концепцию Подготовка С чего начать 19

  20. • Готовый функционал — чат Чат Чат Чат Как мы

    доказывали концепцию Подготовка С чего начать 20
  21. • Планирование и документация Чат Чат Чат Как мы доказывали

    концепцию Подготовка С чего начать • Готовый функционал — чат 21
  22. • На связи с существующими процессами Чат Чат Чат Как

    мы доказывали концепцию Подготовка С чего начать • Планирование и документация • Готовый функционал — чат 22
  23. • Повторное использование Чат Чат Как мы доказывали концепцию Подготовка

    С чего начать • Планирование и документация • Готовый функционал — чат 23 • На связи с существующими процессами
  24. • Интеграция другими разработчиками Чат Как мы доказывали концепцию Подготовка

    С чего начать 24 • Повторное использование • Планирование и документация • Готовый функционал — чат • На связи с существующими процессами
  25. • Последующие интеграции — дело техники Чат Как мы доказывали

    концепцию Приложение Подготовка С чего начать 25 • Интеграция другими разработчиками • Повторное использование • Планирование и документация • Готовый функционал — чат • На связи с существующими процессами
  26. Результаты эксперимента • Документация • Живой пример в репозитории •

    Большинство разработчиков участвовали в процессе • Все понимают, чего ожидать Подготовка С чего начать 26
  27. Унификация конфигураций проектов с помощью xcconfig Подготовка 27

  28. • Отличия в конфигурации проектов • Нет возможности менять опции

    для всего и сразу • Нет общей точки контроля • Излишняя нагрузка на разработчиков Подготовка .xcconfig Проблемы 28
  29. Сеть Sign In with Apple Видео стриминг Аналитика Подготовка .xcconfig

    Я обрезаю debug символы Bitcode в debug конфигурации? Почему бы и нет Эх, armv6! Помню тебя еще молодым Предупреждения компилятора — визуальный шум Унификация 29 Регистрация Платежи Чат
  30. Сеть Регистрация Sign In with Apple Видео стриминг Платежи Аналитика

    Чат Подготовка .xcconfig Редактирование А давайте попробуем разные оптимизации компилятора! 240 = 5 проектов * 3 конфигурации * (4 * 4) варианта оптимизации 30
  31. • Хранят настройки вне .xcodeproj • Поддерживают вложенность • Настройки

    на уровне и проекта, и target’а • Текстовые файлы – легко читать в CVS • Единый источник правды для всех модулей Подготовка .xcconfig Что это такое xcconfig 31
  32. Подготовка .xcconfig Как это работает В проекте хранятся все общие

    конфигурации 32
  33. Подготовка .xcconfig Что это дает • Унифицированные настройки • Эксперименты

    с конфигурациями • Минимальный риск ошибки • Ответственна конкретная команда • Изменения настроек в .xcodeproj запрещены 33
  34. Явные и неявные зависимости. Разница. Подготовка 34 и почему вам

    лучше об этом знать
  35. Подготовка Зависимости Явное и неявное 35 • По умолчанию Xcode

    предпочитает неявные зависимости
  36. Явное и неявное • По умолчанию Xcode предпочитает неявные зависимости

    • Явные зависимости • Задаются через “Target Dependencies” • Всегда собираются до зависимого проекта • Приоритет выше, чем неявные зависимости 36 Подготовка Зависимости
  37. Сеть Регистрация Sign In with Apple Видеостриминг Платежи Аналитика Чат

    37 Подготовка Зависимости
  38. Сеть Регистрация Sign In with Apple Видеостриминг Платежи Аналитика Чат

    Неявное Система сборки 38 Подготовка Зависимости
  39. Сеть Регистрация Sign In with Apple Видеостриминг Платежи Аналитика Чат

    Неявное Система сборки 39 Подготовка Зависимости
  40. Сеть Регистрация Sign In with Apple Видеостриминг Платежи Аналитика Чат

    Явное Система сборки 40 Подготовка Зависимости
  41. Почему это важно Когда у вас >10 модулей, вы захотите

    понимать, что от чего зависит 41 Подготовка Зависимости
  42. Легко ошибиться с неявными зависимостями Почему это важно 42 Подготовка

    Зависимости
  43. DYLD_FRAMEWORK_PATH=../Xcode/DerivedData/../Build/Products/Debug-iphonesimulator Почему это важно 43 Подготовка Зависимости Легко ошибиться с

    неявными зависимостями
  44. Единственный способ построить граф зависимостей — напрямую из проектов Почему

    это важно 44 Подготовка Зависимости
  45. Чат Платформа Удаление неявных промежуточных зависимостей не изменят граф Почему

    это важно 45 Подготовка Зависимости
  46. Платформа Неявные зависимости запрещены Почему это важно 46 Подготовка Зависимости

  47. Платформа Зависит Использует Почему это важно 47 Подготовка Зависимости Неявные

    зависимости запрещены
  48. Автоматизация создания новых модулей Подготовка 48

  49. Подготовка Создание модулей Зачем автоматизировать • Xcode не предоставляет инструментов

    для автоматизации • Много однотипных шагов • Настройка — бесконечное кликанье • Высокая вероятность ошибок • Процесс не должен мешать разработке 49
  50. Подготовка Создание модулей Как это работает • Swift скрипт, который

    знает о наших соглашениях • Правильные пути и структура (Xcodegen) • Шаблоны для файлов с исходным кодом • Конфигурация с помощью xcconfig • Настройки для непрерывной интеграции 50
  51. Подготовка Создание модулей Как это работает 51

  52. Подготовка Создание модулей Результат • Создание нового модуля занимает минуты

    • Все модули имеют одинаковую структуру • Изменения при создании модулей скрыты за утилитой • Низкий порог вхождения • За утилиту ответственна отдельная команда 52
  53. Подготовка Итого • Проверка концепции – документированное решение 53

  54. • Проверка концепции – документированное решение • xcconfig – унификация

    сложных мест, низкий порог вхождения Подготовка Итого 54
  55. • Проверка концепции – документированное решение • xcconfig – унификация

    сложных мест, низкий порог вхождения • Явные зависимости – прозрачная структура Подготовка Итого 55
  56. • Проверка концепции – документированное решение • xcconfig – унификация

    сложных мест, низкий порог вхождения • Явные зависимости – прозрачная структура • Автоматизация - быстрые и гибкие инструменты Подготовка Итого 56
  57. • Проверка концепции – документированное решение • xcconfig – унификация

    сложных мест, низкий порог вхождения • Явные зависимости – прозрачная структура • Автоматизация - быстрые и гибкие инструменты • Понимание возможных последствий Подготовка Итого 57
  58. ВЫЗВАННЫЕ ИЗМЕНЕНИЯ 58

  59. Связывание и поддержка развесистого графа зависимостей Вызванные изменения 59

  60. Вызванные изменения Граф “Упрощенная” схема 60

  61. Проблемы • Граф зависимостей – это сложно • Визуализация —

    только выборочная • Тяжело отлаживать • Добавление зависимостей – задача не для слабонервных • Избыточная нагрузка на разработчиков Вызванные изменения Граф 61
  62. Вызванные изменения Граф 62 Утилита deps • Ищет проблемы в

    графе зависимостей • Указывает разработчикам на проблемы • Исправляет типовые ошибки
  63. Утилита deps • Swift консольное приложение • Оперирует xcodeproj файлами

    • Знает о требованиях к нашему графу • “Понимает” сторонние зависимости • Включена в процессы непрерывной интеграции Вызванные изменения Граф 63
  64. Утилита deps Вызванные изменения Граф 64 Doctor — проверяет, что

    все зависимости корректно связаны и встроены в приложение
  65. Утилита deps – doctor Вызванные изменения Граф 65

  66. Утилита deps Вызванные изменения Граф 66 Fix — исправляет все

    ошибки, о которых ей известно
  67. Утилита deps – fix Вызванные изменения Граф 67

  68. Утилита deps Вызванные изменения Граф • Add — добавляет зависимость

    между двумя модулями Сеть Регистрация Sign In with Apple Видео стриминг Платежи Аналитика Чат 68
  69. Утилита deps – add Вызванные изменения Граф Сеть Регистрация Sign

    In with Apple Видео стриминг Платежи Аналитика Чат Навигация 69
  70. Утилита deps – add Вызванные изменения Граф Сеть Регистрация Sign

    In with Apple Видео стриминг Платежи Аналитика Чат Навигация Видео чат 70
  71. Результат • Поддержка графа автоматизирована • Упрощенное редактирование • Валидация

    с возможностью восстановления после ошибок Вызванные изменения Граф 71
  72. Прерывания в непрерывной интеграции Вызванные изменения 72 или Как не

    собирать 100 модулей на каждый чих
  73. Проблемы • “Проверь всё” плохо масштабируется • Собирать 100 проектов

    — долго, дорого и бессмысленно • Инфраструктурные проблемы больше отвлекают Вызванные изменения Непрерывная интеграция 73
  74. Попытка номер один • Вычислять изменения по структуре директорий •

    Запускать часть интеграционных проверок ночью • Разработчик сам указывает, что проверять Вызванные изменения Непрерывная интеграция 74
  75. Решение Вызванные изменения Непрерывная интеграция Нужно проверять только то, что

    реально изменилось 75
  76. Утилита deps Вызванные изменения Непрерывная интеграция 76 Affected — указывает

    на то, какие модули затронуты изменениями в системе контроля версий
  77. Утилита deps – affected Вызванные изменения Непрерывная интеграция 77

  78. Сеть Регистрация Sign In with Apple Видео стриминг Платежи Аналитика

    Чат Вызванные изменения Непрерывная интеграция 78 Утилита deps – affected
  79. Явно затронуты Вызванные изменения Непрерывная интеграция 79 Утилита deps –

    affected Сеть Регистрация Sign In with Apple Видео стриминг Платежи Аналитика Чат
  80. Косвенно затронуты Вызванные изменения Непрерывная интеграция 80 Утилита deps –

    affected Сеть Регистрация Sign In with Apple Видео стриминг Платежи Аналитика Чат
  81. Результат • Проверяется только то, что реально изменилось • Процесс

    непрерывной интеграции не связан с количеством модулей линейно • Бонус: можно определять, какие модули затронуты изменениями в коде на любом этапе разработки Вызванные изменения Непрерывная интеграция 81
  82. Как мы делали тесты умными Вызванные изменения 82

  83. Вызванные изменения Умные тесты 83 Сеть Sign In with Apple

    Видео стриминг Платежи Чат Регистрация Аналитика Мы знаем, какие модульные тесты запускать, чтобы протестировать изменения в ветке deps affected
  84. Сквозные тесты (E2E) • Напрямую не соотносятся с модулями •

    Оперируют пользовательским функционалом на уровне приложения • Группируются по пользовательским сценариям 84 Вызванные изменения Умные тесты
  85. Умные сквозные тесты 85 Вызванные изменения Умные тесты Полуавтоматический механизм

    вычисления нужного набора сквозных тестов из списка затронутых модулей
  86. Умные сквозные тесты 86 Вызванные изменения Умные тесты

  87. Результат • Нагрузка на систему непрерывной интеграции значительно снизилась •

    Уменьшился шум от инфраструктурных проблем • Дополнительная точка синхронизации между разработкой и тестированием 87 Вызванные изменения Умные тесты
  88. Результат 88 Вызванные изменения Умные тесты Тесты поумнели

  89. Статическое связывание модулей Вызванные изменения 89 или "10 динамических модулей

    хватит всем!" (c) Apple
  90. Проблема Вызванные изменения Статическое связывание 90 Динамическое связывание замедляет запуск

    приложения Apple, WWDC 2016 Optimizing App Startup Time
  91. Вызванные изменения Статическое связывание 91 Время запуска приложения

  92. Вызванные изменения Статическое связывание 92 А прель 2018 И ю

    ль 2018 О ктябрь 2018 Январь 2019 А прель 2019 И ю ль 2019 О ктябрь 2019 Январь 2020 Время запуска приложения
  93. Время запуска приложения Вызванные изменения Статическое связывание 93 65 модулей

    90 модулей iOS 13 (dyld3) 45 модулей
  94. Минусы • Статические модули не могут содержать ресурсов • Практически

    обязательный флаг -all-load для модулей с Objective C • Придется переключить оптимизации не в оптимальные режимы (STRIP_STYLE, STRIP_INSTALLED_PRODUCT) 94 Вызванные изменения Статическое связывание
  95. Результат • Количество модулей не отражается на времени запуска •

    Поддержка ресурсов для статических модулей с помощью bundle • Размер приложения уменьшился на 30% • Количество аварийных завершений сократилось в 3 раза (в основном для устройств выпущенных 3-4 года назад) 95 Вызванные изменения Статическое связывание
  96. Выводы • Следите за вашим графом зависимостей • Не попадайтесь

    в ловушку, когда у других систем появляется линейная зависимость от количества модулей • Скорее всего, вам придется переключиться на статическое связывание • Мониторинг поможет избежать сюрпризов 96 Вызванные изменения
  97. МОНИТОРИНГ 97

  98. Почему и как мы стали отслеживать время сборки на рабочих

    станциях разработчиков и что мы узнали Мониторинг 98
  99. 99 У разработчиков весьма специфичные конфигурации для сборки проектов, и

    цифры для “чистой” сборки не дают полной картины Мониторинг Время сборки
  100. Мониторинг Время сборки 100

  101. Мониторинг Время сборки 101 Проблема

  102. 102 Медленно — не всегда аргумент за оптимизации Мониторинг Время

    сборки Нужно смотреть на картину в целом
  103. Мониторинг Время сборки 103

  104. 104 Повышайте качество жизни разработчиков в целом Мониторинг Время сборки

  105. Мониторинг Время сборки 105

  106. Как • Отдельное приложение • Мониторинг .xcactivitylog • Отслеживает только

    рабочие проекты • Отправляет данные во внутреннюю систему аналитики • По дороге в open-source 106 Мониторинг Время сборки
  107. Результат • Можем измерять воздействие изменений на разработчиков • Прямое

    сравнение между инкрементальными сборками и чистыми • Знаем, что улучшать • Быстрые результаты экспериментов 107 Мониторинг Время сборки
  108. Технические метрики в процессе модуляризации и где их взять Мониторинг

    108
  109. Время запуска приложения 109 Мониторинг Метрики Xcode

  110. Размер артефактов 110 Мониторинг Метрики

  111. Воздействие на инфраструктуру 111 Мониторинг Метрики TeamCity

  112. Итого • Не упускайте инфраструктуру • Метрики можно собирать и

    локально • Не можете измерить результат — не тратьте время 112 Мониторинг Метрики
  113. ЗАКЛЮЧЕНИЕ 113

  114. 25 Разработчиков 114 Заключение Команда iOS

  115. 25 Разработчиков 6 Команд 115 3 Человека в Core Team

    iOS Заключение Команда
  116. 25 Разработчиков 6 Команд 7 Приложений 116 3 Человека в

    Core Team iOS Заключение Команда
  117. 25 Разработчиков 6 Команд 7 Приложений 1.8м Строк кода 117

    3 Человека в Core Team iOS 400к Приложения 1.4м Модули Заключение Команда
  118. Заключение Историческая справка Кодовая база (Приложения против модулей) Строк кода

    325 000 650 000 975 000 1 300 000 А прель 2018 И ю ль 2018 О ктябрь 2018 Январь 2019 А прель 2019 И ю ль 2019 О ктябрь 2019 Январь 2020 Всего Приложения Модули 118
  119. Минусы • Усложнение процессов • Много проблем вскрывается в процессе

    интеграции • Дополнительные ресурсы на поддержку • Больше зависимостей между приложениями 119 Заключение Результаты
  120. Плюсы 120 Заключение Результаты • Гибкое масштабирование • Явные зоны

    ответственности • Благотворно сказывается на инфраструктуре • Улучшения в мониторинге
  121. Выводы 121 Заключение Результаты • Экспериментируйте xcconfig Явные зависимости Поддержка

    графа Процессы
  122. Выводы 122 Заключение Результаты • Экспериментируйте • Готовьте инфраструктуру xcconfig

    Явные зависимости Автоматизация Поддержка графа Непрерывная интеграция Умные тесты Процессы
  123. Выводы 123 Заключение Результаты • Экспериментируйте • Готовьте инфраструктуру •

    Анализируйте результаты xcconfig Явные зависимости Автоматизация Поддержка графа Непрерывная интеграция Умные тесты Процессы Статическое связавание Мониторинг Люди
  124. Дополнительно • UIGallery — шоурум всего UI, который стал возможен

    благодаря модуляризации • TestSupport модули — как мы храним фиктивные реализации, необходимые для модульных тестов • Swift vs Objective C — дружба с последствиями • Монорепо: путешествие обратно. История модуляризации в Badoo — Mobius 2018, Антон Щукин • Разработка производительного чата. Опыт Badoo — Mobius 2019, Антон Щукин Заключение 124
  125. СПАСИБО! bit.ly/2HiuN7f - Links tech.badoo.com/ru github.com/dive @justsitandgrin