Upgrade to Pro — share decks privately, control downloads, hide ads and more …

«Итерационный подход в борьбе с legacy» — Алексей Коротин, SuperJob

Badoo Tech
February 15, 2020

«Итерационный подход в борьбе с legacy» — Алексей Коротин, SuperJob

Очередная встреча сообщества PHP-разработчиков в офисе Badoo.

«Легаси — неизбежное явление для любого крупного проекта, и SuperJob тут не исключение. Я расскажу о том, что вообще можно считать легаси, как мы последовательно боремся с ним в своём проекте и какие инструменты для этого используем.

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

Badoo Tech

February 15, 2020
Tweet

More Decks by Badoo Tech

Other Decks in Programming

Transcript

  1. Итерационный подход
    в борьбе с легаси
    Алексей Коротин
    Тимлид команды «Платформа»

    View Slide

  2. SuperJob — это:
    10 млн
    пользователей
    в месяц
    более
    30 млн
    резюме
    1.5 млн
    пользователей
    в сутки
    2

    View Slide

  3. Легаси в коде
    ● API
    ● Версионирование
    ● Борьба с легаси
    О чём поговорим
    3

    View Slide

  4. Легаси в коде
    ● API
    ● Версионирование
    ● Борьба с легаси
    О чём поговорим
    4
    Легаси в данных
    ● В БД
    ● В кэше

    View Slide

  5. Что такое легаси в коде?
    5

    View Slide

  6. «Легаси — это код без тестов»
    M. Feathers, Working Effectively with Legacy Code
    «Легаси — это код без поддержки»
    Wikipedia
    «Код становится легаси сразу»
    A. Hunt, D. Thomas, The Pragmatic Programmer
    6

    View Slide

  7. Монолит API-based app
    7

    View Slide

  8. Монолит
    Много
    кода
    Мало
    тестов
    8

    View Slide

  9. ● Переписать всё с нуля: дорого и долго
    Что делать?
    9

    View Slide

  10. ● Переписать всё с нуля: дорого и долго
    ● Покрыть всё тестами: лишняя работа
    Что делать?
    10

    View Slide

  11. Middleware
    11

    View Slide

  12. Applicant
    Legacy service 1
    Legacy service 2
    API
    Application
    Resume
    ...
    Vacancy
    Middleware
    12

    View Slide

  13. JSON:API
    Applicant.php
    Resume.php
    Vacancy.php
    applicant
    resume
    vacancy
    Code API
    13

    View Slide

  14. GET /applicant//
    14

    View Slide

  15. GET /applicant//
    Legacy service
    15

    View Slide

  16. Test 1
    Test 2
    Test 3
    GET /applicant//
    Legacy service
    16

    View Slide

  17. Test 1
    Test 2
    Test 3
    New service
    Legacy service GET /applicant//
    17

    View Slide

  18. А здесь происходит
    нечто зловещее
    Метод возвращает
    нужную нам модель
    18

    View Slide

  19. 19

    View Slide

  20. Наш будущий экшн
    Ограничиваем доступ
    20

    View Slide

  21. Id из роута
    Передаём результат
    работы сервиса в
    middleware
    21

    View Slide

  22. Версионирование
    22

    View Slide

  23. Версионирование через фичи
    Feature A
    Feature B
    Feature C
    Server Client
    Feature D
    Feature C
    Feature E
    Feature D
    Feature F
    23

    View Slide

  24. Версионирование через фичи
    Feature A
    Feature B
    Feature C
    Server Client
    Feature E
    Feature F
    Feature C
    Feature D
    Feature D
    24

    View Slide

  25. Версионирование через Git
    v1.0
    v1.1
    Git tags Server
    v2.0
    v1.0
    v1.1
    v2.0
    25

    View Slide

  26. Версионирование через боль
    или конструкции языка
    26

    View Slide

  27. Наш выбор
    Ёж Уж
    (вроде)
    +
    27

    View Slide

  28. Наш выбор
    +
    Циферки Фичи
    28

    View Slide

  29. Основные принципы
    Меняются сущности Версионируем конфиг
    29

    View Slide

  30. Основные принципы
    Меняются сущности Версионируем конфиг
    Меняются эндпоинты Версионируем роуты
    30

    View Slide

  31. Основные принципы
    Меняются сущности Версионируем конфиг
    Меняются эндпоинты Версионируем роуты
    Меняется логика Используем фичи
    31

    View Slide

  32. Структура конфигов
    config
    mapping
    routes.php
    applicant.yml
    ...
    Роуты API
    Маппинг для сущностей
    32

    View Slide

  33. Структура конфигов
    config
    mapping
    routes.php
    applicant.yml
    config
    1.0
    endpoints
    config.yml
    mapping
    applicant.yml
    2.0
    3.0
    33

    View Slide

  34. Структура конфигов
    config
    mapping
    routes.php
    applicant.yml
    config
    1.0
    endpoints
    config.yml
    mapping
    applicant.yml
    2.0
    3.0
    34

    View Slide

  35. Структура конфигов
    config
    1.0
    endpoints
    config.yml
    mapping
    applicant.yml
    2.0
    3.0
    config
    mapping
    routes.php
    applicant.yml
    35

    View Slide

  36. 36

    View Slide

  37. 37

    View Slide

  38. Добавляем
    фичу в enum
    38

    View Slide

  39. Новая версия
    Активируем фичу
    39

    View Slide

  40. Версионируемая логика изолирована
    и легко ищется
    40

    View Slide

  41. Профиты подхода
    ● Меньше кода: всё в конфигах
    41

    View Slide

  42. Профиты подхода
    ● Меньше кода: всё в конфигах
    ● Легко искать ненужное: код обёрнут фичами
    42

    View Slide

  43. Профиты подхода
    ● Меньше кода: всё в конфигах
    ● Легко искать ненужное: код обёрнут фичами
    ● Меньше рефакторить: можем удалять старый код
    43

    View Slide

  44. Легаси в БД
    44

    View Slide

  45. потеряли
    45

    View Slide

  46. Подозрительные таблицы
    ● Давно не менялись
    46

    View Slide

  47. Подозрительные таблицы
    ● Давно не менялись
    ● Давно не читались
    47

    View Slide

  48. Подозрительные таблицы
    ● Давно не менялись
    ● Давно не читались
    ● Таблица большая
    48

    View Slide

  49. Размер таблицы
    INFORMATION_SCHEMA
    TABLES
    DATA_LENGTH
    INDEX_LENGTH
    Сумма этих колонок даст
    примерный размер таблицы
    InnoDB
    49

    View Slide

  50. MySQL: PERFORMANCE_SCHEMA
    PERFORMANCE_SCHEMA
    table_io_waits_summary_by_table
    COUNT_READ
    COUNT_WRITE
    Количество чтений из таблицы
    Количество изменений таблицы
    (INSERT + UPDATE + DELETE)
    50

    View Slide

  51. TrackTableTimestampsCommand.php
    51

    View Slide

  52. table_io_waits_summary_by_table
    TrackTableTimestampsCommand.php
    52

    View Slide

  53. table_io_waits_summary_by_table table_timestamps
    TrackTableTimestampsCommand.php
    53

    View Slide

  54. MySQL (5.7+): sys schema
    sys
    schema_table_statistics
    rows_fetched
    rows_inserted
    Такое название хотя бы можно
    запомнить (нет)
    rows_updated
    rows_deleted
    54

    View Slide

  55. Percona/MariaDB: плагин userstat
    my.cnf: Runtime:
    или
    55

    View Slide

  56. Percona/MariaDB: плагин userstat
    INFORMATION_SCHEMA
    TABLE_STATISTICS
    ROWS_READ
    ROWS_CHANGED
    Таблица создаётся плагином
    Не PERFORMANCE_SCHEMA
    56

    View Slide

  57. Пример отчёта по таблицам
    57

    View Slide

  58. Пример отчёта по таблицам
    Логи постоянно пишутся,
    но читаются только при
    необходимости
    58

    View Slide

  59. Пример отчёта по таблицам
    Выглядит, как не до
    конца спиленная фича
    59

    View Slide

  60. Легаси в кэше?
    60

    View Slide

  61. Подозрительные кэши
    ● В кэш пишут, но не читают
    61

    View Slide

  62. Подозрительные кэши
    ● В кэш пишут, но не читают
    ● Кэш пытаются удалить, но не пишут
    62

    View Slide

  63. Подозрительные кэши
    ● В кэш пишут, но не читают
    ● Кэш пытаются удалить, но не пишут
    ● Часто обращаются к несуществующим ключам
    63

    View Slide

  64. Неймспейсы кэшей
    64

    View Slide

  65. Дэшборд по неймспейсу
    hit / miss, get / set, etc
    65

    View Slide

  66. Принцип построения графиков
    Слишком много промахов
    hit / miss < 1
    66

    View Slide

  67. Принцип построения графиков
    hit / miss > 1
    67

    View Slide

  68. AnalyzeCacheMetricsCommand.php
    68

    View Slide

  69. Grafana (Graphite)
    AnalyzeCacheMetricsCommand.php
    69

    View Slide

  70. Grafana (Graphite) Report
    AnalyzeCacheMetricsCommand.php
    70

    View Slide

  71. Пример отчёта по кэшам
    71

    View Slide

  72. Пример отчёта по кэшам
    Ссылка на дэшборд по
    неймспейсу
    Список найденных
    аномалий
    Неймспейс
    72

    View Slide

  73. 73
    Почти всё!

    View Slide

  74. 74
    Наши планы
    ● Автоматический поиск ненужного кода

    View Slide

  75. 75
    Наши планы
    ● Автоматический поиск ненужного кода
    ● Более детальный анализ данных

    View Slide

  76. 76
    Наши планы
    ● Автоматический поиск ненужного кода
    ● Более детальный анализ данных
    ● Обязательно что-нибудь ещё :)

    View Slide

  77. Спасибо!
    77

    View Slide