В DWH только Python

Вопреки названию, мы используем далеко не только Python. Но большой проект на любом языке требует к себе вдумчивый подход, особенно в плане учета особенностей языка и технологий. 

Пройдя все стадии от отрицания до принятия в программировании на Python, могу сказать, что он нам подошел. Но будет неправдой сказать, что нас обошли стороной трудности и проблемы, связанные с особенностями разработки. 

Про жизненные неурядицы и то, как мы их решали и продолжаем решать — об этом и немного об устройстве DWH в inDrive я и расскажу. А еще на примере кейсов разберу, что в проекте может пойти не так.

6f4e220aa3ff0461c97dabe167cc5225.png

Языки и технологии в нашем DWH

Наш DWH облачный и расположен в Google Cloud. Значительную часть технологий этой платформы мы используем для решения задач:

  • BigQuery.

  • Pub/Sub + Dataflow.

  • Dataproc.

  • Google Functions.

  • Composer.

Помимо этого, есть опенсорсные технологии, которые активно используем — Livy и Presto.

Языки нашей разработки можно представить в виде небольшой таблицы:  

Scala

SQL

Python

General-purpose язык.

Быстрый.

Имеет небольшую распространенность.

Поддерживается для многих систем обработки/хранения данных.

Скорость зависит от системы.

Очень распространен (основные конструкции).

General-purpose язык.

Не очень быстрый.

Очень распространен.

Подружить такое количество технологий с доставкой данных из API и бэкенда требует много усилий. Это выросло в целый проект, позволяющий автоматизировать выгрузки и сбор витрин данных. В качестве основного языка мы используем Python, в узких местах Scala. Проект, предоставляющий простой интерфейс для работы со сложными инструментами, мы назвали de-core.

Что же могло пойти не так?

83666016b89578e4df409c726b553cd0.png

Кейс 1. Навигация в проекте

В начале проект писали два человека. Со временем команда подросла и встал вопрос, как ориентироваться в коде. 

Проблемы:

  • Непонятно, что и где лежит.

  • common.py на 10 тысяч строк.

  • IDE не помогает найти нужные файлы.

  • Документации нет.

Эти проблемы могут привести к тому, что в какой-то момент возникнет дублирующий функционал, а новички начнут долго разбираться в проекте. А документацию никто писать не любит, плюс понятная документация — это трудно. А если существует часть проекта и его требуется ретроспективно задокументировать? Это уже задачка со звездочкой. В нашем кейсе проблемы подсветили новые коллеги — оказалось, что порог входа в проект очень высокий.

Что можно сделать:

  • Закоммититься на определенную структуру проекта.

  • Явно разделить функционал для общего использования и частного процесса.

  • Описать базовые классы того, что ожидается от фичи.

  • Начать вести документацию. 

  • Придумать нейминг.

Первым делом мы выделили «ядро» проекта. Это центральная часть, которая часто переиспользуется и должна быть написана наиболее качественно. Провели глубокий рефакторинг этой части, определили базовые структуры для того, чтобы унифицировать разрабатываемые модули. Ввели понятную структуру в проекте для поддержки ETL-процессов, завязались на нашу архитектуру DWH (raw-, ods-, dds-, cdm-слои), и поиск нужных файлов свелся к логическим единицам — источник и таблица.

Пример структуры для источникаПример структуры для источника

Кейс 2. Помоги себе сам

Больше человек в команде — больше работы с чужим кодом. Python часто используют для маленьких скриптов, где требования к коду ниже, так как сам скрипт легко влезает на экран. В большом проекте нужно писать код так, чтобы другой человек смог легко в нем разобраться.

Спор о необходимости типизации в PythonСпор о необходимости типизации в Python

Проблемы:

  • IDE не подсказывает методы класса.

  • Передал аргументы не того типа.

  • Нейминг функций/методов/переменных не всегда помогает.

Типизация помогает понять, что ожидает функция или метод, IDE может подсказать атрибуты и методы. А линтеры автоматически проверят эти ожидания. Мы также определили базовые классы как стандарт написания ETL. Поддержка интерфейса классов позволяет быстрее ориентироваться в чужом коде.

Что можно сделать:

  • Прописать типы.

  • Определить интерфейс ответа функции/метода.

  • Подготовить базовые классы.

  • Настроить линтеры и хуки.

Функция с типизацией и базовым классомФункция с типизацией и базовым классом

Кейс 3. Сложная схема зависимостей

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

Проблемы:

  • Всегда нужно деплоить проект целиком.

  • Трудно вынести часть проекта в отдельную библиотеку. 

  • Пакеты зависят друг от друга циклически для разных файлов.

Здесь помогает регулярный рефакторинг, когда нужно пересматривать актуальность текущего кода после изменения требований. Как вариант разрыва зависимостей — определение объектов для передачи в функцию/метод/класс.

Что можно сделать:

  • Переразбить проект на пакеты.

  • Провести код-ревью и груминг.

  • Заложить время на рефакторинг.

Можете ли вы позволить себе оформить часть проекта как отдельную библиотеку?Можете ли вы позволить себе оформить часть проекта как отдельную библиотеку?

Кейс 4. А у меня локально запускается

Одна из частых проблем — запуск в разных средах и локальное тестирование. Существует риск, что среда будет отличаться от продакшена при тесте. А это может привести к непредсказуемым ошибкам.

Проблемы:

Здесь спасает Docker. Все тесты и проверки работы приложения нужно тестировать в виртуальной сред, соответствующей проду.

Что можно сделать:

Вам тоже выдали новый MacBook с M1?Вам тоже выдали новый MacBook с M1?

Я пролистал текст, о чем он был?

Изначально простой и маленький проект вырос в сложный, с которым работает много разработчиков. Стандарты работы с этой кодовой базой постоянно эволюционировали. А про те кейсы, которые задели струны в моей душе, я написал выше.

Главное, что стоит держать в голове, начиная большой проект на Python:

  • Промышленная разработка на Python — это сложно.

  • IDE ваш друг, используйте возможности по максимуму.

  • Есть много рекомендаций по тому, как писать код — лучше их изучить.

  • Не поскупитесь на автоматизацию, линтеры, хуки, документацию.

В итоге задача разработчика — знать о разных практиках, уметь оценить полезность для вашего конкретного проекта и иметь волю по их внедрению при необходимости. Даже если вы пишете на Python.

ed0095be487de01ba7abbb023b2c0ec9.png

© Habrahabr.ru