You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
977 lines
30 KiB
Markdown
977 lines
30 KiB
Markdown
# 🏛️ Architecture Logicielle - BricoLoc Evolution
|
|
|
|
> **Document de Référence Architecture**
|
|
> Version 1.0 - Octobre 2025
|
|
|
|
---
|
|
|
|
## 📋 Table des Matières
|
|
|
|
1. [Vue d'Ensemble](#vue-densemble)
|
|
2. [Principes Architecturaux](#principes-architecturaux)
|
|
3. [Patterns Utilisés](#patterns-utilisés)
|
|
4. [Architecture Legacy](#architecture-legacy)
|
|
5. [Architecture Moderne](#architecture-moderne)
|
|
6. [Comparaison Architecturale](#comparaison-architecturale)
|
|
7. [Décisions Techniques](#décisions-techniques)
|
|
8. [Qualités Architecturales](#qualités-architecturales)
|
|
|
|
---
|
|
|
|
## 🎯 Vue d'Ensemble
|
|
|
|
### Contexte
|
|
|
|
BricoLoc est une plateforme de location d'outils en ligne. L'application actuelle (Legacy) souffre de plusieurs problèmes architecturaux accumulés depuis 2013 :
|
|
|
|
- ❌ **Architecture monolithique** avec couplage fort
|
|
- ❌ **Logique métier éparpillée** (frontend, backend, base de données)
|
|
- ❌ **Maintenance difficile** (régressions fréquentes)
|
|
- ❌ **Performance dégradée** (temps de réponse > 3s)
|
|
- ❌ **Scalabilité limitée**
|
|
|
|
### Objectif
|
|
|
|
Démontrer une **refonte architecturale complète** en appliquant les **principes et patterns modernes** d'architecture logicielle.
|
|
|
|
### Approche
|
|
|
|
Création de **deux applications** côte à côte :
|
|
1. **Legacy** : Simulation du système actuel avec ses problèmes
|
|
2. **Moderne** : Nouvelle architecture avec résolution des problèmes
|
|
|
|
---
|
|
|
|
## 🏛️ Principes Architecturaux
|
|
|
|
### SOLID Principles
|
|
|
|
#### **S** - Single Responsibility Principle
|
|
> Une classe/module ne doit avoir qu'une seule raison de changer.
|
|
|
|
**Application** :
|
|
- Séparation claire entre couches (UI, Business Logic, Data)
|
|
- Composants React mono-responsabilité
|
|
- Services dédiés par domaine métier
|
|
|
|
#### **O** - Open/Closed Principle
|
|
> Ouvert à l'extension, fermé à la modification.
|
|
|
|
**Application** :
|
|
- Utilisation d'interfaces et abstractions
|
|
- Pattern Strategy pour comportements variables
|
|
- Plugins et extensions sans modifier le code existant
|
|
|
|
#### **L** - Liskov Substitution Principle
|
|
> Les classes dérivées doivent être substituables à leurs classes de base.
|
|
|
|
**Application** :
|
|
- Interfaces respectées par toutes les implémentations
|
|
- Repository pattern avec différentes sources de données
|
|
|
|
#### **I** - Interface Segregation Principle
|
|
> Les clients ne doivent pas dépendre d'interfaces qu'ils n'utilisent pas.
|
|
|
|
**Application** :
|
|
- Interfaces spécifiques par contexte
|
|
- Composants avec props minimales
|
|
|
|
#### **D** - Dependency Inversion Principle
|
|
> Dépendre des abstractions, pas des implémentations.
|
|
|
|
**Application** :
|
|
- Injection de dépendances
|
|
- Abstractions (interfaces) entre couches
|
|
|
|
---
|
|
|
|
### Clean Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────┐
|
|
│ UI Layer (React Components) │
|
|
│ - Pages, Components, Hooks │
|
|
└──────────────────┬──────────────────────────┘
|
|
│
|
|
┌──────────────────▼──────────────────────────┐
|
|
│ Application Layer (Use Cases) │
|
|
│ - Services, Business Logic │
|
|
└──────────────────┬──────────────────────────┘
|
|
│
|
|
┌──────────────────▼──────────────────────────┐
|
|
│ Domain Layer (Entities) │
|
|
│ - Models, Types, Business Rules │
|
|
└──────────────────┬──────────────────────────┘
|
|
│
|
|
┌──────────────────▼──────────────────────────┐
|
|
│ Infrastructure Layer (Data Sources) │
|
|
│ - Repositories, APIs, Database │
|
|
└─────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Règles** :
|
|
- Les dépendances pointent **vers l'intérieur**
|
|
- Le domaine ne dépend de rien
|
|
- L'infrastructure dépend du domaine (inversion)
|
|
|
|
---
|
|
|
|
### Separation of Concerns
|
|
|
|
Chaque partie du système a une **responsabilité claire** :
|
|
|
|
| Couche | Responsabilité | Exemples |
|
|
|--------|----------------|----------|
|
|
| **UI** | Présentation | Composants React, pages |
|
|
| **Application** | Orchestration | Services, use cases |
|
|
| **Domain** | Métier | Entities, business rules |
|
|
| **Infrastructure** | Technique | API calls, DB access |
|
|
|
|
---
|
|
|
|
## 🎨 Patterns Utilisés
|
|
|
|
### 1. Repository Pattern
|
|
|
|
**Objectif** : Abstraire l'accès aux données
|
|
|
|
```typescript
|
|
// Interface (Domain Layer)
|
|
interface OutilRepository {
|
|
findAll(filters?: OutilFilters): Promise<Outil[]>
|
|
findById(id: string): Promise<Outil | null>
|
|
create(outil: CreateOutilDTO): Promise<Outil>
|
|
update(id: string, data: UpdateOutilDTO): Promise<Outil>
|
|
delete(id: string): Promise<void>
|
|
}
|
|
|
|
// Implémentation (Infrastructure Layer)
|
|
class SupabaseOutilRepository implements OutilRepository {
|
|
constructor(private supabase: SupabaseClient) {}
|
|
|
|
async findAll(filters?: OutilFilters): Promise<Outil[]> {
|
|
// Implémentation Supabase
|
|
}
|
|
|
|
// ... autres méthodes
|
|
}
|
|
```
|
|
|
|
**Bénéfices** :
|
|
- ✅ Changement de source de données sans impact
|
|
- ✅ Tests facilités (mock du repository)
|
|
- ✅ Logique data isolée
|
|
|
|
---
|
|
|
|
### 2. Service Layer Pattern
|
|
|
|
**Objectif** : Centraliser la logique métier
|
|
|
|
```typescript
|
|
// Service Layer
|
|
class ReservationService {
|
|
constructor(
|
|
private reservationRepo: ReservationRepository,
|
|
private stockService: StockService,
|
|
private pricingService: PricingService
|
|
) {}
|
|
|
|
async createReservation(data: CreateReservationDTO): Promise<Reservation> {
|
|
// 1. Vérifier disponibilité
|
|
const isAvailable = await this.stockService.checkAvailability(
|
|
data.outilId,
|
|
data.entrepotId,
|
|
data.dateDebut,
|
|
data.dateFin
|
|
)
|
|
|
|
if (!isAvailable) {
|
|
throw new UnavailableError()
|
|
}
|
|
|
|
// 2. Calculer prix
|
|
const prix = await this.pricingService.calculate(data)
|
|
|
|
// 3. Créer réservation
|
|
const reservation = await this.reservationRepo.create({
|
|
...data,
|
|
prixTotal: prix
|
|
})
|
|
|
|
// 4. Mettre à jour stock
|
|
await this.stockService.reserve(data.outilId, data.entrepotId)
|
|
|
|
return reservation
|
|
}
|
|
}
|
|
```
|
|
|
|
**Bénéfices** :
|
|
- ✅ Logique métier centralisée et réutilisable
|
|
- ✅ Orchestration des opérations complexes
|
|
- ✅ Tests unitaires faciles
|
|
|
|
---
|
|
|
|
### 3. Dependency Injection
|
|
|
|
**Objectif** : Découpler les dépendances
|
|
|
|
```typescript
|
|
// Container DI (simplifié)
|
|
class ServiceContainer {
|
|
private static instance: ServiceContainer
|
|
|
|
private services = new Map<string, any>()
|
|
|
|
register<T>(key: string, factory: () => T): void {
|
|
this.services.set(key, factory)
|
|
}
|
|
|
|
resolve<T>(key: string): T {
|
|
const factory = this.services.get(key)
|
|
return factory()
|
|
}
|
|
}
|
|
|
|
// Enregistrement
|
|
container.register('outilRepository', () =>
|
|
new SupabaseOutilRepository(supabaseClient)
|
|
)
|
|
|
|
container.register('outilService', () =>
|
|
new OutilService(
|
|
container.resolve('outilRepository')
|
|
)
|
|
)
|
|
|
|
// Utilisation
|
|
const outilService = container.resolve<OutilService>('outilService')
|
|
```
|
|
|
|
---
|
|
|
|
### 4. Factory Pattern
|
|
|
|
**Objectif** : Créer des objets complexes
|
|
|
|
```typescript
|
|
class ReservationFactory {
|
|
static create(dto: CreateReservationDTO, user: User): Reservation {
|
|
return {
|
|
id: generateId(),
|
|
utilisateurId: user.id,
|
|
outilId: dto.outilId,
|
|
statut: 'en_attente_paiement',
|
|
createdAt: new Date(),
|
|
// ... autres champs calculés
|
|
}
|
|
}
|
|
|
|
static createFromLegacy(legacyData: any): Reservation {
|
|
// Adapter les anciennes données
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 5. Observer Pattern (Realtime)
|
|
|
|
**Objectif** : Réagir aux changements en temps réel
|
|
|
|
```typescript
|
|
// Supabase Realtime = Observer Pattern
|
|
const stockChannel = supabase
|
|
.channel('stocks')
|
|
.on('postgres_changes',
|
|
{
|
|
event: 'UPDATE',
|
|
schema: 'public',
|
|
table: 'stocks'
|
|
},
|
|
(payload) => {
|
|
// Notifier les observers (composants React)
|
|
updateStockCache(payload.new)
|
|
}
|
|
)
|
|
.subscribe()
|
|
```
|
|
|
|
---
|
|
|
|
## 🕰️ Architecture Legacy
|
|
|
|
### Vue d'Ensemble
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[Client Browser] --> B[Apache HTTP Reverse Proxy]
|
|
B --> C[Tomcat - Spring Framework Frontend]
|
|
C --> D[WebLogic - Java EE Backend]
|
|
D --> E[Oracle Database]
|
|
D --> F[MySQL Cache DB]
|
|
C --> F
|
|
|
|
G[Client Lourd Stocks] --> H[WCF Service]
|
|
H --> E
|
|
|
|
I[SAP ERP] --> J[Batch CSV]
|
|
J --> E
|
|
```
|
|
|
|
### Problèmes Architecturaux
|
|
|
|
#### 1. **Couplage Fort**
|
|
- Frontend accède directement à la BDD (court-circuite backend)
|
|
- Logique métier dans les procédures stockées PL/SQL
|
|
- Dépendance directe aux technologies (Oracle, WebLogic)
|
|
|
|
#### 2. **Monolithe Complexe**
|
|
- Tout dans une seule application
|
|
- Déploiement all-or-nothing
|
|
- Scaling vertical uniquement
|
|
|
|
#### 3. **Maintenance Difficile**
|
|
- Code spaghetti accumulé sur 10+ ans
|
|
- Tables avec 150+ colonnes
|
|
- Documentation obsolète
|
|
- Pas de tests automatisés
|
|
|
|
#### 4. **Performance**
|
|
- Synchronisation stocks quotidienne (décalage 24h)
|
|
- Pas de cache efficace
|
|
- Requêtes SQL non optimisées
|
|
|
|
---
|
|
|
|
## ⚡ Architecture Moderne
|
|
|
|
### Style Architectural : Microservices Hybride + Clean Architecture
|
|
|
|
L'architecture moderne combine :
|
|
- **Microservices** pour la décomposition fonctionnelle et l'autonomie
|
|
- **Clean Architecture** (couches) à l'intérieur de chaque microservice
|
|
- **API Gateway** pour l'orchestration
|
|
- **Event-Driven** pour la communication asynchrone
|
|
|
|
### Vue d'Ensemble - Architecture Microservices
|
|
|
|
```mermaid
|
|
graph TB
|
|
subgraph "Client Layer"
|
|
A[Web App - Next.js]
|
|
B[Mobile App - Future]
|
|
end
|
|
|
|
subgraph "API Gateway Layer"
|
|
C[API Gateway / BFF]
|
|
end
|
|
|
|
A --> C
|
|
B --> C
|
|
|
|
subgraph "Microservices Layer"
|
|
D[Auth Service<br/>Supabase Auth]
|
|
E[Catalogue Service<br/>Next.js API + Supabase]
|
|
F[Reservation Service<br/>Next.js API + Supabase]
|
|
G[Payment Service<br/>Next.js API + Stripe Mock]
|
|
H[Notification Service<br/>Next.js API + Resend]
|
|
I[Inventory Service<br/>Next.js API + Supabase Realtime]
|
|
end
|
|
|
|
C --> D
|
|
C --> E
|
|
C --> F
|
|
C --> G
|
|
C --> H
|
|
C --> I
|
|
|
|
subgraph "Data Layer"
|
|
J[(Supabase PostgreSQL<br/>+ Realtime)]
|
|
K[Cache - Redis/Supabase]
|
|
L[Storage - Supabase Storage]
|
|
end
|
|
|
|
E --> J
|
|
F --> J
|
|
I --> J
|
|
E --> K
|
|
F --> K
|
|
I --> L
|
|
|
|
subgraph "Event Bus"
|
|
M[Event Bus<br/>Supabase Realtime Channels]
|
|
end
|
|
|
|
F --> M
|
|
I --> M
|
|
M --> H
|
|
```
|
|
|
|
### Décomposition en Microservices
|
|
|
|
#### 🔐 **Auth Service** (Supabase Auth)
|
|
**Responsabilité** : Authentification et autorisation
|
|
- Inscription / Connexion
|
|
- Gestion des tokens JWT
|
|
- Gestion des rôles (RBAC)
|
|
- OAuth providers (Google, etc.)
|
|
|
|
**Technologies** : Supabase Auth (géré)
|
|
|
|
---
|
|
|
|
#### 📚 **Catalogue Service**
|
|
**Responsabilité** : Gestion du catalogue d'outils
|
|
- CRUD outils
|
|
- Recherche et filtrage
|
|
- Catégories
|
|
- Comparateur de prix
|
|
|
|
**API Endpoints** :
|
|
- `GET /api/catalogue/outils`
|
|
- `GET /api/catalogue/outils/:id`
|
|
- `GET /api/catalogue/categories`
|
|
- `POST /api/catalogue/search`
|
|
|
|
**Base de données** : Tables `outils`, `categories`, `outil_images`, `prix_comparatifs`
|
|
|
|
**Architecture interne** (Clean Architecture) :
|
|
```
|
|
catalogue-service/
|
|
├── domain/
|
|
│ ├── entities/
|
|
│ │ └── outil.entity.ts
|
|
│ └── repositories/
|
|
│ └── outil.repository.interface.ts
|
|
│
|
|
├── application/
|
|
│ ├── use-cases/
|
|
│ │ ├── get-outils.use-case.ts
|
|
│ │ └── search-outils.use-case.ts
|
|
│ └── services/
|
|
│ └── catalogue.service.ts
|
|
│
|
|
└── infrastructure/
|
|
├── repositories/
|
|
│ └── supabase-outil.repository.ts
|
|
└── api/
|
|
└── routes.ts
|
|
```
|
|
|
|
---
|
|
|
|
#### 📅 **Reservation Service**
|
|
**Responsabilité** : Gestion des réservations
|
|
- Création de réservations
|
|
- Vérification de disponibilité
|
|
- Calcul des prix
|
|
- Gestion du cycle de vie (en cours, terminée, annulée)
|
|
|
|
**API Endpoints** :
|
|
- `POST /api/reservations`
|
|
- `GET /api/reservations/:id`
|
|
- `GET /api/reservations/user/:userId`
|
|
- `PATCH /api/reservations/:id/cancel`
|
|
- `GET /api/reservations/check-availability`
|
|
|
|
**Base de données** : Table `reservations`
|
|
|
|
**Events émis** :
|
|
- `reservation.created`
|
|
- `reservation.confirmed`
|
|
- `reservation.cancelled`
|
|
|
|
**Architecture interne** :
|
|
```
|
|
reservation-service/
|
|
├── domain/
|
|
│ ├── entities/
|
|
│ │ └── reservation.entity.ts
|
|
│ ├── value-objects/
|
|
│ │ ├── date-range.vo.ts
|
|
│ │ └── price.vo.ts
|
|
│ └── rules/
|
|
│ └── availability.rule.ts
|
|
│
|
|
├── application/
|
|
│ ├── use-cases/
|
|
│ │ ├── create-reservation.use-case.ts
|
|
│ │ └── check-availability.use-case.ts
|
|
│ └── services/
|
|
│ ├── reservation.service.ts
|
|
│ └── pricing.service.ts
|
|
│
|
|
└── infrastructure/
|
|
├── repositories/
|
|
│ └── supabase-reservation.repository.ts
|
|
└── events/
|
|
└── reservation.events.ts
|
|
```
|
|
|
|
---
|
|
|
|
#### 📦 **Inventory Service**
|
|
**Responsabilité** : Gestion des stocks temps réel
|
|
- Stocks par entrepôt
|
|
- Disponibilité en temps réel
|
|
- Réservation temporaire de stock
|
|
- Synchronisation multi-entrepôts
|
|
|
|
**API Endpoints** :
|
|
- `GET /api/inventory/stocks/:outilId`
|
|
- `GET /api/inventory/entrepots/:entrepotId/stocks`
|
|
- `POST /api/inventory/reserve`
|
|
- `POST /api/inventory/release`
|
|
|
|
**Base de données** : Table `stocks`, `entrepots`
|
|
|
|
**Realtime** : Supabase Realtime pour push des mises à jour
|
|
|
|
**Events émis/écoutés** :
|
|
- Écoute : `reservation.confirmed` → Décrémente stock
|
|
- Écoute : `reservation.cancelled` → Libère stock
|
|
- Émet : `stock.updated`
|
|
|
|
---
|
|
|
|
#### 💳 **Payment Service**
|
|
**Responsabilité** : Gestion des paiements
|
|
- Intégration Stripe (simulée)
|
|
- Création de payment intent
|
|
- Confirmation de paiement
|
|
- Remboursements
|
|
|
|
**API Endpoints** :
|
|
- `POST /api/payment/create-intent`
|
|
- `POST /api/payment/confirm`
|
|
- `POST /api/payment/refund`
|
|
- `GET /api/payment/:id/status`
|
|
|
|
**Base de données** : Table `transactions` (logs)
|
|
|
|
**Events émis** :
|
|
- `payment.succeeded`
|
|
- `payment.failed`
|
|
|
|
---
|
|
|
|
#### 💬 **Notification Service**
|
|
**Responsabilité** : Notifications multi-canal
|
|
- Emails (Resend API)
|
|
- Notifications in-app
|
|
- SMS (futur)
|
|
|
|
**API Endpoints** :
|
|
- `POST /api/notifications/send`
|
|
- `GET /api/notifications/user/:userId`
|
|
|
|
**Events écoutés** :
|
|
- `reservation.created` → Email confirmation
|
|
- `payment.succeeded` → Email facture
|
|
- `stock.low` → Email admin
|
|
|
|
---
|
|
|
|
### Communication entre Microservices
|
|
|
|
#### 1. **Communication Synchrone** (REST)
|
|
Pour les opérations nécessitant une réponse immédiate :
|
|
|
|
```typescript
|
|
// Reservation Service appelle Inventory Service
|
|
const availability = await fetch('/api/inventory/check-availability', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ outilId, entrepotId, dateDebut, dateFin })
|
|
})
|
|
```
|
|
|
|
#### 2. **Communication Asynchrone** (Events)
|
|
Pour les opérations non-bloquantes :
|
|
|
|
```typescript
|
|
// Reservation Service émet un event
|
|
await eventBus.publish('reservation.confirmed', {
|
|
reservationId,
|
|
outilId,
|
|
entrepotId,
|
|
dateDebut,
|
|
dateFin
|
|
})
|
|
|
|
// Inventory Service écoute l'event
|
|
eventBus.subscribe('reservation.confirmed', async (data) => {
|
|
await inventoryService.reserveStock(data.outilId, data.entrepotId)
|
|
})
|
|
```
|
|
|
|
**Implémentation** : Supabase Realtime Channels (Pub/Sub)
|
|
|
|
---
|
|
|
|
### API Gateway / BFF (Backend For Frontend)
|
|
|
|
Le frontend Next.js agit comme **BFF (Backend For Frontend)** :
|
|
|
|
```typescript
|
|
// app/api/reservations/route.ts (API Gateway pattern)
|
|
export async function POST(request: Request) {
|
|
const data = await request.json()
|
|
|
|
// 1. Vérifier auth
|
|
const user = await authService.getCurrentUser()
|
|
|
|
// 2. Vérifier disponibilité (appel Inventory Service)
|
|
const isAvailable = await inventoryService.checkAvailability(data)
|
|
if (!isAvailable) {
|
|
return NextResponse.json({ error: 'Unavailable' }, { status: 400 })
|
|
}
|
|
|
|
// 3. Créer réservation (appel Reservation Service)
|
|
const reservation = await reservationService.create({
|
|
...data,
|
|
utilisateurId: user.id
|
|
})
|
|
|
|
// 4. Créer payment intent (appel Payment Service)
|
|
const paymentIntent = await paymentService.createIntent({
|
|
amount: reservation.prixTotal,
|
|
reservationId: reservation.id
|
|
})
|
|
|
|
return NextResponse.json({ reservation, paymentIntent })
|
|
}
|
|
```
|
|
|
|
**Avantages du BFF** :
|
|
- ✅ Agrégation de plusieurs microservices
|
|
- ✅ Réduction du nombre d'appels frontend
|
|
- ✅ Logique d'orchestration centralisée
|
|
- ✅ Adaptation au besoin du client (web, mobile)
|
|
|
|
---
|
|
|
|
### Architecture Hybride : Couches + Microservices
|
|
|
|
Chaque microservice implémente **Clean Architecture** en interne :
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ MICROSERVICE │
|
|
│ ┌─────────────────────────────────────────────────┐ │
|
|
│ │ API Layer (Controllers/Routes) │ │
|
|
│ └────────────────┬────────────────────────────────┘ │
|
|
│ │ │
|
|
│ ┌────────────────▼────────────────────────────────┐ │
|
|
│ │ Application Layer (Use Cases, Services) │ │
|
|
│ └────────────────┬────────────────────────────────┘ │
|
|
│ │ │
|
|
│ ┌────────────────▼────────────────────────────────┐ │
|
|
│ │ Domain Layer (Entities, Business Rules) │ │
|
|
│ └────────────────┬────────────────────────────────┘ │
|
|
│ │ │
|
|
│ ┌────────────────▼────────────────────────────────┐ │
|
|
│ │ Infrastructure (Repositories, DB, Events) │ │
|
|
│ └─────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Pourquoi Hybride ?**
|
|
- ✅ **Microservices** : Autonomie, scalabilité indépendante, équipes séparées
|
|
- ✅ **Clean Architecture** : Maintenabilité, testabilité, indépendance technologique
|
|
- ✅ **Best of both worlds**
|
|
|
|
### Structure des Dossiers - Architecture Microservices
|
|
|
|
```
|
|
apps/modern-app/
|
|
├── src/
|
|
│ ├── app/ # Next.js App Router (UI + BFF)
|
|
│ │ ├── (auth)/
|
|
│ │ ├── (main)/
|
|
│ │ └── api/ # API Gateway / BFF
|
|
│ │ ├── catalogue/ # Catalogue Service API
|
|
│ │ ├── reservations/ # Reservation Service API
|
|
│ │ ├── inventory/ # Inventory Service API
|
|
│ │ ├── payment/ # Payment Service API
|
|
│ │ └── notifications/ # Notification Service API
|
|
│ │
|
|
│ ├── components/ # UI Components (Presentation)
|
|
│ │
|
|
│ ├── services/ # Microservices (Business Logic)
|
|
│ │ ├── catalogue/
|
|
│ │ │ ├── domain/
|
|
│ │ │ │ ├── entities/
|
|
│ │ │ │ └── repositories/
|
|
│ │ │ ├── application/
|
|
│ │ │ │ ├── use-cases/
|
|
│ │ │ │ └── services/
|
|
│ │ │ └── infrastructure/
|
|
│ │ │ ├── repositories/
|
|
│ │ │ └── supabase/
|
|
│ │ │
|
|
│ │ ├── reservation/
|
|
│ │ │ ├── domain/
|
|
│ │ │ ├── application/
|
|
│ │ │ └── infrastructure/
|
|
│ │ │
|
|
│ │ ├── inventory/
|
|
│ │ │ ├── domain/
|
|
│ │ │ ├── application/
|
|
│ │ │ └── infrastructure/
|
|
│ │ │
|
|
│ │ ├── payment/
|
|
│ │ │ ├── domain/
|
|
│ │ │ ├── application/
|
|
│ │ │ └── infrastructure/
|
|
│ │ │
|
|
│ │ └── notification/
|
|
│ │ ├── domain/
|
|
│ │ ├── application/
|
|
│ │ └── infrastructure/
|
|
│ │
|
|
│ ├── shared/ # Code partagé entre services
|
|
│ │ ├── domain/ # Shared entities, value objects
|
|
│ │ ├── infrastructure/ # Shared utilities
|
|
│ │ └── events/ # Event Bus
|
|
│ │
|
|
│ ├── hooks/ # Custom React Hooks
|
|
│ └── types/ # TypeScript Types
|
|
```
|
|
|
|
**Remarque** : Chaque microservice suit Clean Architecture en interne (domain → application → infrastructure)
|
|
|
|
|
|
### Flux de Données - Architecture Microservices
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant U as User (UI)
|
|
participant BFF as API Gateway (BFF)
|
|
participant RS as Reservation Service
|
|
participant IS as Inventory Service
|
|
participant PS as Payment Service
|
|
participant EB as Event Bus
|
|
participant NS as Notification Service
|
|
participant DB as Supabase DB
|
|
|
|
U->>BFF: POST /api/reservations
|
|
|
|
BFF->>IS: Check Availability
|
|
IS->>DB: Query stocks
|
|
DB-->>IS: Stock data
|
|
IS-->>BFF: Available
|
|
|
|
BFF->>RS: Create Reservation
|
|
RS->>DB: Insert reservation
|
|
DB-->>RS: Reservation created
|
|
RS->>EB: Publish "reservation.created"
|
|
RS-->>BFF: Reservation object
|
|
|
|
BFF->>PS: Create Payment Intent
|
|
PS-->>BFF: Payment Intent
|
|
|
|
BFF-->>U: {reservation, paymentIntent}
|
|
|
|
EB->>IS: Event "reservation.created"
|
|
IS->>DB: Reserve stock
|
|
|
|
EB->>NS: Event "reservation.created"
|
|
NS->>U: Send confirmation email
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Comparaison Architecturale
|
|
|
|
### Styles Architecturaux
|
|
|
|
| Aspect | Legacy | Moderne |
|
|
|--------|--------|---------|
|
|
| **Style** | Monolithe | Microservices Hybride |
|
|
| **Frontend** | MVC (Spring) | SPA + BFF (Next.js) |
|
|
| **Backend** | Java EE (monolithe) | Microservices (Next.js API) |
|
|
| **Communication** | SOAP | REST + Events |
|
|
| **Déploiement** | Tout-en-un | Indépendant par service |
|
|
| **Scalabilité** | Verticale | Horizontale par service |
|
|
| **Architecture interne** | ❌ Aucune | Clean Architecture |
|
|
|
|
### Caractéristiques
|
|
|
|
| Aspect | Legacy | Moderne |
|
|
|--------|--------|---------|
|
|
| **Couplage** | Fort (direct DB access) | Faible (via interfaces) |
|
|
| **Cohésion** | Faible | Forte (services focalisés) |
|
|
| **Testabilité** | Difficile | Facile (isolation) |
|
|
| **Autonomie** | ❌ Aucune | ✅ Par service |
|
|
| **Résilience** | ❌ Single point of failure | ✅ Fault isolation |
|
|
| **Maintenance** | Complexe (tout lié) | Simple (services isolés) |
|
|
|
|
### Décomposition
|
|
|
|
| Critère | Legacy | Moderne |
|
|
|---------|--------|---------|
|
|
| **Granularité** | 1 application | 6 microservices |
|
|
| **Base de données** | 1 monolithe Oracle | Database per service (logique) |
|
|
| **Déploiement** | 1 artefact | 6 services indépendants |
|
|
| **Équipes** | 1 équipe | Possibilité d'équipes par service |
|
|
| **Technologies** | Uniformes | Polyglotte (si besoin) |
|
|
|
|
### Patterns
|
|
|
|
| Pattern | Legacy | Moderne |
|
|
|---------|--------|---------|
|
|
| **Microservices** | ❌ Non | ✅ Oui |
|
|
| **API Gateway / BFF** | ❌ Non | ✅ Oui |
|
|
| **Event-Driven** | ❌ Non | ✅ Oui (Supabase Realtime) |
|
|
| **Repository** | ❌ Non | ✅ Oui |
|
|
| **Service Layer** | ⚠️ Partiel | ✅ Oui |
|
|
| **Dependency Injection** | ❌ Non | ✅ Oui |
|
|
| **Clean Architecture** | ❌ Non | ✅ Oui (par service) |
|
|
| **SOLID** | ❌ Non | ✅ Oui |
|
|
| **CQRS** | ❌ Non | ⚠️ Partiel (read/write séparés) |
|
|
|
|
### Bénéfices de l'Architecture Microservices
|
|
|
|
#### ✅ Avantages
|
|
|
|
1. **Autonomie** : Chaque service peut être développé/déployé/scalé indépendamment
|
|
2. **Isolation des pannes** : Un service en panne n'affecte pas les autres
|
|
3. **Scalabilité ciblée** : Scale uniquement les services sous charge (ex: Inventory Service)
|
|
4. **Flexibilité technologique** : Possibilité d'utiliser différentes techs par service
|
|
5. **Équipes indépendantes** : Une équipe par service (futur)
|
|
6. **Déploiement continu** : Déploiement d'un service sans impact sur les autres
|
|
|
|
#### ⚠️ Complexités introduites
|
|
|
|
1. **Distributed system** : Gestion de la cohérence, latence réseau
|
|
2. **Observabilité** : Besoin de tracing distribué (logs, metrics)
|
|
3. **Transactions distribuées** : Saga pattern (si nécessaire)
|
|
4. **Tests d'intégration** : Plus complexes (inter-services)
|
|
|
|
**Mitigations appliquées** :
|
|
- ✅ Event-driven pour asynchrone (résilience)
|
|
- ✅ BFF pour agrégation (moins d'appels frontend)
|
|
- ✅ Supabase pour gestion centralisée de la data
|
|
- ✅ Next.js pour colocalisation (simplicité de déploiement)
|
|
|
|
### Métriques
|
|
|
|
| Métrique | Legacy | Moderne | Impact |
|
|
|----------|--------|---------|--------|
|
|
| **Complexité Cyclomatique** | ~35 | ~8 | -77% |
|
|
| **Couplage (afferent/efferent)** | ~15 | ~3 | -80% |
|
|
| **Lignes par fichier** | ~500 | ~150 | -70% |
|
|
| **Tests Coverage** | 0% | 80%+ | +∞ |
|
|
|
|
---
|
|
|
|
## 🎯 Décisions Techniques
|
|
|
|
Toutes les décisions architecturales majeures sont documentées dans les [ADR](./docs/architecture/ADR/).
|
|
|
|
### ADR Principaux
|
|
|
|
| # | Titre | Décision |
|
|
|---|-------|----------|
|
|
| [001](./docs/architecture/ADR/001-mono-repo.md) | Structure Mono-repo | pnpm workspaces |
|
|
| [002](./docs/architecture/ADR/002-framework-frontend.md) | Framework Frontend | Next.js 14 |
|
|
| [003](./docs/architecture/ADR/003-backend-supabase.md) | Backend & BDD | Supabase |
|
|
| [004](./docs/architecture/ADR/004-architecture-layers.md) | Architecture en Couches | Clean Architecture |
|
|
| [005](./docs/architecture/ADR/005-patterns.md) | Patterns | Repository + Service Layer |
|
|
|
|
---
|
|
|
|
## 🏆 Qualités Architecturales
|
|
|
|
### 1. Maintenabilité
|
|
|
|
**Legacy** : ⭐ (1/5)
|
|
- Code spaghetti
|
|
- Pas de séparation des responsabilités
|
|
- Documentation obsolète
|
|
|
|
**Moderne** : ⭐⭐⭐⭐⭐ (5/5)
|
|
- Code modulaire et propre
|
|
- Séparation claire des couches
|
|
- Documentation à jour
|
|
|
|
### 2. Testabilité
|
|
|
|
**Legacy** : ⭐ (1/5)
|
|
- Couplage fort = tests difficiles
|
|
- Pas de tests existants
|
|
- Dépendances sur BDD réelle
|
|
|
|
**Moderne** : ⭐⭐⭐⭐⭐ (5/5)
|
|
- Interfaces = mocking facile
|
|
- Tests unitaires isolés
|
|
- Tests d'intégration avec Supabase local
|
|
|
|
### 3. Scalabilité
|
|
|
|
**Legacy** : ⭐⭐ (2/5)
|
|
- Scaling vertical uniquement
|
|
- Monolithe = réplication complète
|
|
- Coûts exponentiels
|
|
|
|
**Moderne** : ⭐⭐⭐⭐⭐ (5/5)
|
|
- Scaling horizontal (Vercel)
|
|
- Supabase géré et scalable
|
|
- Coûts linéaires
|
|
|
|
### 4. Performance
|
|
|
|
**Legacy** : ⭐⭐ (2/5)
|
|
- Temps de réponse lents
|
|
- Pas de cache efficace
|
|
- Synchronisation différée
|
|
|
|
**Moderne** : ⭐⭐⭐⭐⭐ (5/5)
|
|
- SSR/SSG optimisés
|
|
- Cache intelligent (React Query)
|
|
- Temps réel (Supabase)
|
|
|
|
### 5. Sécurité
|
|
|
|
**Legacy** : ⭐⭐ (2/5)
|
|
- Hash MD5 (faible)
|
|
- SQL injection possible
|
|
- Pas de RLS
|
|
|
|
**Moderne** : ⭐⭐⭐⭐⭐ (5/5)
|
|
- JWT sécurisés (Supabase)
|
|
- Parameterized queries
|
|
- Row Level Security (RLS)
|
|
|
|
---
|
|
|
|
## 📚 Références
|
|
|
|
### Livres
|
|
- **Clean Architecture** - Robert C. Martin
|
|
- **Design Patterns** - Gang of Four
|
|
- **Domain-Driven Design** - Eric Evans
|
|
|
|
### Articles & Ressources
|
|
- [The Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)
|
|
- [SOLID Principles](https://en.wikipedia.org/wiki/SOLID)
|
|
- [Repository Pattern](https://martinfowler.com/eaaCatalog/repository.html)
|
|
|
|
---
|
|
|
|
## 🔄 Évolution
|
|
|
|
Ce document évolue avec le projet. Chaque décision architecturale majeure doit :
|
|
1. Être discutée en équipe
|
|
2. Faire l'objet d'un ADR
|
|
3. Être intégrée dans ce document
|
|
4. Être reflétée dans le code
|
|
|
|
---
|
|
|
|
*Document maintenu par : Équipe Architecture*
|
|
*Dernière révision : Octobre 2025*
|