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.

14 KiB

🤝 Contributing to BricoLoc Architecture Evolution

Merci de votre intérêt pour contribuer au projet ! Ce document vous guide à travers le processus de contribution.


📋 Table des Matières

  1. Code of Conduct
  2. Comment Contribuer
  3. Standards de Code
  4. Process de Pull Request
  5. Standards de Commit
  6. Architecture et Patterns
  7. Tests
  8. Documentation

Code of Conduct

Nos Engagements

  • Respecter tous les contributeurs
  • Accueillir les nouveaux membres
  • Fournir des feedbacks constructifs
  • Se concentrer sur l'apprentissage

Comportements Attendus

  • Utiliser un langage accueillant et inclusif
  • Respecter les points de vue différents
  • Accepter les critiques constructives
  • Montrer de l'empathie envers les autres

Comment Contribuer

Types de Contributions

Type Exemples Difficulté
🐛 Bug Fixes Corriger un bug, améliorer performance
Features Nouvelle fonctionnalité, microservice
📚 Documentation README, guides, ADR
🧪 Tests Tests unitaires, intégration
🎨 UI/UX Améliorer interface, accessibilité
♻️ Refactoring Clean code, patterns

Avant de Commencer

  1. Lire la documentation :

  2. Setup environnement :

  3. Vérifier les issues :

    • Regarder les issues existantes
    • Vérifier qu'une issue similaire n'existe pas déjà

Standards de Code

TypeScript

Configuration : Suivre tsconfig.base.json (strict mode activé)

Bonnes pratiques :

// ✅ BON : Types explicites
function calculatePrice(days: number, dailyRate: number): number {
  return days * dailyRate
}

// ❌ MAUVAIS : Types implicites any
function calculatePrice(days, dailyRate) {
  return days * dailyRate
}

// ✅ BON : Interface bien définie
interface CreateReservationDTO {
  outilId: string
  dateDebut: Date
  dateFin: Date
  userId: string
}

// ❌ MAUVAIS : any partout
function createReservation(data: any): any {
  // ...
}

// ✅ BON : Gestion d'erreurs explicite
async function getUser(id: string): Promise<User | null> {
  try {
    const user = await userRepository.findById(id)
    return user
  } catch (error) {
    logger.error('Failed to fetch user', { id, error })
    throw new RepositoryError('User fetch failed')
  }
}

// ❌ MAUVAIS : Pas de gestion d'erreurs
async function getUser(id: string) {
  return await userRepository.findById(id)
}

Naming Conventions

Type Convention Exemples
Variables camelCase userId, dateDebut
Constantes UPPER_SNAKE_CASE MAX_RETRIES, API_URL
Fonctions camelCase + verbe createReservation(), calculatePrice()
Classes PascalCase ReservationService, UserFactory
Interfaces PascalCase + I prefix IReservationRepository
Types PascalCase CreateReservationDTO
Enums PascalCase ReservationStatus
Fichiers kebab-case reservation-service.ts
Dossiers kebab-case use-cases/, repositories/

Formatage

Prettier : Configuration automatique (.prettierrc.json)

# Formater tout le projet
pnpm prettier --write .

# Formater un fichier spécifique
pnpm prettier --write path/to/file.ts

ESLint : Vérification automatique

# Linter tout le projet
pnpm lint

# Linter avec auto-fix
pnpm lint --fix

Structure de Fichiers (Clean Architecture)

Microservice :

packages/microservices/<service>/
├── src/
│   ├── domain/                    # Couche Domaine (business logic)
│   │   ├── entities/              # Entités métier
│   │   ├── value-objects/         # Value Objects
│   │   ├── repositories/          # Interfaces repositories
│   │   ├── factories/             # Factories pour entités
│   │   └── rules/                 # Règles métier
│   │
│   ├── application/               # Couche Application (use cases)
│   │   ├── use-cases/             # Cas d'usage
│   │   ├── services/              # Services applicatifs
│   │   └── dtos/                  # Data Transfer Objects
│   │
│   └── infrastructure/            # Couche Infrastructure (implémentations)
│       ├── repositories/          # Implémentations des repositories
│       ├── external-apis/         # APIs externes (Stripe, etc.)
│       └── events/                # Event Bus
│
├── tests/                         # Tests
│   ├── unit/
│   ├── integration/
│   └── e2e/
│
├── package.json
├── tsconfig.json
└── README.md

Process de Pull Request

1. Fork & Clone (si externe)

# Fork le repo sur GitHub

# Clone votre fork
git clone https://github.com/VOTRE_USERNAME/bricoloc-architecture-evolution.git
cd bricoloc-architecture-evolution

# Ajouter le repo original comme upstream
git remote add upstream https://github.com/REPO_ORIGINAL/bricoloc-architecture-evolution.git

2. Créer une Feature Branch

git checkout develop
git pull origin develop
git checkout -b feature/ma-nouvelle-feature

3. Développer

4. Committer

Suivre Conventional Commits :

git add .
git commit -m "feat(catalogue): add search filters"

Format :

<type>(<scope>): <description>

[optional body]

[optional footer]

Types :

  • feat : Nouvelle fonctionnalité
  • fix : Correction de bug
  • docs : Documentation
  • style : Formatage
  • refactor : Refactoring
  • test : Tests
  • chore : Maintenance

5. Push & Pull Request

git push -u origin feature/ma-nouvelle-feature

Sur GitHub :

  • Créer Pull Request vers develop
  • Remplir le template
  • Assigner des reviewers (si applicable)

Template de PR :

## Description
Brève description des changements

## Type de changement
- [ ] Bug fix
- [ ] Nouvelle feature
- [ ] Breaking change
- [ ] Documentation

## Changements
- Changement 1
- Changement 2

## Checklist
- [ ] Code compile sans erreurs
- [ ] Tests passent
- [ ] Linting passe
- [ ] Documentation mise à jour
- [ ] J'ai testé manuellement

## Screenshots (si UI)

6. Review Process

Reviewer :

  • Vérifier le code
  • Tester localement si possible
  • Fournir feedback constructif

Contributeur :

  • Répondre aux commentaires
  • Faire les modifications demandées
  • Re-push

7. Merge

Après approbation :

  • Squash and Merge (par défaut)
  • Supprimer la branche feature

Standards de Commit

Messages de Commit

Bons exemples :

feat(auth): implement user registration with email validation
fix(inventory): resolve race condition in stock updates
docs(adr): add ADR-006 for Event Bus choice
refactor(reservation): apply Repository Pattern
test(catalogue): add unit tests for SearchOutils use case
chore(deps): upgrade Next.js to 14.2.0
style(format): run prettier on all TypeScript files

Mauvais exemples :

fix bug                    # Trop vague
update                     # Pas de contexte
WIP                        # Work In Progress
asdfasdf                   # Non descriptif
Fixed everything           # Pas spécifique

Commit Fréquence

  • Commits atomiques (une fonctionnalité = un commit)
  • Committer fréquemment (toutes les 30min - 2h)
  • Éviter les "mega commits" (100+ fichiers)

Architecture et Patterns

Principes SOLID

Toujours respecter les principes SOLID :

Single Responsibility :

// ✅ BON : Une seule responsabilité
class ReservationService {
  async createReservation(data: CreateReservationDTO): Promise<Reservation> {
    // Logique métier de création de réservation uniquement
  }
}

// ❌ MAUVAIS : Trop de responsabilités
class ReservationService {
  async createReservation() { /* ... */ }
  async sendEmail() { /* ... */ }        // Devrait être dans NotificationService
  async processPayment() { /* ... */ }   // Devrait être dans PaymentService
}

Dependency Inversion :

// ✅ BON : Dépend de l'interface
class ReservationService {
  constructor(private repo: IReservationRepository) {}
}

// ❌ MAUVAIS : Dépend de l'implémentation
class ReservationService {
  private repo = new SupabaseReservationRepository()
}

Patterns Obligatoires

Pattern Utilisation Exemple
Repository Accès données IReservationRepository
Service Layer Logique métier ReservationService
Dependency Injection Découplage Container IoC
Factory Création entités ReservationFactory
Observer Events async Event Bus

Clean Architecture

Respecter les dépendances :

Presentation Layer → Application Layer → Domain Layer
                                       ↑
Infrastructure Layer ─────────────────┘

Règles :

  • Domain Layer ne dépend de RIEN
  • Application Layer dépend uniquement de Domain
  • Infrastructure implémente les interfaces du Domain
  • Domain ne doit JAMAIS importer de Supabase, Next.js, etc.

Tests

Coverage Minimum

  • 80% de coverage pour les microservices
  • 70% de coverage global

Types de Tests

Tests Unitaires (priorité) :

// tests/unit/ReservationService.test.ts

describe('ReservationService', () => {
  let service: ReservationService
  let mockRepo: jest.Mocked<IReservationRepository>

  beforeEach(() => {
    mockRepo = {
      create: jest.fn(),
      findById: jest.fn(),
      // ...
    } as any
    service = new ReservationService(mockRepo)
  })

  it('should create a reservation when availability is confirmed', async () => {
    // Arrange
    const data: CreateReservationDTO = { /* ... */ }
    mockRepo.create.mockResolvedValue(mockReservation)

    // Act
    const result = await service.createReservation('user-1', data)

    // Assert
    expect(result).toEqual(mockReservation)
    expect(mockRepo.create).toHaveBeenCalledWith(data)
  })
})

Tests d'Intégration :

// tests/integration/api/reservations.test.ts

describe('POST /api/reservations', () => {
  it('should create a reservation and return 201', async () => {
    const response = await fetch('http://localhost:3001/api/reservations', {
      method: 'POST',
      body: JSON.stringify({ /* ... */ }),
    })

    expect(response.status).toBe(201)
    const data = await response.json()
    expect(data).toHaveProperty('id')
  })
})

Commandes

# Lancer tous les tests
pnpm test

# Tests avec coverage
pnpm test --coverage

# Tests en watch mode
pnpm test --watch

# Tests d'un fichier spécifique
pnpm test ReservationService.test.ts

Documentation

Quand Documenter

  • Toute nouvelle feature
  • Changement d'architecture
  • Nouvelle décision technique (ADR)
  • API publique

Types de Documentation

Code Comments :

/**
 * Crée une nouvelle réservation après vérification de disponibilité.
 *
 * @param userId - ID de l'utilisateur créant la réservation
 * @param data - Données de la réservation
 * @returns La réservation créée
 * @throws {BusinessError} Si l'outil n'est pas disponible
 * @throws {ValidationError} Si les dates sont invalides
 */
async createReservation(
  userId: string,
  data: CreateReservationDTO
): Promise<Reservation> {
  // ...
}

README par Microservice :

# Reservation Service

## Responsabilités
- Gestion des réservations
- Vérification de disponibilité
- Calcul des prix

## Architecture
- Domain : Entités, règles métier
- Application : Use cases, services
- Infrastructure : Repositories, events

## Usage
\`\`\`typescript
const service = container.get<ReservationService>('ReservationService')
const reservation = await service.createReservation(userId, data)
\`\`\`

ADR (Architecture Decision Records) :

  • Créer un ADR pour toute décision architecturale majeure
  • Format : docs/architecture/ADR/XXX-title.md
  • Suivre le template existant

Checklist de Contribution

Avant de soumettre une PR, vérifier :

Code

  • Code compile sans erreurs (pnpm build)
  • Linting passe (pnpm lint)
  • Formatage correct (pnpm prettier --check .)
  • Pas de console.log oubliés
  • Types TypeScript corrects (pas de any)

Tests

  • Tests passent (pnpm test)
  • Coverage > 80% pour le code ajouté
  • Tests unitaires ET intégration (si applicable)

Documentation

  • README mis à jour (si nécessaire)
  • Code commenté (fonctions complexes)
  • ADR créé (si décision architecturale)

Git

  • Commits suivent Conventional Commits
  • PR description complète
  • Branche à jour avec develop

Besoin d'Aide ?


Remerciements

Merci de contribuer à ce projet ! Chaque contribution, petite ou grande, est appréciée. 🙏


Dernière mise à jour : Octobre 2025