- news_app – хранит данные приложения (приложением считать сервис по отправке новостей)
- endpoints – хранит логику роутеров
- all_news – роутер, возвращает все новости
- news_by_id – роутер, возвращает данные по конкретной новости
- support – хранит дополнительную логику роутеров
- models – модели Pydantic
- internal – внутренние модели, для подготовки данных (используются как data-classes, не отдаются пользователю)
- response – модели, которые отдаются пользователю
- all_news_response – модели для all_news
- news_by_id_response – модели для возврата по конкретной новости
- my_shiny_db – файлы json, имитирующие DB
- utils – дополнительные утилиты
- db_reader – логика чтения json-файлов
- env_setter – статический класс, задающий переменные окружения
- endpoints – хранит логику роутеров
- tests – тесты
- .env – переменные окружения (имитация данных для подключения к базе)
Стандартные роутеры для ловли запросы и формирования ответа и "сортировщики" – классы для подготовки данных для овтета.
Каждый endpoint имеет своего сортировщика (DataSorter и SpecificNewsDataSorter). Оба отнаследованы от ABSSorter, который является базовым классом (не интерфейс) для ликвидации дублирования кода. ABSSorter имеет потенциал для превращения в классический интерфейс, например endpoint'ы могли бы тыкать один метод в его наследниках, передавая какой-либо сигнал, распознаваемый фабрикой, которая бы отдавала нужного наследника... Но я не успел :|
Я предположил, что задание заключается в том, чтобы прочитать данные так, как они лежат в json-файлах. Если бы данные лежали в DB, то прочитать их можно было бы сразу в нужном виде, без необходимости сортировать вручную, и вычитать только требуемые, сразу указав это в SQL-запросе. Вместо этого логика подготовки данных перенесена в сортировщиков.
Если бы данные читались из DB, то такие задачи было бы удобно распараллелить (если бы запросов было несколько). Пока ждем один ответ - делаем второй. Вместо этого параллельные запросы к файла сымитированы параллельными, фактически они последовательные. Добиться настоящей параллельности все равно можно было бы, кажется есть библиотеки, умеющие читать файлы асинхронно, а также есть threading.Thread, который в данной ситуации смог бы без лишних трудностей отправить в OS 2 запроса на чтения данных и ждать ответа, что, вероятно, могло бы дать небольшой прирост скорости при чтении больших json-файлов. Но я не успел :|
Модели разбиты на внутренние и внешние. Первые задуманы для внутренней кухни (разбор и организация данных), вторые для отправки пользователю.
Тесты можно запускать по-одному, тыкая нужный файл, или все месте, запустив test_runner.py. Новые тесты полагается добавлять в test_runner.py вручную, если они пригодны для массового запуска.
Тестирование endpoint'ов отдельно не проводилось, так как протестирована их нижележащая логика, сам же endpoint принимает запрос и отдает ответ, чья логика (логика формирования ответа) протестирована.
- Python 3.10
- Windows 10
- Docstring format: Google-style
Внимание! Протестировано на Windows! Нет возможности развернуть виртуальную машины или протестировать Docker – материнская плата не поддерживает виртуализацию, Docker отказывается запускаться как явление.
Для запуска в режиме разработки – выполнить main.py в корне репозитория (НЕ в news_app.py!).
- При запуске на Linux нужно проверить корректность работы путей (слэши).
- При запуске на Linux нужно проверить, что datetime работает ожидаемо! Библиотека замечена в разности работы на Win/Lin
annotated-types==0.6.0 anyio==4.2.0 click==8.1.7 colorama==0.4.6 exceptiongroup==1.2.0 fastapi==0.109.0 h11==0.14.0 idna==3.6 pydantic==2.5.3 pydantic_core==2.14.6 sniffio==1.3.0 starlette==0.35.1 typing_extensions==4.9.0 uvicorn==0.26.0