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
- Code of Conduct
- Comment Contribuer
- Standards de Code
- Process de Pull Request
- Standards de Commit
- Architecture et Patterns
- Tests
- 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
-
Lire la documentation :
-
Setup environnement :
- Suivre Setup WSL Guide
-
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
- Suivre les standards de code
- Écrire des tests
- Mettre à jour la documentation
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 bugdocs: Documentationstyle: Formatagerefactor: Refactoringtest: Testschore: 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 ?
- 📖 Documentation : Lire
docs/ - 💬 Issues : Poser une question via GitHub Issues
- 📧 Email : votre.email@example.com
Remerciements
Merci de contribuer à ce projet ! Chaque contribution, petite ou grande, est appréciée. 🙏
Dernière mise à jour : Octobre 2025