Chapitre 23
23. Interviews - Design Patterns
23. Interviews - Design Patterns
60 Questions d'Interview - Design Patterns
Partie 1 : Questions Comportementales (30)
Expérience générale
Q1 : Parle-moi d'un projet où tu as utilisé des Design Patterns. Quel pattern as-tu choisi et pourquoi ?
Q2 : Décris une situation où l'absence de Design Patterns a causé des problèmes dans un projet.
Q3 : Comment as-tu introduit les Design Patterns dans une équipe qui ne les utilisait pas ?
Q4 : Quel est le plus grand échec technique que tu aies rencontré avec un pattern ?
Q5 : Décris un refactoring important que tu as mené. Quels patterns as-tu appliqués ?
Prise de décision
Q6 : Comment choisis-tu entre plusieurs patterns pour résoudre un problème ?
Q7 : Décris une situation où tu as délibérément choisi de ne pas utiliser un pattern.
Q8 : Comment évalues-tu si un pattern est sur-engineering pour un problème donné ?
Q9 : Quelle est ton approche pour équilibrer flexibilité et simplicité dans une architecture ?
Q10 : Comment décides-tu quand refactorer du code legacy ?
Collaboration
Q11 : Comment expliques-tu un pattern complexe à un développeur junior ?
Q12 : Décris une revue de code où tu as suggéré l'utilisation d'un pattern.
Q13 : Comment gères-tu les désaccords sur le choix d'un pattern dans l'équipe ?
Q14 : As-tu déjà dû convaincre ton manager de l'importance d'investir dans l'architecture ?
Q15 : Comment documentes-tu les décisions architecturales dans ton équipe ?
Apprentissage
Q16 : Comment as-tu appris les Design Patterns ? Quelle ressource a été la plus utile ?
Q17 : Quel pattern as-tu découvert récemment et dans quel contexte ?
Q18 : Comment te tiens-tu à jour sur les nouveaux patterns et pratiques ?
Q19 : Quel livre sur les patterns recommanderais-tu à un développeur intermédiaire ?
Q20 : Quelle conférence ou vidéo sur les patterns t'a le plus marqué ?
Problèmes concrets
Q21 : Décris un système complexe que tu as conçu. Quels patterns architecturaux as-tu utilisés ?
Q22 : Comment as-tu géré une migration de monolithe vers microservices ?
Q23 : Décris un bug causé par une mauvaise utilisation de pattern et comment tu l'as corrigé.
Q24 : Comment gères-tu la dette technique liée aux patterns mal implémentés ?
Q25 : Décris comment tu as utilisé les tests pour valider une architecture de patterns.
Leadership
Q26 : Comment établis-tu des standards de code autour des patterns dans une équipe ?
Q27 : As-tu déjà créé un ADR (Architecture Decision Record) ? Décris le processus.
Q28 : Comment onboardes-tu un nouveau développeur sur une codebase riche en patterns ?
Q29 : Quels sont les anti-patterns les plus courants que tu vois en entreprise ?
Q30 : Quelle serait ton approche pour auditer l'architecture d'une application existante ?
Partie 2 : Questions Techniques (30)
Identification de patterns
Q31 : Donne un exemple concret où tu utiliserais le pattern Stratégie plutôt qu'un switch/if.
Q32 : Quelle est la différence entre Factory Method et Abstract Factory ? Donne un exemple pour chacun.
Q33 : Dans quels cas le pattern Singleton est-il approprié ? Dans quels cas est-ce un anti-pattern ?
Q34 : Quelle est la différence entre un Proxy et un Decorator ?
Q35 : Quand utiliser Composite plutôt qu'une simple collection ?
Implémentation
Q36 : Implémente un Observateur thread-safe en TypeScript.
Q37 : Code un Builder fluent pour une classe QueryBuilder SQL.
Q38 : Écris un Proxy de cache pour un service d'API avec TTL configurable.
Q39 : Implémente une Chaîne de Responsabilité pour un middleware HTTP.
Q40 : Code un Circuit Breaker simple avec les 3 états.
Architecture
Q41 : Conçois l'architecture d'un système de notifications supportant Email, SMS, Push, avec ajout facile d'un nouveau canal.
Q42 : Comment structurerais-tu un système de plugins en utilisant les patterns ?
Q43 : Conçois un système de validation de données avec composition de validateurs.
Q44 : Comment implémenterais-tu un undo/redo dans un éditeur ?
Q45 : Propose une architecture pour un système e-commerce avec les patterns appropriés.
SOLID et principes
Q46 : Explique le Dependency Inversion Principle. Donne un exemple avant/après.
Q47 : Comment le pattern Observateur viole-t-il potentiellement le LSP ? Comment l'éviter ?
Q48 : Quelle est la relation entre OCP (Open/Closed) et les patterns Strategy/Decorator ?
Q49 : Comment appliquer l'ISP (Interface Segregation) au React Context API ?
Q50 : Décris comment le pattern Adapter respecte le SRP.
Design Patterns avancés
Q51 : Explique le pattern Saga. Dans quel contexte l'utiliser ?
Q52 : Quelle est la différence entre CQRS et Event Sourcing ? Comment les combine-t-on ?
Q53 : Décris l'Anti-Corruption Layer. Quand est-il nécessaire ?
Q54 : Explique le pattern Strangler Fig pour la migration de systèmes legacy.
Q55 : Comment le pattern Outbox garantit-il la livraison fiable des événements ?
Systèmes distribués
Q56 : Comment gères-tu les transactions distribuées dans une architecture microservices ?
Q57 : Conçois un système de réservation avec Saga et compensation.
Q58 : Comment implémenter un API Gateway avec agrégation ?
Q59 : Explique le pattern BFF (Backend for Frontend). Donne un exemple.
Q60 : Comment assurer la résilience dans un système distribué ? Quels patterns utiliser ?
Réponses résumées (Techniques)
Q31 - Strategy vs switch
// Au lieu de :
function getDiscount(type: string) {
if (type === 'VIP') return 0.2;
if (type === 'LOYAL') return 0.15;
// ...
}
// Utiliser Strategy :
interface DiscountStrategy { calculate(amount: number): number; }
class VIPDiscount implements DiscountStrategy { calculate(a: number) { return a * 0.2; } }
class LoyalDiscount implements DiscountStrategy { calculate(a: number) { return a * 0.15; } }
Q36 - Observer thread-safe
class ThreadSafeObserver {
private observers = new Set<Function>();
private mutex = new Mutex();
async subscribe(fn: Function): Promise<void> {
await this.mutex.acquire();
try { this.observers.add(fn); }
finally { this.mutex.release(); }
}
async notify(data: any): Promise<void> {
const tasks = [...this.observers].map(fn => fn(data));
await Promise.all(tasks);
}
}
Q40 - Circuit Breaker
class CircuitBreaker {
state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED';
failures = 0;
threshold = 5;
timeout = 30000;
lastFailure = 0;
async call<T>(fn: () => Promise<T>): Promise<T> {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailure > this.timeout) this.state = 'HALF_OPEN';
else throw new Error('Circuit open');
}
try {
const result = await fn();
this.failures = 0;
this.state = 'CLOSED';
return result;
} catch (error) {
this.failures++;
this.lastFailure = Date.now();
if (this.failures >= this.threshold) this.state = 'OPEN';
throw error;
}
}
}
Q41 - Notification system
interface Notifier { send(message: string): void; }
class EmailNotifier implements Notifier { /* ... */ }
class SMSNotifier implements Notifier { /* ... */ }
class PushNotifier implements Notifier { /* ... */ }
class NotificationService {
constructor(private notifiers: Notifier[]) {}
send(message: string) { this.notifiers.forEach(n => n.send(message)); }
}
Q44 - Undo/Redo
Combinaison Command + Memento : chaque commande est stockée dans une pile. L'undo restaure le memento précédent.
Q51 - Saga
Transaction distribuée composée d'étapes locales avec compensation. Choreography (événements) ou Orchestration (coordinateur).
Q55 - Outbox
Sauvegarde l'événement dans la même transaction que l'opération métier. Un poller lit la table outbox et publie au broker. Garantie "at least once".