Добрый день, уважаемые читатели! Материал адресован всем специалистам, работающим с данными, которые решили написать первое веб-приложение. В данной публикации я не буду выкладывать листинги кода. На просторах Интернета есть масса практических примеров сборки сервисов, написанных на разных фреймворках. Но вот теоретических статей о логике процесса, архитектуре решения, а, главное, трудностях, с которыми впервые столкнется специалист, крайне мало. Я решил заполнить эту нишу и описать свой личный опыт, который кому-то может быть полезен.

 Специально для статьи я подготовил два идентичных примера на Flask и Dash и выложил их на GitHub. В них иллюстрируется расчет и вывод показателей юнит-экономики абстрактного IT-маркета, который называется Хабр (а почему бы и нет, ведь сейчас все компании начали заниматься электронной коммерцией:).

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

“ОПП: не умеешь – не берись!” Когда речь заходит об ОПП, мне почему-то автоматически вспоминается Django с его классами. Но если посмотреть работы начинающих data scientist-ов или аналитиков данных, то мы увидим совсем другую картину. Классы применяются ради самих классов. В данную структуру языка просто сливается весь код. За что отвечает этот “монстр”? За все! Как искать ошибки или переписывать код, не понятно. Лично у меня такое мнение на этот счет. Если не знаешь когда, как и почему следует применять ОПП, то лучше для небольших разработок использовать процедурно-функциональный стиль.

“Пусть безобразие, но единообразие. Даже если вы работаете один, разработайте единую систему формирования пространства имен. Это, во-первых, улучшит читаемость кода, а, во-вторых, ускорит его написание, так как не нужно вспоминать как именно названа функция на другой странице.

“Коммитим, даже если не пушим.” Даже если у вас нет GitHub аккаунта, заведите себе практику использовать систему контроля версий. Это реально удобно, так как позволяет производить эксперименты во вспомогательных ветках без создания дополнительных листов для тестирования гипотез. Я часто пренебрегаю данной рекомендацией, а зря.

“Муки выбора или о разных фреймворках замолвим слово.” Сочетание каких технологий можно использовать для создания собственного сервиса? Приведу несколько вариантов, которые сразу приходят на ум. Заранее прошу прощения, что обойду вниманием PHP, Ruby, C#:

  • Flask – статичные страницы с шаблонами HTML+CSS

  • Django – статичные страницы с шаблонами HTML+CSS

  • Flask Rest API/FastAPI/Django Rest Framework – динамические страницы HTML+CSS+фреймворк Javascript (Vue, React, Angular)

  • Dash (по сути работает Flask) – Dask (по сути работает React)

Как бы рассуждал я, если передо мной стоял выбор.

  • Нужно выводить таблицы, графики, интерактивные элементы здесь и сейчас – Dash

  • Нужно рендерить отдельные показатели на статичной странице. Есть время на эксперименты с дизайном, но нет помощи фронтенд-разработчика – Flask

  • Нужно выводить разноплановую информацию, нужна интерактивность. Есть много времени, есть ресурсы, плюс поддержка верстальщика и фронтенд-программиста – FastAPI – Vue.js

Теперь приведу скриншоты работ на Flask и Dash и сделаю несколько замечаний касательно данных платформ.

Задача состояла в том, что нужно было рассчитать, а потом отобразить 6 таблиц с показателями юнит-экономики, то есть сформировать веб-дашборд. Сразу скажу, что на разработку примеров я потратил примерно одинаковое время. Кардинального различия в результатах я не увидел, но есть нюансы.

В проекте Flask файл, который отвечает за вывод результатов, страницы html и фреймворк css это разные сущности. Документация по Bootstrap4 довольно качественная, но так как у меня нет навыков верстки, мне не удалось добиться корректного вывода всех сводных таблиц.

В проекте Dash за все операции отвечает единый файл, так как я выбрал вариант с хранением таблицы стилей в app.py. Если дашборд простой, то читаемость кода будет приемлемой. Но с ростом проекта с этим могут возникнуть трудности. Стили можно переместить в папку asset. Можно ли как-то еще раздробить основной файл я не знаю. Сразу из коробки имеется хорошая поддержка всех аналитических компонентов, включая таблицы, но нужно время для ознакомления со спецификой разработки.

“Архитектура всему голова.” Заранее продумывайте архитектуру своего приложения. Все файлы должны быть разнесены по модулям согласно их функционалу. При этом нужно стремиться к тому, чтобы, если изъять из сервиса часть модулей, остальная часть программы сохранила работоспособность. Компоненты должны спокойно интегрироваться в другой сервис с минимальными доработками. Переходим к моим ошибкам. Скрипты для запуска etl-процессов и расчета показателей лежат рядом с главным файлом проекта.

“Многофункциональности здесь не место.” В продолжение предыдущего пункта. Ваше приложение должно делать хорошо что-то одно. Мой сервис выполняет etl-команды, формирует БД, а затем наполняет ее записями и отвечает за вывод дашборда. Это три разных процесса, которые с большой долей вероятности в реальности будут разнесены во времени. И конечно, нужно убирать файл с данными из приложения, так как он только занимает место.

“Что SQL-запросом вытянешь, то и считать будешь.” Максимально перенесите расчетную нагрузку на сторону БД. При этом следует учитывать разности в диалектах sql. Старайтесь писать запросы максимально универсальными. Мои ошибки. База данных в качестве физического файла присутствует в проекте. В запросах имеются уникальные конструкции диалекта SQLite.

“Pandas мне друг, но производительность дороже.” Мне пришлось применить данную библиотеку, так требовалась именно сводная таблица, а получить ее на стороне БД проблематично. В большинстве случаев лучше обойтись только нативным Python.

“Не все то золото, что YAML-файл.” Идею применения yaml файла для хранения констант проекта я почерпнул из одного видео-ролика практикующего data scientist-а на Youtube. Что в этом плохого или хорошего я не знаю. Решать только вам.

“А не замахнуться ли нам на Docker.“ Небольшое лирическое отступление. Чего мне реально не хватает в Windows, так это Docker. В Windows 10 эту проблему решили, а вот в предыдущих версиях пользователям остается лишь устанавливать Docker Toolbox. Но в настоящее время разработка и поддержка данного продукта завершена, хотя архивный файл можно по-прежнему скачать на официальном аккаунте Docker на GitHub. Лично у меня по некоторым причинам установлен Windows 8.1, поэтому я задался вопросом, как еще можно заполучить в распоряжение эту программу. Установку второй операционной системы я отмел сразу, а вот вариант с виртуальной машиной меня заинтересовал. Для экономии ресурсов я выбрал Debian 10. Если выделить под нужды ВМ один процессор и три гигабайта оперативной памяти, то вполне можно тестировать свои идеи. Но стоит оговориться, что если захочется собрать и запустить контейнер с Apache Airflow, то указанных вычислительных мощностей будет недостаточно.

Теперь можно возвращаться к нашим приложениям. Как сбилдить и запустить контейнер я рассказывать не буду, так как данную информацию легко можно нагуглить в Интернете. Есть лишь пара моментов, на которых я заострю внимание. В процессе сборки будет выдаваться предупреждение о необходимости создания виртуального окружения внутри контейнера. Я решил пренебречь им, так как контейнер и так изолирован от рабочей среды Linux. И еще момент. После того, как приложение на Dash было упаковано в docker-контейнер, перестал отображаться логотип Хабра. Явной причины этого я быстро не нашел, а время, отведенное на эксперимент, было исчерпано.

“Семь раз проверь, один раз задеплой.” Завершить публикацию я решил на банальной ноте. А именно напомнить вам, о том, как важно проверять результаты перед сдачей. Пара досадных опечаток в комментариях, конечно, не поставят крест на всем проекте, но ведь может сложиться ситуация, что приложение просто не запуститься на демонстрации.

И вот вам конкретный пример. Я построил контейнер на Dash, а дашборд в браузере не отображается. В локальном варианте все было нормально. Оказалось, я просто забыл поменять в файле app.py хост с 127.0.0.1, на 0.0.0.0.

Вместо заключения. За скобками разговора остались моменты связанные с подготовкой проекта к развертыванию на сервере и непосредственно деплой. Пусть это будет вопросами для самостоятельного изучения или темой одной из будущих публикаций.

На этом все. Всем здоровья, удачи и профессиональных успехов!