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

Языки и технологии в нашем 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.
Что же могло пойти не так?

Кейс 1. Навигация в проекте
В начале проект писали два человека. Со временем команда подросла и встал вопрос, как ориентироваться в коде.
Проблемы:
-
Непонятно, что и где лежит.
-
common.pyна 10 тысяч строк. -
IDE не помогает найти нужные файлы.
-
Документации нет.
Эти проблемы могут привести к тому, что в какой-то момент возникнет дублирующий функционал, а новички начнут долго разбираться в проекте. А документацию никто писать не любит, плюс понятная документация — это трудно. А если существует часть проекта и его требуется ретроспективно задокументировать? Это уже задачка со звездочкой. В нашем кейсе проблемы подсветили новые коллеги — оказалось, что порог входа в проект очень высокий.
Что можно сделать:
-
Закоммититься на определенную структуру проекта.
-
Явно разделить функционал для общего использования и частного процесса.
-
Описать базовые классы того, что ожидается от фичи.
-
Начать вести документацию.
-
Придумать нейминг.
Первым делом мы выделили «ядро» проекта. Это центральная часть, которая часто переиспользуется и должна быть написана наиболее качественно. Провели глубокий рефакторинг этой части, определили базовые структуры для того, чтобы унифицировать разрабатываемые модули. Ввели понятную структуру в проекте для поддержки ETL-процессов, завязались на нашу архитектуру DWH (raw-, ods-, dds-, cdm-слои), и поиск нужных файлов свелся к логическим единицам — источник и таблица.

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

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

Кейс 3. Сложная схема зависимостей
В большом проекте возникает соблазн притянуть импорты из другого модуля и быстро решить проблему. Но подход может привести к тому, что возникнут сложные зависимости, которые будет сложно дебажить.
Проблемы:
-
Всегда нужно деплоить проект целиком.
-
Трудно вынести часть проекта в отдельную библиотеку.
-
Пакеты зависят друг от друга циклически для разных файлов.
Здесь помогает регулярный рефакторинг, когда нужно пересматривать актуальность текущего кода после изменения требований. Как вариант разрыва зависимостей — определение объектов для передачи в функцию/метод/класс.
Что можно сделать:
-
Переразбить проект на пакеты.
-
Провести код-ревью и груминг.
-
Заложить время на рефакторинг.

Кейс 4. А у меня локально запускается
Одна из частых проблем — запуск в разных средах и локальное тестирование. Существует риск, что среда будет отличаться от продакшена при тесте. А это может привести к непредсказуемым ошибкам.
Проблемы:
-
Разное поведение локально и на проде.
-
Неправильные подсказки от IDE.
Здесь спасает Docker. Все тесты и проверки работы приложения нужно тестировать в виртуальной сред, соответствующей проду.
Что можно сделать:
-
Сделать отдельное виртуальное окружение для проекта;
-
Запускать тесты только в Docker.

Я пролистал текст, о чем он был?
Изначально простой и маленький проект вырос в сложный, с которым работает много разработчиков. Стандарты работы с этой кодовой базой постоянно эволюционировали. А про те кейсы, которые задели струны в моей душе, я написал выше.
Главное, что стоит держать в голове, начиная большой проект на Python:
-
Промышленная разработка на Python — это сложно.
-
IDE ваш друг, используйте возможности по максимуму.
-
Есть много рекомендаций по тому, как писать код — лучше их изучить.
-
Не поскупитесь на автоматизацию, линтеры, хуки, документацию.
В итоге задача разработчика — знать о разных практиках, уметь оценить полезность для вашего конкретного проекта и иметь волю по их внедрению при необходимости. Даже если вы пишете на Python.

ссылка на оригинал статьи https://habr.com/ru/articles/706842/
Добавить комментарий