5.1 KiB
5.1 KiB
Recherche & Décisions Techniques — Budget Tracker
Authentification
- Décision : JWT (tokens access 15min + refresh 7j) via
python-jose+passlib[bcrypt] - Rationale : stateless, compatible SPA React, aucune session serveur à gérer, facile à dockeriser
- Alternatives :
- Session cookies (plus simple mais couplé au serveur, complexe en CORS)
- OAuth2 externe / Keycloak (overkill pour usage personnel)
- FastAPI-Users (bibliothèque haut niveau — ajoute de la magie, préférence pour la transparence)
Base de données
- Décision : PostgreSQL 16
- Rationale : ACID natif (critique pour données financières), types UUID, ENUM, support transactionnel, standard de l'industrie
- Alternatives :
- SQLite (suffisant en dev, mais limité en concurrence et types)
- MySQL (moins bon support UUID/ENUM natif)
ORM & Migrations
- Décision : SQLAlchemy 2.0 (mode async) + Alembic
- Rationale : async natif pour FastAPI, migrations versionées et réversibles, mature et bien documenté
- Alternatives :
- Tortoise ORM (async natif mais moins mature, moins d'intégrations)
- SQLModel (wrapper SQLAlchemy+Pydantic — moins de contrôle sur les modèles)
- Prisma (Node.js uniquement)
Framework Backend
- Décision : FastAPI 0.111+
- Rationale : OpenAPI/Swagger auto-généré (conforme principe I de la Constitution), validation Pydantic intégrée, async natif, typage strict
- Alternatives :
- Django REST Framework (sync-first, plus lourd)
- Flask (pas d'async natif, validation manuelle)
Framework Frontend
- Décision : React 18 + TypeScript + Vite
- Rationale : écosystème riche, SPA adaptée à une app de gestion, typage fort réduit les erreurs sur les montants financiers
- Alternatives :
- Next.js (SSR inutile pour usage authentifié perso)
- Vue 3 (viable mais écosystème plus réduit)
Styling Frontend
- Décision : Tailwind CSS 3 + shadcn/ui
- Rationale : utilitaires CSS rapides, shadcn/ui fournit composants accessibles (formulaires, modales, tableaux) sans dépendance lourde
- Alternatives :
- MUI / Ant Design (plus lourds, style moins personnalisable)
- CSS Modules (trop verbeux pour une SPA)
Graphiques Frontend
- Décision : Recharts
- Rationale : composants React purs (pas de D3 direct), bon support responsive, Tailwind-compatible, léger (~180 ko gzip)
- Alternatives :
- Chart.js + react-chartjs-2 (moins idiomatic React, state management externe)
- Nivo (très complet mais plus lourd, over-engineering pour 2 types de graphiques)
- Victory (moins maintenu)
Gestion d'état Frontend
- Décision : TanStack Query (React Query) v5
- Rationale : cache serveur, invalidation automatique après mutations (soldes recalculés), gestion loading/error intégrée — évite un store global Redux pour des données essentiellement serveur
- Alternatives :
- Redux Toolkit (overkill, état global inutile si les données viennent de l'API)
- SWR (moins de fonctionnalités sur les mutations)
- Zustand (utile pour état local UI uniquement, complémentaire)
Export CSV
- Décision : module
csvPython stdlib - Rationale : aucune dépendance additionnelle, suffisant pour colonnes tabulaires de transactions, streaming possible via
StreamingResponseFastAPI - Alternatives :
- pandas (overkill, dépendance lourde)
Export PDF
- Décision : WeasyPrint
- Rationale : rendu HTML→PDF côté serveur, templates Jinja2 réutilisables, CSS support correct, rendu fidèle
- Alternatives :
- ReportLab (API bas niveau, verbeux pour des tableaux)
- pdfkit (dépendance système wkhtmltopdf, difficile à dockeriser)
- Reportlab + xhtml2pdf (moins stable)
Stockage des montants
- Décision : entiers en centimes (
amount_cents INTEGER) - Rationale : conforme au principe II de la Constitution — élimine toute erreur d'arrondi IEEE 754 sur les opérations financières (ex : 0.1 + 0.2 ≠ 0.3 en float)
- Règle : la conversion euros↔centimes se fait uniquement aux frontières (serialisation Pydantic et affichage React)
Soft Delete
- Décision : champ
deleted_at TIMESTAMP NULLsurTransactionetCategory - Rationale : conforme au principe II (tracabilité historique), permet l'audit et la restauration éventuelle
- Implémentation : filtre
WHERE deleted_at IS NULLsystématique dans les requêtes ; index partiel recommandé
Conteneurisation
- Décision : Docker Compose (backend + frontend + PostgreSQL)
- Rationale : conforme au principe V de la Constitution, reproductibilité dev/prod, un seul
docker compose up - Structure :
backend/— image Python 3.12-slimfrontend/— build Vite servi par Nginxdb/— PostgreSQL 16 officiel
Tests Backend
- Décision : pytest + httpx (client async) + pytest-asyncio + base de données de test dédiée
- Rationale : conforme au principe III (80% coverage services/), tests d'intégration sur vraie BDD (pas de mock SQLAlchemy)
- Alternatives :
- unittest (moins expressif)
- mocks SQLAlchemy (rejeté — risque de divergence mock/prod)