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.

329 lines
11 KiB
Markdown

# ADR-004 : Architecture Microservices Hybride
**Statut** : ✅ Accepté
**Date** : Octobre 2025
**Décideurs** : Équipe Architecture
**Tags** : `architecture`, `microservices`, `patterns`
---
## Contexte
Le système BricoLoc peut être architecturé de plusieurs façons :
- Architecture **monolithique** (comme le legacy)
- Architecture **en couches** (layered)
- Architecture **microservices**
- Architecture **hexagonale**
L'objectif est de démontrer la maîtrise de l'architecture logicielle en appliquant des **patterns modernes**.
### Options considérées
1. **Monolithe modulaire** (architecture en couches uniquement)
2. **Microservices purs** (services déployés séparément)
3. **Microservices hybride** (logiquement séparés, physiquement colocalisés)
4. **Architecture hexagonale** (ports & adapters)
---
## Décision
**Nous adoptons une architecture Microservices Hybride avec Clean Architecture interne**
**Hybride** signifie :
- **Logiquement** : 6 microservices distincts avec responsabilités claires
- **Physiquement** : Colocalisés dans le même déploiement Next.js (simplicité)
- **Évolutif** : Possibilité de séparer les déploiements si besoin
---
## Justification
### Pourquoi Microservices ?
#### 1. **Décomposition par Domaine Métier** 📦
Chaque microservice correspond à un **bounded context** :
| Microservice | Responsabilité | Bounded Context |
|--------------|----------------|-----------------|
| **Auth Service** | Authentification, autorisation | Identity & Access Management |
| **Catalogue Service** | Gestion outils, catégories, recherche | Product Catalog |
| **Reservation Service** | Réservations, planning | Booking Management |
| **Inventory Service** | Stocks, entrepôts, disponibilité | Inventory Management |
| **Payment Service** | Paiements, transactions | Payment Processing |
| **Notification Service** | Emails, notifications | Communication |
**Avantage** : Séparation claire des responsabilités (Single Responsibility Principle)
#### 2. **Autonomie** 🚀
Chaque microservice :
- A sa propre logique métier (domaine)
- Gère ses propres données (database per service - logique)
- Peut être développé indépendamment
- Peut évoluer sans impacter les autres
**Exemple** : Changement de la logique de pricing → uniquement Reservation Service touché
#### 3. **Scalabilité Ciblée** 📈
Possibilité de scaler uniquement les services sous charge :
- **Inventory Service** (beaucoup d'accès en temps réel) → scale horizontal
- Les autres restent à 1 instance
**Comparaison Legacy** : Monolithe = scale tout ou rien (coûteux)
#### 4. **Isolation des Pannes** 🛡️
Si un service tombe en panne, les autres continuent :
- **Payment Service down** → Catalogue et Recherche fonctionnent toujours
- **Graceful degradation** possible
**Comparaison Legacy** : Monolithe = single point of failure
#### 5. **Évolutivité Technologique** 🔧
Chaque microservice pourrait utiliser une techno différente :
- Catalogue Service → Node.js (si besoin d'ElasticSearch)
- Payment Service → Python (si ML pour fraude detection)
- Etc.
**Note** : Dans notre cas, tout est Next.js API Routes (simplicité), mais l'architecture permet l'évolution.
#### 6. **Démonstration Architecturale** 🏛️
C'est un **projet d'architecture logicielle** :
- Microservices = pattern architectural majeur
- Démontre la maîtrise de la décomposition
- Impressionnant pour un portfolio
---
### Pourquoi "Hybride" ? (Pas microservices purs)
#### Microservices Purs (Rejeté)
**Avantages** :
- Déploiement indépendant par service
- Technologies hétérogènes possibles
- Scaling précis
**Inconvénients** :
-**Complexité opérationnelle** (6 déploiements séparés)
-**Coûts** (6 instances minimum)
-**Latence réseau** (appels HTTP inter-services)
-**Debugging complexe** (logs distribués)
-**Overkill** pour projet académique
#### Microservices Hybride (Choisi)
**Principe** :
- Services logiquement séparés (code organisé en microservices)
- Physiquement colocalisés (même déploiement Next.js)
- Communication intra-process (pas HTTP externe)
**Avantages** :
-**Simplicité opérationnelle** (1 seul déploiement)
-**Performance** (pas de latence réseau)
-**Coûts réduits** (1 seule instance)
-**Debugging facile** (logs centralisés)
-**Démontre l'architecture** sans overhead
**Possibilité d'évolution** :
- Si besoin de scale → extraire un service en déploiement séparé
- Architecture prête pour ça (faible couplage)
---
### Clean Architecture Interne
Chaque microservice implémente **Clean Architecture** :
```
microservice/
├── domain/ # Couche Domaine
│ ├── entities/ # Entités métier
│ ├── value-objects/ # Value Objects
│ ├── repositories/ # Interfaces repositories
│ └── rules/ # Règles métier
├── application/ # Couche Application
│ ├── use-cases/ # Cas d'usage
│ ├── services/ # Services applicatifs
│ └── dtos/ # Data Transfer Objects
└── infrastructure/ # Couche Infrastructure
├── repositories/ # Implémentations (Supabase)
├── external-apis/ # APIs externes (Stripe)
└── events/ # Event Bus
```
**Bénéfices** :
- ✅ Testabilité maximale
- ✅ Indépendance des frameworks
- ✅ Maintenabilité
- ✅ Respect de SOLID
---
## Architecture Proposée
### Vue d'Ensemble
```
┌───────────────────────────────────────────────────┐
│ Client (Browser) - Next.js SSR │
└─────────────────────┬─────────────────────────────┘
┌─────────────────────▼─────────────────────────────┐
│ API Gateway / BFF (Next.js API) │
│ Orchestration & Aggregation │
└─┬──────┬───────┬───────┬───────┬────────┬────────┘
│ │ │ │ │ │
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌─────┐┌─────┐┌──────┐┌──────┐┌──────┐┌──────┐
│Auth ││Cata-││Reser-││Inven-││Pay- ││Noti- │
│Svc ││logue││vation││tory ││ment ││fica- │
│ ││Svc ││Svc ││Svc ││Svc ││tion │
│ ││ ││ ││ ││ ││Svc │
└──┬──┘└──┬──┘└───┬──┘└───┬──┘└───┬──┘└───┬──┘
│ │ │ │ │ │
│ │ │ │ │ │
└──────┴───────┴───────┴───────┴────────┘
┌──────▼──────┐
│ Event Bus │ (Supabase Realtime)
└──────┬──────┘
┌──────▼──────┐
│ Supabase │ (PostgreSQL + Auth + Storage)
└─────────────┘
```
### Communication
#### Synchrone (REST-like)
```typescript
// API Gateway appelle directement le service (même process)
const availability = await inventoryService.checkAvailability({
outilId,
entrepotId,
dateDebut,
dateFin
})
```
#### Asynchrone (Events)
```typescript
// Service émet un event via Event Bus (Supabase Realtime)
await eventBus.publish('reservation.confirmed', {
reservationId,
outilId,
entrepotId
})
// Autre service écoute l'event
eventBus.subscribe('reservation.confirmed', async (data) => {
await inventoryService.reserveStock(data)
})
```
---
## Conséquences
### ✅ Avantages
1. **Architecture claire** : Décomposition fonctionnelle évidente
2. **Maintenabilité** : Chaque service est focalisé et petit
3. **Testabilité** : Tests unitaires isolés par service
4. **Évolutivité** : Possibilité d'extraire un service si besoin
5. **Démonstration** : Montre la maîtrise de patterns avancés
6. **Simplicité opérationnelle** : 1 seul déploiement
7. **Performance** : Pas de latence réseau
### ⚠️ Complexités
1. **Structure du code** : Plus de dossiers et fichiers
2. **Communication** : Gérer Event Bus pour async
3. **Transactions distribuées** : Saga pattern si nécessaire
4. **Tests d'intégration** : Plus complexes
### 🛠️ Mitigations
- **Structure** : Documentation claire (README par service)
- **Communication** : Event Bus simple (Supabase Realtime)
- **Transactions** : Éviter si possible, ou Saga simplifié
- **Tests** : Focus sur tests unitaires par service
---
## Alternatives Rejetées
### ❌ Monolithe Modulaire (Couches uniquement)
**Raisons du rejet** :
- Moins impressionnant architecturalement
- Pas de décomposition fonctionnelle
- Moins adapté pour démonstration d'architecture
- Scaling "tout ou rien"
### ❌ Microservices Purs (Déploiements séparés)
**Raisons du rejet** :
- Trop complexe pour projet académique
- Coûts hébergement (6 instances)
- Overhead opérationnel
- Debugging distribué difficile
### ❌ Architecture Hexagonale Seule
**Raisons du rejet** :
- Pattern complémentaire (on l'utilise en interne)
- Moins "visible" que microservices
- Moins adapté pour comparaison avec legacy
---
## Migration vers Microservices Purs (Futur)
L'architecture permet d'extraire un service facilement :
**Étape 1** : Extraire Inventory Service (le plus sollicité)
```
Avant : Next.js (tout colocalisé)
Après : Next.js + Inventory Service (Node.js séparé)
```
**Changement minimal** :
- Remplacer appel direct par appel HTTP
- Déployer Inventory Service séparément
- Event Bus déjà en place (pas de changement)
**Couplage faible** ✅ → Migration facile
---
## Références
- [Microservices Pattern](https://microservices.io/)
- [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)
- [Domain-Driven Design](https://martinfowler.com/bliki/DomainDrivenDesign.html)
- [Bounded Context](https://martinfowler.com/bliki/BoundedContext.html)
- [Database per Service](https://microservices.io/patterns/data/database-per-service.html)
---
## Validations
- [x] Bounded contexts identifiés
- [x] 6 microservices définis
- [x] Communication sync/async définie
- [x] Clean Architecture par service validée
- [x] Event Bus (Supabase Realtime) testé
---
**Prochaine révision** : Si complexité trop élevée lors du développement