744 lines
18 KiB
Markdown
744 lines
18 KiB
Markdown
|
|
# ORIGIN_ERROR_PREVENTION_GUIDE.md
|
||
|
|
|
||
|
|
## 📋 RÉSUMÉ EXÉCUTIF
|
||
|
|
|
||
|
|
Ce document définit le **système complet de prévention d'erreurs** pour le projet Veza. Il s'intègre parfaitement à la méthodologie ORIGIN_ existante et doit être appliqué **AVANT** de commencer toute nouvelle tâche d'implémentation. Ce guide garantit qu'aucune erreur récurrente ne sera introduite dans le codebase.
|
||
|
|
|
||
|
|
**Dernière mise à jour** : 2025-11-09
|
||
|
|
**Statut** : ✅ Document de référence officiel
|
||
|
|
**Version** : 1.0.0
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 OBJECTIFS
|
||
|
|
|
||
|
|
### Objectif Principal
|
||
|
|
Établir un système de prévention d'erreurs qui garantit qu'aucune erreur récurrente ne sera introduite dans les futures implémentations.
|
||
|
|
|
||
|
|
### Objectifs Secondaires
|
||
|
|
- Réduire le temps de correction d'erreurs (< 5% du temps de développement)
|
||
|
|
- Maintenir la qualité du code (0 erreurs P0/P1)
|
||
|
|
- Faciliter l'onboarding (checklists claires)
|
||
|
|
- Standardiser les patterns de code (templates validés)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔒 RÈGLES IMMUABLES
|
||
|
|
|
||
|
|
1. **Pre-Flight Check OBLIGATOIRE** avant toute nouvelle tâche
|
||
|
|
2. **Templates OBLIGATOIRES** pour créer de nouveaux fichiers
|
||
|
|
3. **Quality Gates BLOQUANTS** en CI/CD
|
||
|
|
4. **Aucune exception** sans approbation Lead Engineer
|
||
|
|
5. **Documentation OBLIGATOIRE** de tout nouveau pattern d'erreur
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📖 TABLE DES MATIÈRES
|
||
|
|
|
||
|
|
1. [Pre-Flight Checklists](#1-pre-flight-checklists)
|
||
|
|
2. [Implementation Patterns](#2-implementation-patterns)
|
||
|
|
3. [Validation Gates](#3-validation-gates)
|
||
|
|
4. [Templates de Code](#4-templates-de-code)
|
||
|
|
5. [Workflow Intégré](#5-workflow-intégré)
|
||
|
|
6. [Références](#6-références)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 1. PRE-FLIGHT CHECKLISTS
|
||
|
|
|
||
|
|
### 1.1 Checklist Globale (Avant TOUTE Tâche)
|
||
|
|
|
||
|
|
**OBLIGATOIRE** : Exécuter cette checklist avant de commencer une nouvelle tâche.
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Exécuter le script de pre-flight check
|
||
|
|
./scripts/pre-flight-check.sh
|
||
|
|
```
|
||
|
|
|
||
|
|
**Checklist manuelle** :
|
||
|
|
|
||
|
|
- [ ] Aucune erreur P0/P1 existante (vérifier avec `./scripts/discover-errors.sh`)
|
||
|
|
- [ ] Tests existants passent (`go test ./...` / `npm test`)
|
||
|
|
- [ ] Linter ne produit aucune erreur (`golangci-lint run` / `npm run lint`)
|
||
|
|
- [ ] Code est à jour avec `main` (`git pull origin main`)
|
||
|
|
- [ ] Branche créée pour la tâche (`git checkout -b feature/TXXXX-description`)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 1.2 Checklist Backend Go
|
||
|
|
|
||
|
|
**Avant de créer/modifier du code Go** :
|
||
|
|
|
||
|
|
- [ ] Vérifier qu'aucun import cycle ne sera créé
|
||
|
|
```bash
|
||
|
|
# Visualiser le graphe de dépendances
|
||
|
|
cd veza-backend-api
|
||
|
|
go mod graph | grep -i "cycle"
|
||
|
|
```
|
||
|
|
- [ ] Valider la cohérence des types (string vs *string)
|
||
|
|
- Consulter `ORIGIN_ERROR_PATTERNS.md` PAT-002
|
||
|
|
- Décider une stratégie cohérente avant de modifier un modèle
|
||
|
|
- [ ] Vérifier que tous les packages importés existent
|
||
|
|
```bash
|
||
|
|
go build ./... # Doit réussir sans erreur
|
||
|
|
```
|
||
|
|
- [ ] Tests unitaires du composant parent passent
|
||
|
|
```bash
|
||
|
|
go test ./internal/services/... -v
|
||
|
|
```
|
||
|
|
- [ ] `go vet` ne produit aucun warning
|
||
|
|
```bash
|
||
|
|
go vet ./...
|
||
|
|
```
|
||
|
|
- [ ] `golangci-lint` ne produit aucune erreur
|
||
|
|
```bash
|
||
|
|
golangci-lint run
|
||
|
|
```
|
||
|
|
|
||
|
|
**Patterns à éviter** :
|
||
|
|
- ❌ Services qui importent handlers
|
||
|
|
- ❌ Handlers qui importent services directement
|
||
|
|
- ❌ Types partagés dans les packages qui les utilisent
|
||
|
|
- ❌ Mélange de `string` et `*string` pour champs optionnels
|
||
|
|
|
||
|
|
**Patterns sûrs** :
|
||
|
|
- ✅ Interfaces dans `internal/types/` ou `internal/interfaces/`
|
||
|
|
- ✅ Services dépendent uniquement d'interfaces
|
||
|
|
- ✅ Handlers dépendent uniquement d'interfaces
|
||
|
|
- ✅ Types cohérents (toujours `string` OU toujours `*string`)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 1.3 Checklist Frontend React/TypeScript
|
||
|
|
|
||
|
|
**Avant de créer/modifier du code TypeScript/React** :
|
||
|
|
|
||
|
|
- [ ] Vérifier que `tsconfig.json` est correct
|
||
|
|
```bash
|
||
|
|
cd apps/web
|
||
|
|
npx tsc --noEmit --strict
|
||
|
|
```
|
||
|
|
- [ ] Linter ne produit aucune erreur sur fichiers modifiés
|
||
|
|
```bash
|
||
|
|
npm run lint
|
||
|
|
```
|
||
|
|
- [ ] Tests existants passent avant modification
|
||
|
|
```bash
|
||
|
|
npm test -- --run
|
||
|
|
```
|
||
|
|
- [ ] Types TypeScript sont stricts (pas de `any`)
|
||
|
|
- Vérifier avec `tsc --noEmit --strict`
|
||
|
|
- Utiliser `unknown` si le type est vraiment inconnu
|
||
|
|
- [ ] JSX syntax validée (Prettier)
|
||
|
|
```bash
|
||
|
|
npm run format
|
||
|
|
```
|
||
|
|
- [ ] Pas de `console.log` en production
|
||
|
|
- Utiliser un logger configuré
|
||
|
|
- ESLint devrait bloquer automatiquement
|
||
|
|
|
||
|
|
**Patterns à éviter** :
|
||
|
|
- ❌ Regex non terminées dans les tests
|
||
|
|
- ❌ Tags JSX non fermés
|
||
|
|
- ❌ Types `any` explicites
|
||
|
|
- ❌ Variables non utilisées
|
||
|
|
- ❌ `console.log` en production
|
||
|
|
|
||
|
|
**Patterns sûrs** :
|
||
|
|
- ✅ Types explicites pour toutes les fonctions
|
||
|
|
- ✅ Self-closing tags JSX (`<Component />`)
|
||
|
|
- ✅ Mocks configurés pour tous les tests
|
||
|
|
- ✅ Logger au lieu de `console.log`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 1.4 Checklist Services Rust
|
||
|
|
|
||
|
|
**Avant de créer/modifier du code Rust** :
|
||
|
|
|
||
|
|
- [ ] `cargo check` passe
|
||
|
|
```bash
|
||
|
|
cd veza-chat-server # ou veza-stream-server
|
||
|
|
cargo check
|
||
|
|
```
|
||
|
|
- [ ] `cargo clippy` ne produit aucun warning
|
||
|
|
```bash
|
||
|
|
cargo clippy -- -D warnings
|
||
|
|
```
|
||
|
|
- [ ] SQLx queries validées avec schema
|
||
|
|
```bash
|
||
|
|
cargo sqlx prepare --check
|
||
|
|
```
|
||
|
|
- [ ] Tests unitaires passent
|
||
|
|
```bash
|
||
|
|
cargo test
|
||
|
|
```
|
||
|
|
|
||
|
|
**Patterns à éviter** :
|
||
|
|
- ❌ `unwrap()` en production (utiliser `?` ou gestion d'erreur)
|
||
|
|
- ❌ Types `i32` pour IDs (utiliser `Uuid`)
|
||
|
|
- ❌ Queries SQL non validées
|
||
|
|
|
||
|
|
**Patterns sûrs** :
|
||
|
|
- ✅ Gestion d'erreur avec `Result<T, E>`
|
||
|
|
- ✅ Types `Uuid` pour tous les IDs
|
||
|
|
- ✅ SQLx queries validées avec `sqlx::query!`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. IMPLEMENTATION PATTERNS
|
||
|
|
|
||
|
|
### 2.1 Backend Service Pattern
|
||
|
|
|
||
|
|
**Pattern sûr pour créer un nouveau service** :
|
||
|
|
|
||
|
|
```go
|
||
|
|
// ✅ PATTERN SÛR - Évite import cycles
|
||
|
|
// internal/services/user_service.go
|
||
|
|
package services
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"veza-backend-api/internal/types" // Interfaces dans package neutre
|
||
|
|
"veza-backend-api/internal/models"
|
||
|
|
)
|
||
|
|
|
||
|
|
// UserService implémente l'interface définie dans types
|
||
|
|
type UserService struct {
|
||
|
|
repo types.UserRepository // Dépend de l'interface, pas de l'implémentation
|
||
|
|
logger types.Logger
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewUserService crée une nouvelle instance
|
||
|
|
func NewUserService(repo types.UserRepository, logger types.Logger) *UserService {
|
||
|
|
return &UserService{
|
||
|
|
repo: repo,
|
||
|
|
logger: logger,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// CreateUser crée un nouvel utilisateur
|
||
|
|
func (s *UserService) CreateUser(ctx context.Context, req *CreateUserRequest) (*models.User, error) {
|
||
|
|
// Validation
|
||
|
|
if err := s.validateCreateRequest(req); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
// Business logic
|
||
|
|
user := &models.User{
|
||
|
|
Email: req.Email,
|
||
|
|
Username: req.Username,
|
||
|
|
}
|
||
|
|
|
||
|
|
// Persistence
|
||
|
|
if err := s.repo.Create(ctx, user); err != nil {
|
||
|
|
return nil, fmt.Errorf("failed to create user: %w", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
return user, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// validateCreateRequest valide la requête
|
||
|
|
func (s *UserService) validateCreateRequest(req *CreateUserRequest) error {
|
||
|
|
if req.Email == "" {
|
||
|
|
return types.ErrValidation("email is required")
|
||
|
|
}
|
||
|
|
// ... autres validations
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Interfaces dans package séparé** :
|
||
|
|
|
||
|
|
```go
|
||
|
|
// internal/types/interfaces.go
|
||
|
|
package types
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"veza-backend-api/internal/models"
|
||
|
|
)
|
||
|
|
|
||
|
|
// UserRepository définit les opérations de persistence
|
||
|
|
type UserRepository interface {
|
||
|
|
Create(ctx context.Context, user *models.User) error
|
||
|
|
FindByID(ctx context.Context, id uuid.UUID) (*models.User, error)
|
||
|
|
FindByEmail(ctx context.Context, email string) (*models.User, error)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Logger définit les opérations de logging
|
||
|
|
type Logger interface {
|
||
|
|
Info(msg string, fields ...interface{})
|
||
|
|
Error(msg string, fields ...interface{})
|
||
|
|
Debug(msg string, fields ...interface{})
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2.2 Backend Handler Pattern
|
||
|
|
|
||
|
|
**Pattern sûr pour créer un nouveau handler** :
|
||
|
|
|
||
|
|
```go
|
||
|
|
// ✅ PATTERN SÛR - Évite import cycles
|
||
|
|
// internal/handlers/user_handlers.go
|
||
|
|
package handlers
|
||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
"veza-backend-api/internal/types" // Interfaces seulement
|
||
|
|
"veza-backend-api/internal/models"
|
||
|
|
)
|
||
|
|
|
||
|
|
// UserHandlers gère les requêtes HTTP pour les utilisateurs
|
||
|
|
type UserHandlers struct {
|
||
|
|
userService types.UserService // Interface, pas l'implémentation
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewUserHandlers crée une nouvelle instance
|
||
|
|
func NewUserHandlers(userService types.UserService) *UserHandlers {
|
||
|
|
return &UserHandlers{
|
||
|
|
userService: userService,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// CreateUser gère POST /api/v1/users
|
||
|
|
func (h *UserHandlers) CreateUser(c *gin.Context) {
|
||
|
|
var req CreateUserRequest
|
||
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
user, err := h.userService.CreateUser(c.Request.Context(), &req)
|
||
|
|
if err != nil {
|
||
|
|
handleError(c, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusCreated, user)
|
||
|
|
}
|
||
|
|
|
||
|
|
// handleError gère les erreurs de manière cohérente
|
||
|
|
func handleError(c *gin.Context, err error) {
|
||
|
|
// Logique de gestion d'erreur centralisée
|
||
|
|
// ...
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2.3 Frontend Component Pattern
|
||
|
|
|
||
|
|
**Pattern sûr pour créer un nouveau composant React** :
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ PATTERN SÛR - Évite import hell
|
||
|
|
// src/components/user/UserProfile.tsx
|
||
|
|
import type { User } from '@/types'; // Types séparés
|
||
|
|
import { useUserStore } from '@/stores/user'; // State management
|
||
|
|
import { userService } from '@/services/user'; // API calls
|
||
|
|
import { useUser } from '@/hooks/useUser'; // Custom hook
|
||
|
|
|
||
|
|
interface UserProfileProps {
|
||
|
|
userId: string;
|
||
|
|
className?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Component NE fait PAS de logic business
|
||
|
|
export const UserProfile: React.FC<UserProfileProps> = ({
|
||
|
|
userId,
|
||
|
|
className
|
||
|
|
}) => {
|
||
|
|
// Custom hook gère la logique
|
||
|
|
const { data: user, isLoading, error } = useUser(userId);
|
||
|
|
|
||
|
|
// États de chargement et d'erreur
|
||
|
|
if (isLoading) return <Spinner />;
|
||
|
|
if (error) return <ErrorMessage error={error} />;
|
||
|
|
if (!user) return <div>User not found</div>;
|
||
|
|
|
||
|
|
// Rendu simple
|
||
|
|
return (
|
||
|
|
<div className={className}>
|
||
|
|
<h2>{user.name}</h2>
|
||
|
|
<p>{user.email}</p>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
**Custom Hook Pattern** :
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ PATTERN SÛR - Logique réutilisable
|
||
|
|
// src/hooks/useUser.ts
|
||
|
|
import { useQuery } from '@tanstack/react-query';
|
||
|
|
import { userService } from '@/services/user';
|
||
|
|
|
||
|
|
export function useUser(userId: string) {
|
||
|
|
return useQuery({
|
||
|
|
queryKey: ['user', userId],
|
||
|
|
queryFn: () => userService.getUser(userId),
|
||
|
|
enabled: !!userId,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2.4 Frontend Service Pattern
|
||
|
|
|
||
|
|
**Pattern sûr pour créer un nouveau service API** :
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ PATTERN SÛR - Types explicites
|
||
|
|
// src/services/user.ts
|
||
|
|
import type { User, CreateUserRequest } from '@/types';
|
||
|
|
import { apiClient } from './apiClient';
|
||
|
|
|
||
|
|
export const userService = {
|
||
|
|
async getUser(userId: string): Promise<User> {
|
||
|
|
const response = await apiClient.get<User>(`/api/v1/users/${userId}`);
|
||
|
|
return response.data;
|
||
|
|
},
|
||
|
|
|
||
|
|
async createUser(request: CreateUserRequest): Promise<User> {
|
||
|
|
const response = await apiClient.post<User>('/api/v1/users', request);
|
||
|
|
return response.data;
|
||
|
|
},
|
||
|
|
|
||
|
|
async updateUser(userId: string, request: Partial<User>): Promise<User> {
|
||
|
|
const response = await apiClient.put<User>(`/api/v1/users/${userId}`, request);
|
||
|
|
return response.data;
|
||
|
|
},
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2.5 Test Pattern (Frontend)
|
||
|
|
|
||
|
|
**Pattern sûr pour écrire des tests** :
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// ✅ PATTERN SÛR - Mocks configurés
|
||
|
|
// src/components/user/UserProfile.test.tsx
|
||
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||
|
|
import { render, screen } from '@testing-library/react';
|
||
|
|
import { UserProfile } from './UserProfile';
|
||
|
|
import { useUser } from '@/hooks/useUser';
|
||
|
|
|
||
|
|
// Mock le hook
|
||
|
|
vi.mock('@/hooks/useUser');
|
||
|
|
|
||
|
|
describe('UserProfile', () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
vi.clearAllMocks();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should render user profile', () => {
|
||
|
|
// Arrange
|
||
|
|
const mockUser = {
|
||
|
|
id: '123',
|
||
|
|
name: 'John Doe',
|
||
|
|
email: 'john@example.com',
|
||
|
|
};
|
||
|
|
|
||
|
|
vi.mocked(useUser).mockReturnValue({
|
||
|
|
data: mockUser,
|
||
|
|
isLoading: false,
|
||
|
|
error: null,
|
||
|
|
} as any);
|
||
|
|
|
||
|
|
// Act
|
||
|
|
render(<UserProfile userId="123" />);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
||
|
|
expect(screen.getByText('john@example.com')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('should show loading state', () => {
|
||
|
|
// Arrange
|
||
|
|
vi.mocked(useUser).mockReturnValue({
|
||
|
|
data: null,
|
||
|
|
isLoading: true,
|
||
|
|
error: null,
|
||
|
|
} as any);
|
||
|
|
|
||
|
|
// Act
|
||
|
|
render(<UserProfile userId="123" />);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
expect(screen.getByRole('status')).toBeInTheDocument(); // Spinner
|
||
|
|
});
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. VALIDATION GATES
|
||
|
|
|
||
|
|
### 3.1 Pre-Commit Gates (Husky)
|
||
|
|
|
||
|
|
**Configuration automatique** : Les hooks Husky sont configurés dans `.husky/pre-commit`.
|
||
|
|
|
||
|
|
**Gates activés** :
|
||
|
|
- ✅ Formatage automatique (Prettier, gofmt)
|
||
|
|
- ✅ Linter (ESLint, golangci-lint)
|
||
|
|
- ✅ Tests unitaires rapides (`go test -short`, `npm test -- --run`)
|
||
|
|
- ✅ Type checking (TypeScript)
|
||
|
|
|
||
|
|
**Si un gate échoue** :
|
||
|
|
- ❌ Le commit est bloqué
|
||
|
|
- ✅ Corriger les erreurs
|
||
|
|
- ✅ Réessayer le commit
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3.2 Pre-Merge Gates (GitHub Actions)
|
||
|
|
|
||
|
|
**Configuration** : `.github/workflows/error-prevention.yml`
|
||
|
|
|
||
|
|
**Gates activés** :
|
||
|
|
|
||
|
|
1. **Architecture Validation**
|
||
|
|
- Vérification des import cycles (Go)
|
||
|
|
- Vérification de la structure des packages
|
||
|
|
|
||
|
|
2. **Type Safety**
|
||
|
|
- TypeScript strict mode
|
||
|
|
- Go type checking
|
||
|
|
|
||
|
|
3. **Test Coverage**
|
||
|
|
- Coverage ≥ 80% pour nouveau code
|
||
|
|
- Tous les tests passent
|
||
|
|
|
||
|
|
4. **Linter**
|
||
|
|
- Zero linter errors
|
||
|
|
- Zero linter warnings (ou < 5)
|
||
|
|
|
||
|
|
5. **Build**
|
||
|
|
- Backend compile sans erreur
|
||
|
|
- Frontend build réussit
|
||
|
|
|
||
|
|
**Si un gate échoue** :
|
||
|
|
- ❌ La PR ne peut pas être mergée
|
||
|
|
- ✅ Corriger les erreurs
|
||
|
|
- ✅ Push les corrections
|
||
|
|
- ✅ Les gates se relancent automatiquement
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3.3 Pre-Deployment Gates
|
||
|
|
|
||
|
|
**Gates activés** :
|
||
|
|
- ✅ Tous les tests passent (unit, integration, E2E)
|
||
|
|
- ✅ Coverage ≥ 80% (global)
|
||
|
|
- ✅ Performance tests passent
|
||
|
|
- ✅ Security scan pass
|
||
|
|
- ✅ Smoke tests passent en staging
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. TEMPLATES DE CODE
|
||
|
|
|
||
|
|
### 4.1 Utilisation des Templates
|
||
|
|
|
||
|
|
**Avant de créer un nouveau fichier** :
|
||
|
|
|
||
|
|
1. Consulter la liste des templates disponibles dans `/dev-environment/templates/`
|
||
|
|
2. Copier le template approprié
|
||
|
|
3. Remplacer les placeholders (`{{PLACEHOLDER}}`)
|
||
|
|
4. Adapter selon les besoins spécifiques
|
||
|
|
|
||
|
|
**Exemple** :
|
||
|
|
```bash
|
||
|
|
# Créer un nouveau service Go
|
||
|
|
cp dev-environment/templates/backend-service.template.go \
|
||
|
|
veza-backend-api/internal/services/my_service.go
|
||
|
|
|
||
|
|
# Éditer et remplacer les placeholders
|
||
|
|
# {{SERVICE_NAME}} → MyService
|
||
|
|
# {{PACKAGE_NAME}} → myservice
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 4.2 Templates Disponibles
|
||
|
|
|
||
|
|
**Backend Go** :
|
||
|
|
- `backend-service.template.go` - Service avec interface
|
||
|
|
- `backend-handler.template.go` - Handler HTTP
|
||
|
|
- `backend-repository.template.go` - Repository pattern
|
||
|
|
|
||
|
|
**Frontend React/TypeScript** :
|
||
|
|
- `frontend-component.template.tsx` - Composant React
|
||
|
|
- `frontend-hook.template.ts` - Custom hook
|
||
|
|
- `frontend-service.template.ts` - Service API
|
||
|
|
|
||
|
|
**Rust** :
|
||
|
|
- `rust-service.template.rs` - Service Rust
|
||
|
|
|
||
|
|
**Voir** : `/dev-environment/templates/` pour les templates complets.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. WORKFLOW INTÉGRÉ
|
||
|
|
|
||
|
|
### 5.1 Workflow Complet
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph TD
|
||
|
|
A[Nouvelle Tâche TXXXX] --> B[Pre-Flight Check]
|
||
|
|
B -->|FAIL| C[Corriger Erreurs Existantes]
|
||
|
|
C --> B
|
||
|
|
B -->|PASS| D[Choisir Template]
|
||
|
|
D --> E[Implémenter avec Pattern Sûr]
|
||
|
|
E --> F[Tests Unitaires TDD]
|
||
|
|
F --> G{Coverage ≥ 80%?}
|
||
|
|
G -->|Non| F
|
||
|
|
G -->|Oui| H[Lint Check]
|
||
|
|
H --> I{Zero Errors?}
|
||
|
|
I -->|Non| E
|
||
|
|
I -->|Oui| J[Pre-Commit Hook]
|
||
|
|
J --> K{Hook Pass?}
|
||
|
|
K -->|Non| E
|
||
|
|
K -->|Oui| L[Commit]
|
||
|
|
L --> M[Push & Create PR]
|
||
|
|
M --> N[CI/CD Gates]
|
||
|
|
N --> O{All Gates Pass?}
|
||
|
|
O -->|Non| E
|
||
|
|
O -->|Oui| P[Code Review]
|
||
|
|
P --> Q{Approved?}
|
||
|
|
Q -->|Non| E
|
||
|
|
Q -->|Oui| R[Merge]
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 5.2 Checklist par Étape
|
||
|
|
|
||
|
|
#### Étape 1: Pre-Flight Check
|
||
|
|
- [ ] Exécuter `./scripts/pre-flight-check.sh`
|
||
|
|
- [ ] Vérifier qu'aucune erreur P0/P1 existe
|
||
|
|
- [ ] Tests existants passent
|
||
|
|
- [ ] Linter clean
|
||
|
|
|
||
|
|
#### Étape 2: Implémentation
|
||
|
|
- [ ] Utiliser template approprié
|
||
|
|
- [ ] Suivre pattern sûr (voir section 2)
|
||
|
|
- [ ] Éviter les anti-patterns (voir `ORIGIN_ERROR_PATTERNS.md`)
|
||
|
|
- [ ] Tests en TDD (Red-Green-Refactor)
|
||
|
|
|
||
|
|
#### Étape 3: Validation Locale
|
||
|
|
- [ ] Tests unitaires passent
|
||
|
|
- [ ] Coverage ≥ 80%
|
||
|
|
- [ ] Linter zero errors
|
||
|
|
- [ ] Type check passe
|
||
|
|
- [ ] Build réussit
|
||
|
|
|
||
|
|
#### Étape 4: Commit
|
||
|
|
- [ ] Pre-commit hook passe
|
||
|
|
- [ ] Message de commit suit format: `TXXXX: type: description`
|
||
|
|
- [ ] Commit atomique (une fonctionnalité par commit)
|
||
|
|
|
||
|
|
#### Étape 5: PR & Review
|
||
|
|
- [ ] CI/CD gates passent
|
||
|
|
- [ ] Code review approuvé (2 reviewers)
|
||
|
|
- [ ] Documentation mise à jour si nécessaire
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 6. RÉFÉRENCES
|
||
|
|
|
||
|
|
### Documents ORIGIN
|
||
|
|
|
||
|
|
- **ORIGIN_ERROR_PATTERNS.md** - Catalogue des patterns d'erreurs
|
||
|
|
- **ORIGIN_CODE_STANDARDS.md** - Standards de code
|
||
|
|
- **ORIGIN_MASTER_ARCHITECTURE.md** - Architecture du projet
|
||
|
|
- **ORIGIN_TESTING_STRATEGY.md** - Stratégie de tests
|
||
|
|
- **ORIGIN_IMPLEMENTATION_TASKS.md** - Tâches d'implémentation
|
||
|
|
|
||
|
|
### Scripts Utilitaires
|
||
|
|
|
||
|
|
- `./scripts/pre-flight-check.sh` - Validation pré-tâche
|
||
|
|
- `./scripts/discover-errors.sh` - Découverte d'erreurs
|
||
|
|
- `./scripts/generate-error-summary.sh` - Rapport d'erreurs
|
||
|
|
|
||
|
|
### Outils
|
||
|
|
|
||
|
|
- **Go** : `go vet`, `golangci-lint`, `go test`
|
||
|
|
- **TypeScript** : `tsc`, `eslint`, `prettier`
|
||
|
|
- **Rust** : `cargo check`, `cargo clippy`, `cargo test`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ✅ CHECKLIST DE VALIDATION
|
||
|
|
|
||
|
|
### Avant de Commencer une Tâche
|
||
|
|
|
||
|
|
- [ ] Pre-flight check exécuté et passé
|
||
|
|
- [ ] Template choisi et copié
|
||
|
|
- [ ] Pattern sûr identifié
|
||
|
|
- [ ] Checklist spécifique (Backend/Frontend/Rust) complétée
|
||
|
|
|
||
|
|
### Pendant l'Implémentation
|
||
|
|
|
||
|
|
- [ ] Pattern sûr suivi
|
||
|
|
- [ ] Anti-patterns évités
|
||
|
|
- [ ] Tests écrits en TDD
|
||
|
|
- [ ] Linter activé en temps réel
|
||
|
|
|
||
|
|
### Avant le Commit
|
||
|
|
|
||
|
|
- [ ] Tests passent
|
||
|
|
- [ ] Coverage ≥ 80%
|
||
|
|
- [ ] Linter zero errors
|
||
|
|
- [ ] Type check passe
|
||
|
|
- [ ] Build réussit
|
||
|
|
|
||
|
|
### Avant le Merge
|
||
|
|
|
||
|
|
- [ ] CI/CD gates passent
|
||
|
|
- [ ] Code review approuvé
|
||
|
|
- [ ] Documentation mise à jour
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔄 MAINTENANCE
|
||
|
|
|
||
|
|
### Mise à Jour du Guide
|
||
|
|
|
||
|
|
- **Fréquence** : Mensuelle ou après découverte d'un nouveau pattern
|
||
|
|
- **Responsable** : Lead Engineers
|
||
|
|
- **Processus** :
|
||
|
|
1. Identifier nouveau pattern d'erreur
|
||
|
|
2. Documenter dans `ORIGIN_ERROR_PATTERNS.md`
|
||
|
|
3. Mettre à jour ce guide si nécessaire
|
||
|
|
4. Communiquer à l'équipe
|
||
|
|
|
||
|
|
### Amélioration Continue
|
||
|
|
|
||
|
|
- Analyser les erreurs qui passent malgré les gates
|
||
|
|
- Améliorer les templates si nécessaire
|
||
|
|
- Ajuster les checklists selon les retours
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Dernière mise à jour** : 2025-11-09
|
||
|
|
**Version** : 1.0.0
|
||
|
|
**Statut** : ✅ **APPROUVÉ ET VERROUILLÉ**
|
||
|
|
|
||
|
|
**"Prevention is better than cure."**
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|