Architecture Hexagonale
Fonrex respecte strictement l'Architecture Hexagonale (Ports et Adaptateurs) dans ses modules du domaine. Cela isole la logique métier des frameworks de transport (FastAPI), des ORM (SQLAlchemy) et des scrapers externes (yfinance, BeautifulSoup).
Organisation en Couches
┌──────────────────────────────────────────────────────────┐
│ Adapters (Outer Layer) │
│ ┌───────────────────┐ ┌───────────────────────┐ │
│ │ HTTP Routers │ │ SQLAlchemy ORM │ │
│ │ (FastAPI) │ │ (database/assets.py) │ │
│ └─────────┬─────────┘ └───────────▲───────────┘ │
└────────────┼──────────────────────────────┼──────────────┘
│ Implements Ports │
┌────────────▼──────────────────────────────┴──────────────┐
│ Application / Domain │
│ ┌───────────────────┐ ┌───────────────────────┐ │
│ │ Ports │ ◄──────┤ Use Cases │ │
│ │ (use_cases/ports) │ │ (use_cases/fundam...) │ │
│ └───────────────────┘ └───────────────────────┘ │
└──────────────────────────────────────────────────────────┘
Règles d'Architecture
-
use_cases/Directory Isolation:- MUST NOT import
fastapi,starlette,sqlalchemy,yfinance, orrequests. - MUST NOT handle HTTP status codes or DB connection pooling directly.
- Communicates exclusively via domain entities, dataclasses, and abstract Ports defined in
use_cases/ports.py.
- MUST NOT import
-
Abstract Ports (
use_cases/ports.py):FinancialsRepositoryPort: Contract for persisting fundamental snapshots.FinancialProviderPort: Interface abstraite pour les providers en amont (fetch(ticker, isin)).CachePort: Contract for key-value TTL operations.
-
Adapters (
routers/,database/,financials/):- Les routeurs HTTP (
routers/fundamentals.py) traduisent les paramètres de requête en objets d'entrée Use Case et capturent les exceptions du domaine (use_cases/errors.py) pour les associer aux codes de statut HTTP standards (404 Not Found,422 Unprocessable Entity).
- Les routeurs HTTP (
Table de Correspondance des Exceptions
Domain Exception (use_cases/errors.py) | HTTP Status Code (routers/errors.py) |
|---|---|
ResourceNotFound | 404 Not Found |
InvalidInput | 422 Unprocessable Entity |
DependencyUnavailable | 503 Service Unavailable |
UpstreamFailure | 502 Bad Gateway |