1104 lines
25 KiB
Markdown
1104 lines
25 KiB
Markdown
|
|
# ORIGIN_ERROR_PATTERNS.md
|
||
|
|
|
||
|
|
## 📋 RÉSUMÉ EXÉCUTIF
|
||
|
|
|
||
|
|
Ce document catalogue **TOUS** les patterns d'erreurs identifiés dans le projet Veza pendant la Phase 0 (Error Resolution). Chaque pattern inclut la cause racine, la solution standard, et une checklist de prévention pour éviter sa réapparition dans les futures implémentations.
|
||
|
|
|
||
|
|
**Dernière mise à jour** : 2025-11-09
|
||
|
|
**Statut** : ✅ Document de référence officiel
|
||
|
|
**Version** : 1.0.0
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔒 RÈGLES IMMUABLES
|
||
|
|
|
||
|
|
1. **TOUJOURS consulter ce document** avant de commencer une nouvelle tâche
|
||
|
|
2. **TOUJOURS vérifier** qu'aucun pattern d'erreur ne sera introduit
|
||
|
|
3. **TOUJOURS documenter** tout nouveau pattern découvert
|
||
|
|
4. **JAMAIS contourner** une erreur sans la corriger définitivement
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 STATISTIQUES DES PATTERNS
|
||
|
|
|
||
|
|
| Catégorie | Patterns | Fréquence | Priorité |
|
||
|
|
|-----------|----------|-----------|----------|
|
||
|
|
| **Backend Go** | 5 | Haute | P0-P1 |
|
||
|
|
| **Frontend TypeScript** | 8 | Très Haute | P0-P2 |
|
||
|
|
| **Tests** | 6 | Haute | P1-P2 |
|
||
|
|
| **Configuration** | 3 | Moyenne | P0-P1 |
|
||
|
|
| **Lint/Format** | 4 | Haute | P2 |
|
||
|
|
|
||
|
|
**Total** : 26 patterns documentés
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. BACKEND GO - PATTERNS D'ERREURS
|
||
|
|
|
||
|
|
### PAT-001: Import Cycles (Circular Dependencies)
|
||
|
|
|
||
|
|
**Catégorie** : CAT-01 (Compilation)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Import cyclique détecté entre packages Go, empêchant la compilation.
|
||
|
|
|
||
|
|
**Pattern typique** :
|
||
|
|
```
|
||
|
|
package A imports package B
|
||
|
|
package B imports package C
|
||
|
|
package C imports package A ← CYCLE DÉTECTÉ
|
||
|
|
```
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```go
|
||
|
|
// ❌ ERREUR
|
||
|
|
// internal/services/user_service.go
|
||
|
|
package services
|
||
|
|
import "veza-backend-api/internal/handlers" // Import handlers
|
||
|
|
|
||
|
|
// internal/handlers/user_handlers.go
|
||
|
|
package handlers
|
||
|
|
import "veza-backend-api/internal/services" // Import services → CYCLE!
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Cause Racine
|
||
|
|
|
||
|
|
- Dépendances circulaires entre couches (handlers → services → handlers)
|
||
|
|
- Types partagés définis dans le mauvais package
|
||
|
|
- Interfaces définies dans les packages qui les utilisent
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
**Étape 1** : Identifier le cycle
|
||
|
|
```bash
|
||
|
|
cd veza-backend-api
|
||
|
|
go list -f '{{join .DepsErrors "\n"}}' ./... | grep -i "cycle"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Étape 2** : Créer package de types partagés
|
||
|
|
```go
|
||
|
|
// ✅ SOLUTION - Créer internal/types/interfaces.go
|
||
|
|
package types
|
||
|
|
|
||
|
|
// Interfaces définies dans package neutre
|
||
|
|
type UserRepository interface {
|
||
|
|
Create(user *User) error
|
||
|
|
FindByID(id uuid.UUID) (*User, error)
|
||
|
|
}
|
||
|
|
|
||
|
|
type UserService interface {
|
||
|
|
CreateUser(req *CreateUserRequest) (*User, error)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Étape 3** : Refactorer les packages
|
||
|
|
```go
|
||
|
|
// ✅ internal/services/user_service.go
|
||
|
|
package services
|
||
|
|
import "veza-backend-api/internal/types" // Import types seulement
|
||
|
|
|
||
|
|
type UserService struct {
|
||
|
|
repo types.UserRepository // Dépend de l'interface
|
||
|
|
}
|
||
|
|
|
||
|
|
// ✅ internal/handlers/user_handlers.go
|
||
|
|
package handlers
|
||
|
|
import "veza-backend-api/internal/types" // Import types seulement
|
||
|
|
|
||
|
|
func CreateUser(c *gin.Context) {
|
||
|
|
service := types.UserService // Utilise l'interface
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Vérifier qu'aucun import cycle ne sera créé avant d'ajouter un import
|
||
|
|
- [ ] Utiliser `go mod graph` pour visualiser les dépendances
|
||
|
|
- [ ] Définir les interfaces dans `internal/types/` ou `internal/interfaces/`
|
||
|
|
- [ ] Services ne doivent JAMAIS importer handlers
|
||
|
|
- [ ] Handlers ne doivent JAMAIS importer services directement
|
||
|
|
- [ ] Utiliser dependency injection via interfaces
|
||
|
|
|
||
|
|
#### Références
|
||
|
|
|
||
|
|
- **Documentation Go** : https://golang.org/ref/spec#Import_declarations
|
||
|
|
- **Best Practices** : Clean Architecture, Dependency Inversion Principle
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-002: Type Mismatches (string vs *string)
|
||
|
|
|
||
|
|
**Catégorie** : CAT-01 (Compilation)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Incohérence entre types `string` et `*string` (nullable) causant des erreurs de compilation.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```go
|
||
|
|
// ❌ ERREUR - internal/models/responses.go
|
||
|
|
type User struct {
|
||
|
|
FirstName string `json:"first_name"` // string (non-nullable)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (ur *UserResponse) FromUser(user *User) {
|
||
|
|
if user.FirstName != nil { // ❌ ERREUR: string ne peut pas être nil
|
||
|
|
ur.FirstName = *user.FirstName // ❌ ERREUR: déréférencement impossible
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Cause Racine
|
||
|
|
|
||
|
|
- Migration partielle de `*string` vers `string` (ou vice versa)
|
||
|
|
- Manque de cohérence dans la définition des modèles
|
||
|
|
- Changement de stratégie nullable/non-nullable non appliqué partout
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
**Option A : Utiliser string (non-nullable)**
|
||
|
|
```go
|
||
|
|
// ✅ SOLUTION A
|
||
|
|
type User struct {
|
||
|
|
FirstName string `json:"first_name,omitempty"` // string, jamais nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (ur *UserResponse) FromUser(user *User) {
|
||
|
|
if user.FirstName != "" { // ✅ Vérifier string vide
|
||
|
|
ur.FirstName = user.FirstName // ✅ Pas de déréférencement
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Option B : Utiliser *string (nullable)**
|
||
|
|
```go
|
||
|
|
// ✅ SOLUTION B
|
||
|
|
type User struct {
|
||
|
|
FirstName *string `json:"first_name,omitempty"` // *string, peut être nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (ur *UserResponse) FromUser(user *User) {
|
||
|
|
if user.FirstName != nil { // ✅ Vérifier nil
|
||
|
|
ur.FirstName = *user.FirstName // ✅ Déréférencement correct
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Recommandation** : Utiliser `string` avec valeur vide `""` pour les champs optionnels (plus simple, moins de pointeurs).
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Décider une stratégie cohérente : `string` ou `*string` pour champs optionnels
|
||
|
|
- [ ] Documenter la décision dans `ORIGIN_CODE_STANDARDS.md`
|
||
|
|
- [ ] Vérifier la cohérence des types avant de modifier un modèle
|
||
|
|
- [ ] Utiliser `go vet` pour détecter les incohérences
|
||
|
|
- [ ] Tests unitaires pour valider le comportement nullable/non-nullable
|
||
|
|
|
||
|
|
#### Références
|
||
|
|
|
||
|
|
- **Go Best Practices** : https://go.dev/doc/effective_go#pointers_vs_values
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-003: Missing Packages (Packages Not in std)
|
||
|
|
|
||
|
|
**Catégorie** : CAT-01 (Compilation)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Import de packages qui n'existent pas ou ne sont pas dans le module.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```go
|
||
|
|
// ❌ ERREUR
|
||
|
|
import "veza-backend-api/internal/api/search" // Package n'existe pas
|
||
|
|
import "veza-backend-api/internal/mocks" // Package n'existe pas
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Cause Racine
|
||
|
|
|
||
|
|
- Packages référencés mais jamais créés
|
||
|
|
- Imports non nettoyés après refactoring
|
||
|
|
- Packages déplacés/renommés sans mise à jour des imports
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
**Étape 1** : Identifier les packages manquants
|
||
|
|
```bash
|
||
|
|
cd veza-backend-api
|
||
|
|
go build ./... 2>&1 | grep "is not in std"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Étape 2** : Pour chaque package manquant, décider :
|
||
|
|
- **Option A** : Créer le package (si nécessaire pour la tâche)
|
||
|
|
- **Option B** : Retirer l'import (si non utilisé)
|
||
|
|
- **Option C** : Créer un stub minimal (si nécessaire pour compilation)
|
||
|
|
|
||
|
|
**Option A - Créer le package** :
|
||
|
|
```go
|
||
|
|
// ✅ Créer internal/api/search/handler.go
|
||
|
|
package search
|
||
|
|
|
||
|
|
import "github.com/gin-gonic/gin"
|
||
|
|
|
||
|
|
func SearchHandler(c *gin.Context) {
|
||
|
|
// Stub minimal pour permettre compilation
|
||
|
|
c.JSON(200, gin.H{"message": "Search endpoint - TODO: implement"})
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Option B - Retirer l'import** :
|
||
|
|
```go
|
||
|
|
// ✅ Retirer l'import non utilisé
|
||
|
|
// import "veza-backend-api/internal/api/search" ← SUPPRIMÉ
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Vérifier que tous les packages importés existent avant commit
|
||
|
|
- [ ] Nettoyer les imports non utilisés avec `goimports -w .`
|
||
|
|
- [ ] Créer les packages nécessaires AVANT de les importer
|
||
|
|
- [ ] Utiliser `go mod tidy` pour nettoyer les dépendances
|
||
|
|
- [ ] Vérifier avec `go build ./...` après chaque modification
|
||
|
|
|
||
|
|
#### Références
|
||
|
|
|
||
|
|
- **Go Modules** : https://go.dev/ref/mod
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-004: Missing Dependencies (go.mod)
|
||
|
|
|
||
|
|
**Catégorie** : CAT-03 (Dépendances)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Basse
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Dépendance Go manquante dans `go.mod`.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```go
|
||
|
|
// ❌ ERREUR
|
||
|
|
import "github.com/crewjam/saml/samlsp"
|
||
|
|
// Error: no required module provides package github.com/crewjam/saml/samlsp
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd veza-backend-api
|
||
|
|
go get github.com/crewjam/saml/samlsp
|
||
|
|
go mod tidy
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Vérifier que toutes les dépendances sont dans `go.mod`
|
||
|
|
- [ ] Utiliser `go mod tidy` régulièrement
|
||
|
|
- [ ] Documenter les nouvelles dépendances dans `ORIGIN_TECHNICAL_STACK.md`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-005: Undefined Types/Variables
|
||
|
|
|
||
|
|
**Catégorie** : CAT-01 (Compilation)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Basse
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Utilisation de types ou variables non définis.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```go
|
||
|
|
// ❌ ERREUR
|
||
|
|
// internal/database/chat_repository.go
|
||
|
|
var db *DB // Type DB non défini
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
- Vérifier que le type existe dans le package ou un package importé
|
||
|
|
- Importer le package contenant le type
|
||
|
|
- Créer le type si nécessaire
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Vérifier que tous les types utilisés sont définis
|
||
|
|
- [ ] Utiliser `go vet` pour détecter les problèmes
|
||
|
|
- [ ] IDE (VS Code/GoLand) devrait signaler les erreurs en temps réel
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. FRONTEND TYPESCRIPT/REACT - PATTERNS D'ERREURS
|
||
|
|
|
||
|
|
### PAT-006: Syntax Errors - Unterminated Regex
|
||
|
|
|
||
|
|
**Catégorie** : CAT-01 (Compilation)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Regex non terminée dans les tests, causant une erreur de syntaxe.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR - src/features/auth/hooks/useOAuthCallback.test.ts
|
||
|
|
expect(mockNavigate).toHaveBeenCalledWith('/dashboard/ // ← Guillemet manquant
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Cause Racine
|
||
|
|
|
||
|
|
- Copier-coller incomplet
|
||
|
|
- Erreur de frappe
|
||
|
|
- Éditeur qui n'a pas signalé l'erreur
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX
|
||
|
|
expect(mockNavigate).toHaveBeenCalledWith('/dashboard'); // Guillemet fermant ajouté
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Utiliser un linter en temps réel (ESLint dans VS Code)
|
||
|
|
- [ ] Vérifier la syntaxe avant de sauvegarder
|
||
|
|
- [ ] Utiliser `npm run type-check` avant commit
|
||
|
|
- [ ] Pre-commit hook devrait bloquer les erreurs de syntaxe
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-007: Syntax Errors - Unclosed JSX Tags
|
||
|
|
|
||
|
|
**Catégorie** : CAT-01 (Compilation)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Balises JSX non fermées, causant des erreurs de compilation.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR - src/features/playlists/components/PlaylistList.tsx
|
||
|
|
<div className="playlist-list">
|
||
|
|
{playlists.map(p => <Card>)} // ← Pas de </Card> ni </div>
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX
|
||
|
|
<div className="playlist-list">
|
||
|
|
{playlists.map(p => <Card key={p.id} />)} // Self-closing tag
|
||
|
|
</div> // Tag fermant ajouté
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Utiliser Prettier pour formater automatiquement
|
||
|
|
- [ ] Vérifier que tous les tags JSX sont fermés
|
||
|
|
- [ ] Utiliser l'extension React dans VS Code
|
||
|
|
- [ ] `tsc --noEmit` devrait détecter ces erreurs
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-008: Configuration Errors - vite.config.ts Type Issues
|
||
|
|
|
||
|
|
**Catégorie** : CAT-02 (Configuration)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Basse
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Incompatibilité de types dans la configuration Vite.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR - vite.config.ts
|
||
|
|
build: {
|
||
|
|
terserOptions: {
|
||
|
|
compress: {
|
||
|
|
drop_console: true, // Type incompatibilité
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
**Option A - Utiliser esbuild (recommandé)** :
|
||
|
|
```typescript
|
||
|
|
// ✅ SOLUTION A
|
||
|
|
build: {
|
||
|
|
minify: 'esbuild', // Plus moderne, plus rapide
|
||
|
|
// Pas besoin de terserOptions
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Option B - Corriger terserOptions** :
|
||
|
|
```typescript
|
||
|
|
// ✅ SOLUTION B
|
||
|
|
build: {
|
||
|
|
minify: 'terser',
|
||
|
|
terserOptions: {
|
||
|
|
compress: {
|
||
|
|
drop_console: process.env.NODE_ENV === 'production',
|
||
|
|
},
|
||
|
|
} as any, // Type assertion si nécessaire
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Utiliser esbuild au lieu de terser (plus moderne)
|
||
|
|
- [ ] Vérifier la compatibilité des types avec `tsc --noEmit`
|
||
|
|
- [ ] Consulter la documentation Vite pour les types corrects
|
||
|
|
- [ ] Tester le build après modification de la config
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-009: Type Errors - Missing Type Definitions
|
||
|
|
|
||
|
|
**Catégorie** : CAT-01 (Compilation)
|
||
|
|
**Priorité** : P1 (Haute)
|
||
|
|
**Fréquence** : Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Types TypeScript manquants ou incorrects.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR
|
||
|
|
const user: User = { // Type User non défini
|
||
|
|
id: '123',
|
||
|
|
name: 'John'
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX - Définir le type
|
||
|
|
interface User {
|
||
|
|
id: string;
|
||
|
|
name: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
const user: User = {
|
||
|
|
id: '123',
|
||
|
|
name: 'John'
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Toujours définir les types avant utilisation
|
||
|
|
- [ ] Utiliser `strict: true` dans `tsconfig.json`
|
||
|
|
- [ ] Éviter `any` (utiliser `unknown` si nécessaire)
|
||
|
|
- [ ] Vérifier avec `tsc --noEmit --strict`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-010: Lint Errors - Unused Variables
|
||
|
|
|
||
|
|
**Catégorie** : CAT-07 (Lint/Format)
|
||
|
|
**Priorité** : P2 (Moyenne)
|
||
|
|
**Fréquence** : Très Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Variables déclarées mais jamais utilisées.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR
|
||
|
|
const user = getUser(); // Variable déclarée mais non utilisée
|
||
|
|
console.log('Hello');
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
**Option A - Supprimer la variable** :
|
||
|
|
```typescript
|
||
|
|
// ✅ SOLUTION A
|
||
|
|
// const user = getUser(); ← Supprimé
|
||
|
|
console.log('Hello');
|
||
|
|
```
|
||
|
|
|
||
|
|
**Option B - Préfixer avec underscore** :
|
||
|
|
```typescript
|
||
|
|
// ✅ SOLUTION B - Si la variable sera utilisée plus tard
|
||
|
|
const _user = getUser(); // Préfixe _ indique intentionnellement non utilisé
|
||
|
|
console.log('Hello');
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Supprimer les variables non utilisées
|
||
|
|
- [ ] Utiliser `npm run lint -- --fix` pour auto-fix
|
||
|
|
- [ ] Configurer ESLint pour signaler en temps réel
|
||
|
|
- [ ] Pre-commit hook devrait bloquer les erreurs lint
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-011: Lint Errors - Console Statements
|
||
|
|
|
||
|
|
**Catégorie** : CAT-07 (Lint/Format)
|
||
|
|
**Priorité** : P2 (Moyenne)
|
||
|
|
**Fréquence** : Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Utilisation de `console.log` en production (interdit par lint rules).
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR
|
||
|
|
console.log('Debug info'); // no-console rule
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
**Option A - Supprimer en production** :
|
||
|
|
```typescript
|
||
|
|
// ✅ SOLUTION A
|
||
|
|
if (process.env.NODE_ENV === 'development') {
|
||
|
|
console.log('Debug info');
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Option B - Utiliser un logger** :
|
||
|
|
```typescript
|
||
|
|
// ✅ SOLUTION B
|
||
|
|
import { logger } from '@/utils/logger';
|
||
|
|
logger.debug('Debug info'); // Logger gère l'environnement
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Ne pas utiliser `console.log` en production
|
||
|
|
- [ ] Utiliser un logger configuré
|
||
|
|
- [ ] ESLint devrait bloquer `console.*` en production
|
||
|
|
- [ ] Vite supprime automatiquement les console en build production
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-012: Lint Errors - Any Types
|
||
|
|
|
||
|
|
**Catégorie** : CAT-07 (Lint/Format)
|
||
|
|
**Priorité** : P2 (Moyenne)
|
||
|
|
**Fréquence** : Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Utilisation de `any` au lieu de types spécifiques.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR
|
||
|
|
function processData(data: any) { // any interdit
|
||
|
|
return data.value;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX - Typer correctement
|
||
|
|
interface Data {
|
||
|
|
value: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
function processData(data: Data) {
|
||
|
|
return data.value;
|
||
|
|
}
|
||
|
|
|
||
|
|
// OU utiliser unknown si le type est vraiment inconnu
|
||
|
|
function processData(data: unknown) {
|
||
|
|
if (typeof data === 'object' && data !== null && 'value' in data) {
|
||
|
|
return (data as { value: string }).value;
|
||
|
|
}
|
||
|
|
throw new Error('Invalid data');
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Éviter `any` (utiliser `unknown` si nécessaire)
|
||
|
|
- [ ] Typer toutes les fonctions et variables
|
||
|
|
- [ ] Utiliser `strict: true` dans `tsconfig.json`
|
||
|
|
- [ ] ESLint devrait bloquer `any` explicit
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-013: Missing Return Types
|
||
|
|
|
||
|
|
**Catégorie** : CAT-07 (Lint/Format)
|
||
|
|
**Priorité** : P2 (Moyenne)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Fonctions sans type de retour explicite.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR
|
||
|
|
function getUser(id: string) { // Type de retour manquant
|
||
|
|
return { id, name: 'John' };
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX
|
||
|
|
interface User {
|
||
|
|
id: string;
|
||
|
|
name: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getUser(id: string): User { // Type de retour explicite
|
||
|
|
return { id, name: 'John' };
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Toujours typer le retour des fonctions
|
||
|
|
- [ ] Utiliser `@typescript-eslint/explicit-function-return-type`
|
||
|
|
- [ ] TypeScript peut inférer, mais explicite est mieux
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. TESTS - PATTERNS D'ERREURS
|
||
|
|
|
||
|
|
### PAT-014: Test Failures - Missing Mocks
|
||
|
|
|
||
|
|
**Catégorie** : CAT-05 (Tests)
|
||
|
|
**Priorité** : P1 (Haute)
|
||
|
|
**Fréquence** : Très Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Tests échouent car les mocks ne sont pas configurés.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR
|
||
|
|
it('should fetch user', async () => {
|
||
|
|
const user = await userService.getUser('123'); // userService non mocké
|
||
|
|
expect(user).toBeDefined();
|
||
|
|
});
|
||
|
|
// Error: Cannot read property 'data' of undefined
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX
|
||
|
|
import { vi } from 'vitest';
|
||
|
|
|
||
|
|
vi.mock('@/services/user', () => ({
|
||
|
|
userService: {
|
||
|
|
getUser: vi.fn().mockResolvedValue({ id: '123', name: 'John' })
|
||
|
|
}
|
||
|
|
}));
|
||
|
|
|
||
|
|
it('should fetch user', async () => {
|
||
|
|
const user = await userService.getUser('123');
|
||
|
|
expect(user).toBeDefined();
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Toujours mocker les dépendances externes
|
||
|
|
- [ ] Utiliser `vi.mock()` pour les modules
|
||
|
|
- [ ] Configurer les mocks dans `beforeEach` si réutilisés
|
||
|
|
- [ ] Vérifier que les mocks correspondent aux vrais services
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-015: Test Failures - React act() Warnings
|
||
|
|
|
||
|
|
**Catégorie** : CAT-05 (Tests)
|
||
|
|
**Priorité** : P2 (Moyenne)
|
||
|
|
**Fréquence** : Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Avertissements React `act()` dans les tests.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ WARNING
|
||
|
|
Warning: An update to Component inside a test was not wrapped in act(...).
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX
|
||
|
|
import { act, render, screen } from '@testing-library/react';
|
||
|
|
|
||
|
|
it('should update state', async () => {
|
||
|
|
render(<Component />);
|
||
|
|
|
||
|
|
await act(async () => {
|
||
|
|
fireEvent.click(screen.getByRole('button'));
|
||
|
|
await waitFor(() => {
|
||
|
|
expect(screen.getByText('Updated')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Utiliser `act()` pour les mises à jour d'état
|
||
|
|
- [ ] Utiliser `waitFor()` pour les mises à jour asynchrones
|
||
|
|
- [ ] `@testing-library/react` gère `act()` automatiquement dans la plupart des cas
|
||
|
|
- [ ] Vérifier les warnings dans les logs de tests
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-016: Test Failures - WebSocket Mocking Issues
|
||
|
|
|
||
|
|
**Catégorie** : CAT-05 (Tests)
|
||
|
|
**Priorité** : P1 (Haute)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Problèmes de mock WebSocket dans les tests.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR
|
||
|
|
TypeError: realWebSocket.addEventListener is not a function
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX - Mocker WebSocket globalement
|
||
|
|
global.WebSocket = class MockWebSocket {
|
||
|
|
addEventListener = vi.fn();
|
||
|
|
removeEventListener = vi.fn();
|
||
|
|
send = vi.fn();
|
||
|
|
close = vi.fn();
|
||
|
|
readyState = WebSocket.OPEN;
|
||
|
|
} as any;
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Mocker WebSocket dans `setupTests.ts`
|
||
|
|
- [ ] Utiliser une bibliothèque de mock WebSocket si nécessaire
|
||
|
|
- [ ] Tester les connexions WebSocket séparément
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-017: Test Failures - Outdated Assertions
|
||
|
|
|
||
|
|
**Catégorie** : CAT-05 (Tests)
|
||
|
|
**Priorité** : P1 (Haute)
|
||
|
|
**Fréquence** : Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Assertions de tests obsolètes après changement d'API.
|
||
|
|
|
||
|
|
**Exemple réel** :
|
||
|
|
```typescript
|
||
|
|
// ❌ ERREUR - API changée
|
||
|
|
expect(result).toEqual({ success: true });
|
||
|
|
// API retourne maintenant: { status: 'success', data: {...} }
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX - Adapter aux nouveaux contracts
|
||
|
|
expect(result).toEqual({
|
||
|
|
status: 'success',
|
||
|
|
data: expect.objectContaining({
|
||
|
|
id: expect.any(String),
|
||
|
|
name: expect.any(String),
|
||
|
|
})
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Mettre à jour les tests lors de changement d'API
|
||
|
|
- [ ] Utiliser des matchers flexibles (`expect.objectContaining`)
|
||
|
|
- [ ] Contract testing pour valider les APIs
|
||
|
|
- [ ] Snapshot testing pour détecter les changements
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-018: Test Failures - Missing Test Data
|
||
|
|
|
||
|
|
**Catégorie** : CAT-05 (Tests)
|
||
|
|
**Priorité** : P1 (Haute)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Tests échouent car les données de test sont manquantes.
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ FIX - Créer fixtures
|
||
|
|
// tests/fixtures/users.ts
|
||
|
|
export const testUsers = {
|
||
|
|
normalUser: {
|
||
|
|
id: 'user-123',
|
||
|
|
email: 'user@example.com',
|
||
|
|
name: 'Test User',
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
// test
|
||
|
|
import { testUsers } from '@/tests/fixtures/users';
|
||
|
|
it('should work', () => {
|
||
|
|
const user = testUsers.normalUser;
|
||
|
|
// ...
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Créer des fixtures réutilisables
|
||
|
|
- [ ] Centraliser les données de test
|
||
|
|
- [ ] Utiliser des factories pour générer des données
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-019: Test Coverage Below Threshold
|
||
|
|
|
||
|
|
**Catégorie** : CAT-05 (Tests)
|
||
|
|
**Priorité** : P1 (Haute)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Couverture de tests en dessous du seuil de 80%.
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
- Identifier le code non testé
|
||
|
|
- Écrire des tests pour les branches manquantes
|
||
|
|
- Utiliser `--coverage` pour voir les détails
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Maintenir coverage ≥ 80%
|
||
|
|
- [ ] CI/CD devrait bloquer si coverage < 80%
|
||
|
|
- [ ] Écrire les tests en même temps que le code (TDD)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. CONFIGURATION - PATTERNS D'ERREURS
|
||
|
|
|
||
|
|
### PAT-020: Missing Environment Variables
|
||
|
|
|
||
|
|
**Catégorie** : CAT-02 (Configuration)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Basse
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Variables d'environnement manquantes.
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
- Documenter toutes les variables requises dans `.env.example`
|
||
|
|
- Valider les variables au démarrage
|
||
|
|
- Utiliser des valeurs par défaut si approprié
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Documenter toutes les variables dans `.env.example`
|
||
|
|
- [ ] Valider les variables au démarrage
|
||
|
|
- [ ] Utiliser `dotenv` pour charger les variables
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-021: Docker Configuration Errors
|
||
|
|
|
||
|
|
**Catégorie** : CAT-06 (Docker)
|
||
|
|
**Priorité** : P0 (Critique)
|
||
|
|
**Fréquence** : Basse
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Erreurs de syntaxe YAML dans `docker-compose.yml`.
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
- Valider la syntaxe YAML avec `docker-compose config`
|
||
|
|
- Vérifier l'indentation (espaces, pas tabs)
|
||
|
|
- Utiliser un validateur YAML
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Valider `docker-compose.yml` avant commit
|
||
|
|
- [ ] Utiliser 2 espaces pour l'indentation
|
||
|
|
- [ ] Vérifier les guillemets et caractères spéciaux
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. LINT/FORMAT - PATTERNS D'ERREURS
|
||
|
|
|
||
|
|
### PAT-022: Code Formatting Issues
|
||
|
|
|
||
|
|
**Catégorie** : CAT-07 (Lint/Format)
|
||
|
|
**Priorité** : P2 (Moyenne)
|
||
|
|
**Fréquence** : Haute
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Code non formaté selon les standards.
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Auto-fix avec Prettier
|
||
|
|
npm run format
|
||
|
|
|
||
|
|
# Auto-fix avec ESLint
|
||
|
|
npm run lint -- --fix
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Utiliser Prettier pour formater automatiquement
|
||
|
|
- [ ] Pre-commit hook devrait formater avant commit
|
||
|
|
- [ ] Configurer l'éditeur pour formater à la sauvegarde
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### PAT-023: Import Order Issues
|
||
|
|
|
||
|
|
**Catégorie** : CAT-07 (Lint/Format)
|
||
|
|
**Priorité** : P2 (Moyenne)
|
||
|
|
**Fréquence** : Moyenne
|
||
|
|
**Découvert** : 2025-11-09
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
|
||
|
|
Imports non triés selon les règles.
|
||
|
|
|
||
|
|
#### Solution Standard
|
||
|
|
|
||
|
|
- Utiliser `eslint-plugin-import` avec règle de tri
|
||
|
|
- Auto-fix avec `npm run lint -- --fix`
|
||
|
|
|
||
|
|
#### Checklist de Prévention
|
||
|
|
|
||
|
|
- [ ] Configurer ESLint pour trier les imports
|
||
|
|
- [ ] Auto-fix devrait corriger automatiquement
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 RÉSUMÉ DES CHECKLISTS PAR CATÉGORIE
|
||
|
|
|
||
|
|
### Backend Go
|
||
|
|
|
||
|
|
- [ ] Vérifier import cycles avant d'ajouter un import
|
||
|
|
- [ ] Maintenir cohérence string vs *string
|
||
|
|
- [ ] Vérifier que tous les packages importés existent
|
||
|
|
- [ ] Utiliser `go vet` et `golangci-lint`
|
||
|
|
- [ ] Tests unitaires pour chaque fonction
|
||
|
|
|
||
|
|
### Frontend TypeScript/React
|
||
|
|
|
||
|
|
- [ ] Linter en temps réel activé
|
||
|
|
- [ ] TypeScript strict mode activé
|
||
|
|
- [ ] Tous les tags JSX fermés
|
||
|
|
- [ ] Pas de `any` types
|
||
|
|
- [ ] Pas de `console.log` en production
|
||
|
|
- [ ] Prettier configuré
|
||
|
|
|
||
|
|
### Tests
|
||
|
|
|
||
|
|
- [ ] Mocks configurés pour toutes les dépendances
|
||
|
|
- [ ] Coverage ≥ 80%
|
||
|
|
- [ ] Tests passent avant commit
|
||
|
|
- [ ] Fixtures réutilisables
|
||
|
|
|
||
|
|
### Configuration
|
||
|
|
|
||
|
|
- [ ] Variables d'environnement documentées
|
||
|
|
- [ ] docker-compose.yml validé
|
||
|
|
- [ ] vite.config.ts types corrects
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔄 MAINTENANCE
|
||
|
|
|
||
|
|
### Ajouter un Nouveau Pattern
|
||
|
|
|
||
|
|
1. Identifier le pattern récurrent
|
||
|
|
2. Documenter dans ce fichier avec le format standard
|
||
|
|
3. Mettre à jour les statistiques
|
||
|
|
4. Ajouter à la checklist de prévention appropriée
|
||
|
|
5. Mettre à jour `ORIGIN_ERROR_PREVENTION_GUIDE.md`
|
||
|
|
|
||
|
|
### Révision
|
||
|
|
|
||
|
|
- **Fréquence** : Mensuelle
|
||
|
|
- **Responsable** : Lead Engineers
|
||
|
|
- **Processus** : Analyser les nouvelles erreurs, documenter les patterns
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Dernière mise à jour** : 2025-11-09
|
||
|
|
**Version** : 1.0.0
|
||
|
|
**Statut** : ✅ **APPROUVÉ ET VERROUILLÉ**
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|