Architecture 100 termes

100 termes affichés

TypeBestPractice Concept Method Pattern Principle
Niveau 🟢 Junior 🟡 Mid 🔴 Senior

Mis à jour ces 90 derniers jours 7 nouvelles · 31 révisées

Abstract Factory

Architecture 🟡 Mid? entretien

Fournit une interface pour créer des familles d'objets lies sans spécifier leurs classes concrètes. C'est une factory de factories.

Un catalogue IKEA par style : tu choisis 'scandinave' et tu obtiens table, chaise et lampe assorties.

class DarkThemeFactory {
  createButton() { return new DarkButton(); }
  createInput() { return new DarkInput(); }
}
// Usage: const ui = getFactory('dark');

Cas d'usage : Créer des composants UI cohérents par theme ou des connecteurs DB par provider.

Anti-pattern : Créer une abstract factory pour un seul produit — utiliser Factory Method suffit.
#architecture#interview#gof#creational

Adapter

Architecture 🟢 Junior

Convertit l'interface d'une classe en une autre interface attendue par le client. Permet a des classes incompatibles de collaborer.

Un adaptateur de prise électrique : ta prise française fonctionne dans une prise anglaise grâce a l'adaptateur.

class StripeAdapter {
  constructor(stripe) { this.stripe = stripe; }
  pay(amount) {
    return this.stripe.charges.create({ amount });
  }
}

Cas d'usage : Intégrer une librairie tierce dont l'API ne correspond pas a votre interface interne.

Anti-pattern : Adapter toute l'application a la librairie externe au lieu d'isoler l'adaptation.
#architecture#interview#gof#structural

ADR (Architecture Decision Record)

Architecture 🟢 Junior? entretien

Document court, versionné avec le code, qui consigne une décision d'architecture importante : contexte, décision, conséquences, statut (proposé, accepté, déprécié, remplacé). Popularisé par Michael Nygard dans son billet « Documenting Architecture Décisions » de 2011, le format a évolué vers des modèles comme MADR. Une ADR n'est jamais modifiée après acceptation : on en écrit une nouvelle qui la remplace.

Le journal de bord d'un capitaine : on ne réécrit pas les pages d'hier, on ajoute celle d'aujourd'hui en expliquant pourquoi on change de cap.

# docs/adr/0007-remplacer-ingress-nginx-par-gateway-api.md
# 7. Remplacer Ingress NGINX par la Gateway API
Date : 2026-03-02
Statut : Accepté (remplace ADR-0003)
## Contexte
Ingress NGINX est retiré par le projet Kubernetes en mars 2026 :
plus de correctifs de sécurité.
## Décision
Migrer vers Envoy Gateway + HTTPRoute via ingress2gateway.
## Conséquences
+ routage canary natif, rôles séparés plateforme/équipes
- formation, réécriture des annotations spécifiques

Cas d'usage : Toute décision structurante (base de données, découpage en services, framework, hébergement) qu'un nouvel arrivant devra comprendre dans deux ans.

Anti-pattern : Écrire l'ADR après coup pour justifier, ou la modifier en silence : elle perd sa valeur d'historique honnête.
#architecture#documentation#interview

Aggregate

Architecture 🔴 Senior

Groupe d'entités et de value objects traite comme une unité de cohérence transactionnelle. Toutes les modifications passent par la racine d'agrégat.

Un bon de commande avec ses lignes : tu ne modifies jamais une ligne directement, tu passes toujours par la commande.

class Order {
  #items = [];
  addItem(product, qty) {
    this.#items.push(new OrderLine(product, qty));
    this.recalculateTotal();
  }
}

Cas d'usage : Garantir les invariants métier dans un périmètre transactionnel défini.

Anti-pattern : Agrégats trop gros qui verrouillent trop de données — contention en prod.
#architecture#interview#ddd

Aggregate Root

Architecture 🔴 Senior

Entité principale d'un agrégat qui sert de point d'entrée unique. Les objets externes ne peuvent référencer que la racine, jamais les entités internes.

Le chef d'équipe : toute communication avec l'équipe passe par lui pour garantir la cohérence.

// Order est la racine, OrderLine est interne
const order = await orderRepo.findById(id);
order.addItem(product, qty); // Pas: orderLine.setQty()
await orderRepo.save(order);

Cas d'usage : Protéger les invariants métier en forçant toutes les opérations via un point d'entrée unique.

Anti-pattern : Accéder directement aux entités internes de l'agrégat depuis l'extérieur.
#architecture#interview#ddd

Ambassador

Architecture 🔴 Senior

Proxy helper déployé a cote d'un service pour gérer les connexions sortantes (retry, circuit breaker, monitoring). Variante du Sidecar.

Un ambassadeur diplomatique : il représente ton pays et gère les protocoles complexes a ta place.

// Le sidecar ambassador gere le retry et le circuit breaking
// L'app appelle simplement localhost:9000
const res = await fetch('http://localhost:9000/external-api');

Cas d'usage : Simplifier les connexions sortantes d'un service vers des APIs externes.

Anti-pattern : Implémenter retry/circuit breaker dans chaque service au lieu de les centraliser.
#architecture#interview#microservices#cloud

Anti-Corruption Layer

Architecture 🔴 Senior

Couche de traduction entre votre domaine et un système externe ou legacy. Empêche les concepts étrangers de polluer votre modèle.

Un traducteur-interprété entre deux pays : il adapte non seulement la langue mais aussi les conventions culturelles.

class LegacyUserAdapter {
  toModernUser(legacyData) {
    return new User({
      id: legacyData.USR_ID,
      name: `${legacyData.FNAME} ${legacyData.LNAME}`,
    });
  }
}

Cas d'usage : Intégrer un système legacy sans contaminer votre domaine avec ses conventions.

Anti-pattern : Laisser les champs legacy (USR_ID, FNAME) se propager dans tout votre domaine.
#architecture#interview#ddd

API Gateway

Architecture 🟡 Mid? entretien

Point d'entrée unique pour toutes les requêtes client. Gère routage, authentification, rate limiting, aggregation et transformation.

La réception d'un hôtel : tous les clients passent par elle, et elle dirige vers le bon service.

// Kong / AWS API Gateway config
routes:
  - path: /users
    service: user-service
    plugins: [rate-limit, jwt-auth]
  - path: /orders
    service: order-service

Cas d'usage : Entrée unifiée pour les microservices avec concerns transversaux centralises.

Anti-pattern : Gateway trop intelligente avec de la logique métier — doit rester un passe-plat.
#architecture#interview#microservices

API Pagination (Cursor vs Offset)

Architecture 🟡 Mid? entretien

Offset : skip/limit simple mais instable sur les données qui changent. Cursor : basée sur un marqueur stable, performante a grande échelle.

Offset : 'page 5 d'un livre' (instable si on ajoute des pages). Cursor : 'lire a partir du marque-page' (toujours fiable).

// Offset: GET /users?page=3&limit=20
// Cursor: GET /users?after=eyJpZCI6MTAwfQ&limit=20
const cursor = Buffer.from(JSON.stringify({ id: lastId })).toString('base64');

Cas d'usage : Offset pour les petits datasets avec UI de pages. Cursor pour les feeds infinis et les APIs a fort volume.

Anti-pattern : Offset sur des millions de lignes — performances catastrophiques avec OFFSET 100000.
#architecture#interview#api#best-practice

API Rate Limiting

Architecture 🟡 Mid? entretien

Limite le nombre de requêtes qu'un client peut faire dans un intervalle de temps. Protège contre les abus, le DDoS et la surcharge.

Le nombre max de retraits au distributeur par jour : protège la banque et ton compte.

// Express rate limiter
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 min
  max: 100, // 100 requetes par fenetre
});
app.use('/api/', limiter);

Cas d'usage : APIs publiques, protection contre les abus, équité d'accès entre clients.

Anti-pattern : Rate limit global sans distinction par client — un client gourmand bloque tout le monde.
#architecture#interview#api#security

API Versioning

Architecture 🟡 Mid? entretien

Stratégies pour faire évoluer une API sans casser les clients existants : URL path (/v1/), header (Accept), query param. Chaque approche a ses tradeoffs.

Les éditions d'un manuel scolaire : la v1 reste disponible pendant que la v2 est utilisée par les nouveaux étudiants.

// URL versioning (le plus courant)
app.use('/api/v1/users', usersV1Router);
app.use('/api/v2/users', usersV2Router);
// Header versioning
// Accept: application/vnd.api+json;version=2

Cas d'usage : APIs publiques avec des clients que vous ne contrôlez pas et qui ne migrent pas en même temps.

Anti-pattern : Breaking changes sans versioning — les clients en production cassent.
#architecture#interview#api#best-practice

Application Service

Architecture 🟡 Mid? entretien

Orchestre les use cases de l'application : coordonne le domaine, les repositories et les services externes. Ne contient pas de logique métier.

Un chef de projet : il coordonne les équipes mais ne code pas lui-même.

class PlaceOrderUseCase {
  async execute(dto) {
    const order = Order.create(dto);
    await this.repo.save(order);
    await this.eventBus.publish(order.events);
  }
}

Cas d'usage : Orchestrer un use case complet : validation, persistance, publication d'events.

Anti-pattern : Mettre de la logique métier dans le service applicatif au lieu du domaine.
#architecture#interview#ddd

Backpressure

Architecture 🔴 Senior

Mécanisme par lequel un consommateur lent signale au producteur de ralentir, pour éviter que les données s'accumulent en mémoire jusqu'au plantage. Dans les streams Node.js, write() renvoie false quand le tampon interne dépasse highWaterMark et l'événement drain indique quand reprendre ; pipeline() gère cela automatiquement. Le même principe existe en Kafka (consommation par lot), en RxJS et dans les files de messages (limites de préfetch).

Un serveur qui apporte les plats au rythme où le convive les mange, au lieu d'empiler quinze assiettes sur la table jusqu'à ce qu'elle cède.

import { pipeline } from 'node:stream/promises';
import { createReadStream, createWriteStream } from 'node:fs';
import { createGzip } from 'node:zlib';

// pipeline() propage la backpressure et les erreurs :
// si le disque écrit lentement, la lecture ralentit d'elle-même.
await pipeline(
  createReadStream('export-10go.csv'),
  createGzip(),
  createWriteStream('export-10go.csv.gz'),
);

// À la main, ce serait :
// if (!dest.write(chunk)) await once(dest, 'drain');

Cas d'usage : Export de fichiers volumineux, relais de flux HTTP, ingestion de messages : partout où un producteur rapide alimente un consommateur plus lent.

Anti-pattern : Enchaîner src.on('data', chunk => dest.write(chunk)) en ignorant la valeur de retour de write() : la mémoire du processus gonfle jusqu'au crash.
#architecture#resilience#streams

BFF (Backend for Frontend)

Architecture 🟡 Mid? entretien

Un backend dédié par type de client (web, mobile, IoT) qui adapte et agrège les données des services backend pour les besoins spécifiques de chaque frontend.

Un assistant personnel par langue : chacun traduit et résume l'information selon les besoins de son interlocuteur.

// Mobile BFF - donnees legeres
app.get('/api/mobile/feed', async (req, res) => {
  const data = await feedService.get();
  res.json(data.map(toMobileFeedItem));
});

Cas d'usage : Quand le web a besoin de données riches et le mobile de données légères.

Anti-pattern : Un seul backend pour tous les clients avec des if/else par plateforme.
#architecture#interview#microservices

Bounded Context

Architecture 🟡 Mid? entretien

Frontière explicite dans laquelle un modèle de domaine particulier s'applique. Chaque contexte a son propre langage et ses propres règles.

Les départements d'une entreprise : 'client' signifie prospect en commercial et compte en comptabilité.

// Context 'Sales': Customer has cart, wishlist
// Context 'Billing': Customer has invoices, payments
// Meme mot, modeles differents, bases separees

Cas d'usage : Décomposer un système complexe en sous-domaines autonomes avec des frontières claires.

Anti-pattern : Un modèle unique partage entre tous les contextes — Big Ball of Mud.
#architecture#interview#ddd

Bridge

Architecture 🔴 Senior

Découplé une abstraction de son implémentation pour qu'elles puissent varier indépendamment. Évite l'explosion combinatoire de sous-classes.

Une télécommande universelle : la télécommande (abstraction) fonctionne avec n'importe quelle TV (implémentation).

class Notification {
  constructor(sender) { this.sender = sender; }
  send(msg) { this.sender.deliver(msg); }
}
// new Notification(new SmsSender()).send('Hi');

Cas d'usage : Quand deux dimensions de variation (ex: forme + couleur) génèrent trop de sous-classes.

Anti-pattern : Hériter pour chaque combinaison : RedCircle, BlueCircle, RedSquare...
#architecture#interview#gof#structural

Builder

Architecture 🟢 Junior

Sépare la construction d'un objet complexe de sa représentation. Permet de construire étape par étape avec une API fluide.

Commander un burger personnalise : pain, puis steak, puis sauce, puis fromage — chaque étape est optionnelle.

const query = new QueryBuilder()
  .select('name', 'email')
  .from('users')
  .where('active = true')
  .limit(10)
  .build();

Cas d'usage : Construction de requêtes SQL, objets de configuration ou DTOs avec beaucoup de paramètrès optionnels.

Anti-pattern : Constructeur avec 10+ paramètrès positionnels au lieu d'un builder lisible.
#architecture#interview#gof#creational

Cache Stampede (ruée sur le cache)

Architecture 🔴 Senior

Incident où une clé très demandée expire et où des centaines de requêtes simultanées ratent le cache en même temps et recalculent toutes la même valeur, écrasant la base. Parades : verrou ou « single flight » (une seule recalcule, les autres attendent), servir la valeur périmée pendant le recalcul (stale-while-revalidate), et l'expiration anticipée probabiliste XFetch (article VLDB 2015) où chaque lecteur a une probabilité croissante de rafraîchir avant l'échéance, ce qui lisse les recalculs.

La sonnerie de fin de cours : si toute l'école se rue sur la même cantine à la même seconde, la file explose ; faire sortir les classes avec quelques minutes d'écart règle le problème.

// XFetch : rafraîchir « un peu avant » avec une probabilité croissante
const BETA = 1.0;
async function getWithXFetch(key, ttlSec, compute) {
  const hit = await cache.get(key);   // { value, expiry, delta }
  const now = Date.now() / 1000;
  const mustRefresh =
    !hit || now - hit.delta * BETA * Math.log(Math.random()) >= hit.expiry;
  if (!mustRefresh) return hit.value;

  const t0 = Date.now() / 1000;
  const value = await compute();          // recalcul coûteux
  const delta = Date.now() / 1000 - t0;   // durée du recalcul
  await cache.set(key, { value, delta, expiry: now + ttlSec });
  return value;
}

Cas d'usage : Page d'accueil, top produits, configuration globale : toute clé chaude dont le recalcul est coûteux et l'expiration synchronisée.

Anti-pattern : Mettre le même TTL rond (3600 s) sur mille clés créées au même déploiement : elles expirent toutes ensemble et provoquent la ruée.
#architecture#cache#performance

Cell-Based Architecture

Architecture 🔴 Senior

Découpage d'un système en cellules indépendantes et identiques, chacune servant un sous-ensemble de clients avec sa propre pile complète (calcul, base, files). Un routeur de cellules, le plus mince possible, dirige chaque requête vers la bonne cellule ; un plan de contrôle provisionne les cellules. Une panne, un bogue ou un déploiement raté ne touche qu'une fraction des clients. AWS documente le pattern dans son guide Well-Architected « Reducing the Scope of Impact with Cell-Based Architecture ».

Les compartiments étanches d'un navire : une voie d'eau inonde un compartiment, pas la coque entière.

// Routeur de cellules : couche mince, déterministe, sans logique métier
const CELLS = ['cell-a', 'cell-b', 'cell-c'];

function cellFor(tenantId: string): string {
  // hachage stable → un tenant vit toujours dans la même cellule
  const h = [...tenantId].reduce((a, c) => (a * 31 + c.charCodeAt(0)) >>> 0, 7);
  return CELLS[h % CELLS.length];
}

app.use((req, res, next) => {
  const cell = cellFor(req.headers['x-tenant-id'] as string);
  proxy.web(req, res, { target: `https://${cell}.internal` });
});
// Déployer la version N+1 sur cell-a d'abord = canary par cellule.

Cas d'usage : Plateforme multi-tenant à forte exigence de disponibilité, où l'on veut borner le « rayon d'explosion » d'un incident ou d'un déploiement.

Anti-pattern : Partager une base de données ou une file entre toutes les cellules : la ressource commune redevient le point de défaillance unique.
#architecture#resilience#senior

Chain of Responsibility

Architecture 🟡 Mid? entretien

Passe une requête le long d'une chaîne de handlers. Chaque handler décidé de traiter la requête ou de la passer au suivant.

Le service client : opérateur, superviseur, manager — ta demande remonte jusqu'a quelqu'un qui peut la traiter.

class Handler {
  setNext(h) { this.next = h; return h; }
  handle(req) {
    if (this.canHandle(req)) return this.process(req);
    return this.next?.handle(req);
  }
}

Cas d'usage : Pipeline de validation, middleware Express, gestion d'evenements DOM (bubbling).

Anti-pattern : Chaîne trop longue sans handler par défaut — la requête tombe dans le vide.
#architecture#interview#gof#behavioral

Circuit Breaker

Architecture 🟡 Mid? entretien

Détecte les défaillances et empêche l'application de tenter des opérations vouées a l'échec. Trois états : ferme, ouvert, semi-ouvert.

Un disjoncteur électrique : il coupe le courant quand il détecte une surcharge pour protéger l'installation.

class CircuitBreaker {
  #failures = 0;
  async call(fn) {
    if (this.#failures > 5) throw new Error('Circuit open');
    try { return await fn(); }
    catch(e) { this.#failures++; throw e; }
  }
}

Cas d'usage : Appels a des services externes instables pour éviter les cascades de pannes.

Anti-pattern : Retry infini sans circuit breaker — le service défaillant est submerge.
#architecture#interview#resilience#microservices

Clean Architecture

Architecture 🟡 Mid? entretien

Architecture en couches concentriques ou les dépendances pointent vers l'intérieur. Le domaine est au centre, indépendant des frameworks et de l'infrastructure.

Un oignon : chaque couche protège le coeur (domaine) des détails extérieurs (UI, DB, frameworks).

// Domain (centre) - aucune dependance
class User { validate() { ... } }
// Use Case
class CreateUser { execute(dto) { ... } }
// Infrastructure (exterieur)
class PostgresUserRepo { save(user) { ... } }

Cas d'usage : Applications complexes avec logique métier riche qui doit survivre aux changements de frameworks.

Anti-pattern : Domaine qui dépend du framework ORM ou du framework HTTP.
#architecture#interview#architecture-style

Command

Architecture 🟡 Mid? entretien

Encapsulé une requête comme un objet, permettant de paramétrer, mettre en file d'attente, journaliser et annuler des opérations.

Un bon de commande au restaurant : il capture l'intention, peut être mis en attente ou annule.

class CreateUserCmd {
  constructor(data) { this.data = data; }
  execute() { return db.users.insert(this.data); }
  undo() { return db.users.delete(this.data.id); }
}

Cas d'usage : Système undo/redo, file de taches asynchrones, CQRS command side.

Anti-pattern : Mettre la logique métier dans le command handler au lieu du domaine.
#architecture#interview#gof#behavioral

Composite

Architecture 🟡 Mid? entretien

Compose des objets en structures arborescentes pour représenter des hiérarchies partie-tout. Les clients traitent uniformément objets simples et composes.

Un dossier de fichiers : un dossier peut contenir des fichiers ou d'autres dossiers, et on peut tous les supprimer de la même façon.

class Folder {
  children = [];
  add(child) { this.children.push(child); }
  getSize() {
    return this.children.reduce((s, c) => s + c.getSize(), 0);
  }
}

Cas d'usage : Menus imbriques, arbres DOM, systèmes de fichiers, organigrammes.

Anti-pattern : Traiter différemment feuilles et noeuds partout dans le code client.
#architecture#interview#gof#structural

Composition over Inheritance

Architecture 🟡 Mid? entretien

Favoriser la composition d'objets plutôt que l'héritage de classes pour réutiliser du comportement. Plus flexible et moins fragile.

Les LEGO : tu assembles des pièces pour créer des formes variées, au lieu de mouler une pièce monolithique par forme.

// Heritage fragile:
class FlyingSwimmingDuck extends FlyingDuck { swim() {} }
// Composition:
class Duck {
  constructor(private fly: Flyable, private swim: Swimmable) {}
}

Cas d'usage : Combiner des comportements sans les limites de l'héritage simple ou le diamond problem.

Anti-pattern : Hiérarchies d'héritage profondes (5+ niveaux) — fragiles et impossibles a comprendre.
#architecture#interview#principle

Content Negotiation

Architecture 🟡 Mid? entretien

Mécanisme HTTP ou le client et le serveur se mettent d'accord sur le format de la réponse via les headers Accept et Content-Type.

Commander dans un restaurant multilangue : tu demandes le menu en français, on te le donne en français.

// Client
Accept: application/json
// Serveur
app.get('/users', (req, res) => {
  if (req.accepts('json')) res.json(users);
  else if (req.accepts('xml')) res.send(toXml(users));
  else res.status(406).end();
});

Cas d'usage : APIs qui doivent supporter plusieurs formats (JSON, XML, CSV) pour différents clients.

Anti-pattern : Ignorer le header Accept et toujours renvoyer JSON — mauvaise expérience pour les clients non-JSON.
#architecture#interview#api

Context Mapping

Architecture 🔴 Senior

Cartographie des relations entre Bounded Contexts : shared kernel, customer-supplier, conformist, ACL, partnership. Définit les contrats d'intégration.

La carte diplomatique mondiale : elle montre quels pays sont allies, en conflit, ou indépendants.

// Context Map (documentation)
// Sales <-> Billing : Customer-Supplier
// Sales -> Shipping : Conformist
// Sales <-> Legacy CRM : Anti-Corruption Layer

Cas d'usage : Visualiser et planifier les intégrations entre sous-domaines d'un système complexe.

Anti-pattern : Intégrer des contextes sans définir la relation — couplage implicite non géré.
#architecture#interview#ddd

Convention over Configuration

Architecture 🟡 Mid? entretien

Privilégier des conventions sensées par défaut plutôt que de forcer une configuration explicite. Le développeur ne configure que ce qui dévie de la convention.

Une réunion hebdo toujours lundi 9h : pas besoin de réinviter chaque semaine, seules les exceptions sont signalées.

// Convention NestJS: UserController -> /users
@Controller('users') // convention: nom du controleur = route
class UserController {
  @Get() findAll() { ... } // GET /users
}

Cas d'usage : Frameworks comme Rails, NestJS, Spring Boot : réduire le boilerplate de configuration.

Anti-pattern : Trop de magie implicite rend le debug difficile quand la convention ne convient pas.
#architecture#interview#principle

CORS (Cross-Origin Resource Sharing)

Architecture 🟡 Mid? entretien

Mécanisme de sécurité HTTP qui permet a un serveur d'indiquer quelles origines sont autorisées a accéder a ses ressources. Gère via des headers spécifiques.

Le badge d'accès a un immeuble : seuls les employés autorises (origines) peuvent entrer dans certains étages (endpoints).

app.use(cors({
  origin: ['https://myapp.com'],
  methods: ['GET', 'POST'],
  credentials: true,
  maxAge: 86400 // preflight cache 24h
}));

Cas d'usage : Frontend sur un domaine différent du backend — quasi-obligatoire en SPA moderne.

Anti-pattern : Access-Control-Allow-Origin: * avec credentials — interdit par les navigateurs et insecure.
#architecture#interview#api#security

CQRS

Architecture 🔴 Senior

Command Query Responsibility Ségrégation : sépare les modèles de lecture (Query) et d'écriture (Command). Permet d'optimiser chaque cote indépendamment.

Un guichet de banque : un guichet pour déposer (écriture), un autre pour consulter le solde (lecture).

// Command side
class CreateOrderCmd { execute(data) { db.write(data); } }
// Query side (modele optimise lecture)
class OrderQuery { getList() { return readDb.orders.find(); } }

Cas d'usage : Applications avec des ratios lecture/écriture très différents ou des modèles de lecture complexes.

Anti-pattern : Appliquer CQRS a un simple CRUD — complexité injustifiée.
#architecture#interview#architecture-style

CQS (Command Query Separation)

Architecture 🟡 Mid? entretien

Une méthode est soit une commande (modifie l'état, ne retourne rien) soit une query (retourne des données, ne modifie rien). Jamais les deux.

Au guichet : soit tu deposes un chèque (commande), soit tu consultes ton solde (query). Pas les deux en même temps.

class Stack {
  push(item) { this.items.push(item); } // Command: void
  peek() { return this.items.at(-1); }   // Query: value
  // pop() viole CQS: modifie ET retourne
}

Cas d'usage : Base de CQRS, rend le code prévisible et plus facile a raisonner.

Anti-pattern : Méthodes qui modifient l'état et retournent des résultats — effets de bord caches.
#architecture#interview#principle

DataLoader

Architecture 🟡 Mid? entretien

Utilitaire qui batch et cache les requêtes de données pour résoudre le problème N+1 dans GraphQL. Regroupe les appels DB d'un même tick en une seule requête.

Un serveur qui attend que toute la table ait commande avant d'aller en cuisine, au lieu de faire un aller-retour par personne.

const userLoader = new DataLoader(async (ids) => {
  const users = await db.users.findByIds(ids);
  return ids.map(id => users.find(u => u.id === id));
});
// userLoader.load(1); userLoader.load(2); -> 1 query

Cas d'usage : Resolvers GraphQL qui chargent des entités liées pour éviter N+1 requêtes.

Anti-pattern : Un SELECT par resolver sans batching — 100 items = 100 requêtes DB.
#architecture#interview#api#performance

Decorator

Architecture 🟡 Mid? entretien

Ajoute dynamiquement des responsabilités a un objet sans modifier sa classe. Offre une alternative flexible a l'héritage.

Ajouter des garnitures sur une pizza : chaque garniture enveloppe la précédenté et ajoute son propre goût.

function withLogging(fn) {
  return (...args) => {
    console.log('Call:', fn.name);
    return fn(...args);
  };
}
const save = withLogging(saveUser);

Cas d'usage : Ajouter logging, cache, validation ou authentification de façon transparente.

Anti-pattern : Empiler trop de décorateurs rendant le debug et la trace d'erreurs impossibles.
#architecture#interview#gof#structural

Dependency Inversion Principle

Architecture 🟡 Mid? entretien

Les modules de haut niveau ne doivent pas dépendre des modules de bas niveau. Les deux doivent dépendre d'abstractions. Les abstractions ne dépendent pas des détails.

Une prise électrique : l'appareil et le réseau dépendent du standard de la prise, pas l'un de l'autre.

// Haut niveau depend d'une abstraction
interface Logger { log(msg: string): void; }
class UserService {
  constructor(private logger: Logger) {}
}
// Injecte ConsoleLogger ou FileLogger

Cas d'usage : Rendre le code testable en injectant des mocks et découpler les couches.

Anti-pattern : import direct de l'implémentation concrète dans le module de haut niveau.
#architecture#interview#principle

Domain Event

Architecture 🟡 Mid? entretien

Evenement significatif qui s'est produit dans le domaine métier. Nomme au passe (OrderPlaced, PaymentReceived). Déclenché des réactions dans d'autres contextes.

L'annonce au micro dans un magasin : 'Nouveau produit disponible en rayon 3' — tous les intéressés réagissent.

class OrderPlaced extends DomainEvent {
  constructor(public orderId: string, public total: number) {
    super('OrderPlaced');
  }
}
order.addEvent(new OrderPlaced(order.id, order.total));

Cas d'usage : Découpler les side effects (emails, analytics) de la logique métier principale.

Anti-pattern : Events nommes comme des commandes (CreateInvoice au lieu de OrderPlaced).
#architecture#interview#ddd

Domain Service

Architecture 🟡 Mid? entretien

Service stateless qui encapsulé une logique métier qui ne rentre naturellement dans aucune entité ou value object. Opéré sur plusieurs agrégats.

Un notaire : il ne possède rien mais orchestre une transaction entre acheteur et vendeur.

class TransferService {
  transfer(from: Account, to: Account, amount: Money) {
    from.debit(amount);
    to.credit(amount);
  }
}

Cas d'usage : Opérations métier impliquant plusieurs agrégats qui ne peuvent pas être attribuées a un seul.

Anti-pattern : Domain service anémique qui ne fait que déléguer au repository — logique métier absente.
#architecture#interview#ddd

DRY (Don't Repeat Yourself)

Architecture 🟢 Junior

Chaque pièce de connaissance doit avoir une représentation unique et non ambiguë dans le système. Évite la duplication de logique.

Une source unique de vérité : un seul calendrier familial, pas un par personne qui divergent.

// Mauvais: validation email dupliquee partout
// Bon:
const isValidEmail = (e) => /^[^@]+@[^@]+$/.test(e);
// Reutilise dans form, API, import

Cas d'usage : Centraliser les règles métier, validations et transformations pour éviter les incohérences.

Anti-pattern : DRY prématuré : abstraire du code qui se ressemble mais n'a pas la même raison de changer.
#architecture#interview#principle

Entity (DDD)

Architecture 🟡 Mid? entretien

Objet du domaine défini par son identité unique plutôt que par ses attributs. Deux entités avec les mêmes attributs mais des IDs différents sont distinctes.

Deux jumeaux identiques : même apparence, mais ce sont deux personnes distinctes avec des identités différentes.

class User {
  constructor(public readonly id: string, public name: string) {}
  equals(other: User) { return this.id === other.id; }
}

Cas d'usage : Modéliser des concepts métier qui ont un cycle de vie et une identité persistante.

Anti-pattern : Comparer des entités par valeur au lieu de par identité.
#architecture#interview#ddd

ETag / If-None-Match

Architecture 🟡 Mid? entretien

Mécanisme de cache HTTP : le serveur renvoie un ETag (hash du contenu), le client le renvoie dans If-None-Match. Si inchangé, 304 Not Modified.

Un numéro de version sur un document : si tu as déjà la dernière version, pas besoin de retelecharger.

// Reponse serveur
res.setHeader('ETag', '"abc123"');
// Requete client suivante
// If-None-Match: "abc123"
// Serveur: 304 Not Modified (pas de body)

Cas d'usage : Réduire la bande passante et la charge serveur pour les ressources rarement modifiées.

Anti-pattern : Générer un ETag coûteux (hash de tout le body) sur chaque requête — annule le gain.
#architecture#interview#api#performance

Event Bus

Architecture 🟡 Mid? entretien

Canal central de communication par evenements au sein d'une application. Les composants publient et s'abonnent sans se connaître mutuellement.

Le tableau d'affichage d'une entreprise : n'importe qui peut y poster une annonce, n'importe qui peut la lire.

class EventBus {
  #handlers = {};
  on(event, fn) { (this.#handlers[event] ??= []).push(fn); }
  emit(event, data) { this.#handlers[event]?.forEach(fn => fn(data)); }
}

Cas d'usage : Communication entre modules d'un monolithe modulaire ou composants UI découplés.

Anti-pattern : Event bus global sans typage — impossible de tracer quels events existent.
#architecture#interview#messaging

Event Sourcing

Architecture 🔴 Senior

Stocke l'état comme une séquence immuable d'evenements plutôt que comme l'état courant. L'état se reconstruit en rejouant les evenements.

Un relève bancaire : tu ne stockes pas le solde, mais l'historique de toutes les transactions.

const events = [
  { type: 'AccountOpened', balance: 0 },
  { type: 'MoneyDeposited', amount: 100 },
  { type: 'MoneyWithdrawn', amount: 30 },
];
const balance = events.reduce(applyEvent, 0); // 70

Cas d'usage : Audit trail complet, systèmes financiers, undo/redo, debug temporel.

Anti-pattern : Evenements mutables ou supprimes — on perd la propriété d'immutabilite.
#architecture#interview#architecture-style

Event-Driven Architecture

Architecture 🟡 Mid

Architecture ou les composants communiquent par production et consommation d'evenements asynchrones. Decouplage temporel et spatial.

Un système de sonnettes dans un restaurant : le cuisinier sonne quand le plat est prêt, le serveur réagit.

// Producer
await broker.publish('order.created', order);
// Consumer
broker.subscribe('order.created', async (order) => {
  await inventory.reserve(order.items);
});

Cas d'usage : Systèmes réactifs, microservices découplés, traitement temps réel de flux de données.

Anti-pattern : Event soup : trop d'evenements sans schema clair rendent le système impossible a debugger.
#architecture#interview#architecture-style

Facade

Architecture 🟢 Junior

Fournit une interface simplifiée a un sous-système complexe. Cache la complexité derrière une API unifiée et facile a utiliser.

Le bouton 'démarrer' d'une voiture : un geste simple qui déclenche démarreur, injection, allumage.

class OrderFacade {
  async placeOrder(cart) {
    await this.payment.charge(cart.total);
    await this.inventory.reserve(cart.items);
    await this.shipping.schedule(cart.address);
  }
}

Cas d'usage : Simplifier l'utilisation d'un sous-système avec plusieurs classes interdépendantes.

Anti-pattern : Transformer la façade en God Object qui fait tout au lieu de déléguer.
#architecture#interview#gof#structural

Factory Method

Architecture 🟢 Junior

Définit une interface pour créer un objet, mais laisse les sous-classes décider quelle classe instancier. Permet de déléguer la logique de création.

Un restaurant avec une carte : tu choisis 'pizza' et la cuisine décidé quelle recette exacte préparer.

class NotifFactory {
  create(type) {
    if (type === 'email') return new EmailNotif();
    if (type === 'sms') return new SmsNotif();
    throw new Error('Unknown type');
  }
}

Cas d'usage : Quand la logique de création varie selon le contexte et qu'on veut éviter les if/else dans le code client.

Anti-pattern : Mettre toute la logique de création dans le constructeur au lieu de la déléguer.
#architecture#interview#gof#creational

Fail Fast

Architecture 🟢 Junior

Détecter et signaler les erreurs le plus tôt possible plutôt que de les propager silencieusement. Réduit le temps de debug et les effets de bord.

Le voyant moteur : mieux vaut s'arrêter au premier signal que rouler jusqu'a la panne totale.

function createUser(data) {
  if (!data.email) throw new Error('Email required');
  if (!isValid(data.email)) throw new Error('Invalid email');
  // ... logique seulement si tout est valide
}

Cas d'usage : Validation d'entrées, assertions en début de fonction, guard clauses.

Anti-pattern : Avaler les erreurs silencieusement avec un catch vide ou retourner des valeurs par défaut.
#architecture#interview#principle

Flyweight

Architecture 🔴 Senior

Partage efficacement des objets a grain fin pour économiser la mémoire. Sépare l'état intrinsèque (partage) de l'état extrinsèque (contextuel).

Les caractères d'imprimerie : chaque lettre 'A' utilise le même bloc métallique, seule la position sur la page change.

const icons = new Map();
function getIcon(name) {
  if (!icons.has(name)) icons.set(name, loadIcon(name));
  return icons.get(name);
}

Cas d'usage : Rendu de milliers d'éléments similaires (arbres dans un jeu, caractères dans un éditeur).

Anti-pattern : Créer une nouvelle instance pour chaque élément alors que 90% de l'état est identique.
#architecture#interview#gof#structural#performance

GraphQL

Architecture 🟡 Mid? entretien

Langage de requête pour APIs ou le client spécifié exactement les données souhaitées. Un seul endpoint, schema type, pas d'over/under-fetching.

Commander a la carte au restaurant : tu choisis exactement chaque plat et garniture, rien de plus.

query {
  user(id: 42) {
    name
    email
    orders(last: 5) {
      total
      status
    }
  }
}

Cas d'usage : Frontends avec des besoins de données varies (mobile vs web), dashboards complexes.

Anti-pattern : Problème N+1 : chaque field déclenché une requête DB sans DataLoader.
#architecture#interview#api

gRPC

Architecture 🟡 Mid? entretien

Framework RPC haute performance de Google utilisant Protocol Buffers pour la sérialisation et HTTP/2 pour le transport. Supporte le streaming bidirectionnel.

Un talkie-walkie numérique : communication directe, rapide, avec un protocole strict que les deux cotes comprennent.

// user.proto
service UserService {
  rpc GetUser (UserRequest) returns (UserResponse);
  rpc ListUsers (Empty) returns (stream UserResponse);
}
message UserRequest { int32 id = 1; }

Cas d'usage : Communication inter-microservices performante, streaming temps réel, APIs internes.

Anti-pattern : Utiliser gRPC pour des APIs publiques consommées par des navigateurs — REST/GraphQL est plus adapte.
#architecture#interview#api

HATEOAS

Architecture 🔴 Senior

Hypermedia As The Engine Of Application State. Niveau 3 de Richardson : les réponses contiennent des liens vers les actions possibles, rendant l'API auto-decouvrable.

Un site web : chaque page contient des liens vers les pages suivantes — tu n'as pas besoin de deviner les URLs.

{
  "id": 42, "name": "Alice",
  "_links": {
    "self": { "href": "/users/42" },
    "orders": { "href": "/users/42/orders" },
    "delete": { "href": "/users/42", "method": "DELETE" }
  }
}

Cas d'usage : APIs publiques auto-documentées ou le client n'a pas besoin de hardcoder les URLs.

Anti-pattern : Client qui hardcode toutes les URLs au lieu de suivre les liens — fragile au changement.
#architecture#interview#api

Hexagonal Architecture

Architecture 🟡 Mid

Architecture Ports & Adapters ou le domaine expose des ports (interfaces) et les adaptateurs connectent le monde extérieur. Isole le coeur métier.

Une prise universelle : le port est le standard, l'adaptateur change selon le pays (DB, API, UI).

// Port (interface)
interface UserPort { findById(id): User; }
// Adapter
class MongoUserAdapter implements UserPort {
  findById(id) { return mongo.find({ _id: id }); }
}

Cas d'usage : Remplacer facilement une base de données ou un service externe sans toucher au domaine.

Anti-pattern : Le domaine qui importe directement mongoose ou prisma — violation du port.
#architecture#interview#architecture-style

Hollywood Principle

Architecture 🟡 Mid

Don't call us, we'll call you. Les composants de haut niveau appellent ceux de bas niveau via des callbacks ou des hooks, pas l'inverse.

Un casting Hollywood : l'acteur laisse ses coordonnées, c'est le studio qui rappelle — pas l'inverse.

// Framework appelle ton code (IoC)
app.get('/users', (req, res) => {
  res.json(users); // Tu ne geres pas le serveur HTTP
});
// Express t'appelle quand la route matche

Cas d'usage : Fondement de l'Inversion of Control dans les frameworks et le pattern Template Method.

Anti-pattern : Code applicatif qui poll le framework au lieu d'être appelé par lui.
#architecture#interview#principle

Idempotency

Architecture 🟡 Mid

Une opération idempotente produit le même résultat qu'elle soit exécutée une ou plusieurs fois. Essentiel pour les retries et la fiabilité des APIs.

Appuyer sur le bouton d'un ascenseur déjà allume : le résultat est le même, qu'on appuie 1 ou 10 fois.

// Idempotency key pour eviter les doublons
app.post('/payments', async (req, res) => {
  const existing = await db.findByIdempotencyKey(req.headers['idempotency-key']);
  if (existing) return res.json(existing);
  const payment = await processPayment(req.body);
  res.json(payment);
});

Cas d'usage : Paiements, création de ressources, toute opération qui peut être retentee par le client.

Anti-pattern : POST qui crée un doublon a chaque retry — facturations multiples en production.
#architecture#interview#api#best-practice

Interface Segregation Principle

Architecture 🟡 Mid

Un client ne doit pas être force de dépendre d'interfaces qu'il n'utilise pas. Préférer plusieurs interfaces spécifiques a une seule interface générâle.

Une télécommande par appareil plutôt qu'une télécommande universelle avec 200 boutons dont tu n'en utilises que 5.

// Mauvais: interface Animal { fly(); swim(); run(); }
// Bon:
interface Flyable { fly(): void; }
interface Swimmable { swim(): void; }
class Duck implements Flyable, Swimmable { }

Cas d'usage : Éviter les implémentations vides ou les throws 'not supported' dans les classes.

Anti-pattern : Fat interface avec 20 méthodes dont la plupart des implementeurs n'en utilisent que 3.
#architecture#interview#principle

Interpreter

Architecture 🔴 Senior

Définit une représentation grammaticale pour un langage et un interpréteur pour évaluer ses expressions. Utilisée pour les DSL.

Un traducteur humain : il comprend la grammaire de la langue source et produit l'équivalent dans la langue cible.

class NumberExpr {
  constructor(val) { this.val = val; }
  interpret() { return this.val; }
}
class AddExpr {
  constructor(l, r) { this.l = l; this.r = r; }
  interpret() { return this.l.interpret() + this.r.interpret(); }
}

Cas d'usage : Moteurs de règles métier, parseurs d'expressions mathématiques, langages de requêtes.

Anti-pattern : Utiliser ce pattern pour un langage complexe — mieux vaut un vrai parser generator.
#architecture#interview#gof#behavioral

Iterator

Architecture 🟢 Junior

Fournit un moyen de parcourir sequentiellement les éléments d'une collection sans exposer sa structure interne.

Une playlist musicale : tu appuies sur 'suivant' sans savoir si c'est un tableau, un arbre ou une API.

class Range {
  constructor(start, end) { this.s = start; this.e = end; }
  *[Symbol.iterator]() {
    for (let i = this.s; i <= this.e; i++) yield i;
  }
}

Cas d'usage : Parcourir des structures de données complexes (arbres, graphes) avec une interface uniforme.

Anti-pattern : Exposer la structure interne de la collection au code client.
#architecture#interview#gof#behavioral

KISS (Keep It Simple, Stupid)

Architecture 🟢 Junior

La simplicité doit être un objectif clé du design. La complexité inutile est le pire ennemi de la maintenabilite.

Un interrupteur on/off vs un panneau de contrôle de centrale nucléaire — choisis la simplicité adaptée.

// Over-engineered:
class UserValidatorStrategyFactory { ... }
// KISS:
function validateUser(u) {
  return u.name?.length > 0 && isValidEmail(u.email);
}

Cas d'usage : Choisir la solution la plus simple qui résout le problème actuel.

Anti-pattern : Architecture enterprise pour un side-project de 3 pages.
#architecture#interview#principle

Law of Demeter

Architecture 🟡 Mid

Un objet ne devrait parler qu'a ses amis proches, pas aux amis de ses amis. Évite les chaînés d'appels (train wreck) qui créent du couplage profond.

Au restaurant, tu parles au serveur, pas directement au cuisinier ni au fournisseur du cuisinier.

// Mauvais (train wreck):
user.getAddress().getCity().getZipCode()
// Bon:
user.getZipCode() // delegation interne

Cas d'usage : Réduire le couplage entre objets et rendre le code plus résilient aux changements.

Anti-pattern : Chaînés de getters qui exposent la structure interne de tout le graphe d'objets.
#architecture#interview#principle

Local-first & CRDT

Architecture 🔴 Senior

Approche où l'application stocke et modifie les données d'abord sur l'appareil de l'utilisateur, puis synchronise quand le réseau le permet : zéro attente, fonctionnement hors ligne, collaboration en temps réel, données qui survivent au service. Le terme vient de l'essai d'Ink & Switch de 2019. Les CRDT (Conflict-free Replicated Data Types) rendent la fusion automatique et sans conflit : Yjs domine l'édition de texte collaborative (ProseMirror, TipTap, CodeMirror), Automerge les documents structurés.

Chacun écrit sur son carnet dans le train sans réseau ; à l'arrivée, les carnets se fusionnent tout seuls, sans que personne perde une ligne.

import * as Y from 'yjs';

// Deux répliques déconnectées modifient le même texte
const a = new Y.Doc(), b = new Y.Doc();
a.getText('note').insert(0, 'Bonjour');
b.getText('note').insert(0, 'Salut ');

// Échange des mises à jour (peu importe l'ordre, ni le nombre de fois)
Y.applyUpdate(b, Y.encodeStateAsUpdate(a));
Y.applyUpdate(a, Y.encodeStateAsUpdate(b));

console.log(a.getText('note').toString() === b.getText('note').toString());
// true : convergence garantie sans serveur arbitre

Cas d'usage : Éditeurs collaboratifs, applications de prise de notes ou de terrain avec réseau intermittent, outils où la latence du serveur est inacceptable.

Anti-pattern : Appliquer un CRDT à des invariants métier forts (solde bancaire, stock) : la fusion automatique produit des états valides mais commercialement absurdes.
#architecture#distributed#frontend

Materialized Views

Architecture 🔴 Senior

Vues precalculees et stockées physiquement, optimisées pour la lecture. Mises a jour a partir des evenements ou des changements de données sources.

Un tableau de bord affiche en permanence : les chiffres sont precalcules, pas recalcules a chaque regard.

// PostgreSQL
CREATE MATERIALIZED VIEW order_stats AS
  SELECT user_id, COUNT(*), SUM(total)
  FROM orders GROUP BY user_id;
-- REFRESH MATERIALIZED VIEW order_stats;

Cas d'usage : Dashboards, rapports, requêtes complexes cote lecture en CQRS.

Anti-pattern : Ne pas rafraîchir les vues — données périmées sans que personne ne le sache.
#architecture#interview#performance

Mediator

Architecture 🟡 Mid

Définit un objet qui encapsulé les interactions entre un ensemble d'objets. Réduit le couplage en empêchant les objets de se référer directement.

La tour de contrôle d'un aéroport : les avions ne se parlent pas entre eux, ils passent tous par la tour.

class ChatRoom {
  send(msg, from, to) {
    to.receive(msg, from.name);
  }
}
// Les users ne se connaissent pas directement

Cas d'usage : Coordonner des composants UI interdépendants, chat rooms, systèmes de workflow.

Anti-pattern : Le médiator devient un God Object qui contient toute la logique métier.
#architecture#interview#gof#behavioral

Memento

Architecture 🟡 Mid? entretien

Capture et externalise l'état interne d'un objet sans violer l'encapsulation, pour pouvoir le restaurer plus tard.

La sauvegarde dans un jeu vidéo : tu captures l'état complet pour pouvoir y revenir si tu meurs.

class Editor {
  save() { return { content: this.content }; }
  restore(memento) { this.content = memento.content; }
}
const history = [editor.save()];

Cas d'usage : Undo/redo dans un éditeur, snapshots d'état, point de restauration transactionnel.

Anti-pattern : Stocker trop de mémentos en mémoire sans stratégie de nettoyage.
#architecture#interview#gof#behavioral

Microservices

Architecture 🟡 Mid

Style architectural ou l'application est décomposée en services indépendants, deployables séparément, communiquant via API ou messages.

Une équipe de spécialistes indépendants : chacun fait son métier, ils communiquent par téléphone.

// Service autonome
const app = express();
app.get('/users/:id', userController.findById);
app.listen(3001);
// Deploye independamment, sa propre DB

Cas d'usage : Grandes équipes, scaling indépendant, polyglottisme technologique.

Anti-pattern : Distributed monolith : microservices fortement couples qui doivent être déployés ensemble.
#architecture#interview#architecture-style

Middleware

Architecture 🟢 Junior

Fonction intermédiaire insérée dans un pipeline de traitement. Chaque middleware peut modifier la requête/réponse ou court-circuiter la chaîne.

Les contrôles de sécurité a l'aéroport : chaque étape vérifié quelque chose avant de te laisser passer.

const auth = (req, res, next) => {
  if (!req.headers.token) return res.status(401).end();
  req.user = verify(req.headers.token);
  next();
};

Cas d'usage : Authentification, logging, compression, CORS dans Express/Koa/NestJS.

Anti-pattern : Middleware qui fait trop de choses — il doit avoir une seule responsabilité.
#architecture#interview#best-practice

Modèle C4

Architecture 🟡 Mid? entretien

Méthode de Simon Brown pour représenter une architecture logicielle à quatre niveaux de zoom : Contexte (le système et ses utilisateurs/systèmes voisins), Conteneurs (applications, API, bases déployables), Composants (modules à l'intérieur d'un conteneur) et Code (classes, si nécessaire). Chaque niveau s'adresse à un public différent et reste lisible seul ; l'outil Structurizr permet de décrire le modèle en texte versionné.

Google Maps pour un logiciel : la vue pays, puis la ville, puis le quartier, puis la rue ; on choisit le zoom selon l'interlocuteur.

# workspace.dsl (Structurizr DSL) – modèle versionné avec le code
workspace {
  model {
    client = person "Client"
    boutique = softwareSystem "Boutique en ligne" {
      web = container "Front Next.js" "React"
      api = container "API commandes" "NestJS"
      db  = container "Base"          "PostgreSQL"
    }
    client -> web "Commande via"
    web -> api "Appelle" "HTTPS/JSON"
    api -> db  "Lit/écrit"
  }
  views { systemContext boutique { include * } container boutique { include * } }
}

Cas d'usage : Expliquer l'architecture à un nouvel arrivant, à un client ou en entretien sans noyer le contexte sous les détails d'implémentation.

Anti-pattern : Un unique schéma « boîtes et flèches » qui mélange serveurs, classes et utilisateurs : personne ne sait à quel niveau on parle.
#architecture#documentation#interview

Modular Monolith

Architecture 🟡 Mid

Monolithe organise en modules bien découplés avec des frontières claires. Combine la simplicité du monolithe et la modularité des microservices.

Un immeuble d'appartements : un seul bâtiment, mais chaque appartement est indépendant avec ses propres murs.

// Modules avec interfaces publiques
import { UserModule } from './modules/user';
import { OrderModule } from './modules/order';
// Communication via interfaces, pas d'acces DB croises

Cas d'usage : Équipe moyenne qui veut de la modularité sans la complexité opérationnelle des microservices.

Anti-pattern : Modules qui accèdent directement aux tables des autres modules — couplage cache.
#architecture#interview#architecture-style

Monolith

Architecture 🟢 Junior

Application déployée comme une seule unité ou tous les composants partagent le même processus et la même base de données. Simple mais limitant a l'échelle.

Un couteau suisse : tout est intégré dans un seul outil, pratique au début mais difficile a réparer pièce par pièce.

// Tout dans un seul projet
app.use('/users', userRoutes);
app.use('/orders', orderRoutes);
app.use('/payments', paymentRoutes);
// Un seul deploy, une seule DB

Cas d'usage : MVP, startups early-stage, équipes réduites ou le monolithe est le choix rationnel.

Anti-pattern : Commencer en microservices quand un monolithe suffirait — complexité prématurée.
#architecture#interview#architecture-style

Null Object

Architecture 🟢 Junior

Remplace les vérifications null par un objet neutre qui implémente l'interface attendue avec un comportement par défaut (no-op).

Un chauffeur fantôme dans un taxi autonome : le siège conducteur est occupe par quelque chose qui ne fait rien mais le système fonctionne.

class NullLogger {
  log() {} // no-op
  error() {} // no-op
}
// Au lieu de: if (logger) logger.log(...)

Cas d'usage : Éviter les vérifications null répétitives pour des dépendances optionnelles.

Anti-pattern : Retourner null au lieu d'un objet neutre, forçant des checks partout.
#architecture#interview#behavioral

Object Pool

Architecture 🟡 Mid

Maintient un ensemble d'objets réinitialisés prêts a l'emploi pour éviter le coût de création/destruction répétée. Gère le cycle de vie acquire/release.

Les caddies au supermarché : tu en prends un disponible, tu l'utilises, puis tu le rends.

class Pool {
  #available = [];
  acquire() { return this.#available.pop() ?? create(); }
  release(obj) { obj.reset(); this.#available.push(obj); }
}

Cas d'usage : Pool de connexions DB, threads, ou objets graphiques dans un moteur de jeu.

Anti-pattern : Ne pas réinitialiser les objets avant de les remettre dans le pool — données résiduelles.
#architecture#interview#gof#creational#performance

Observer

Architecture 🟢 Junior

Définit une dépendance un-a-plusieurs : quand un objet change d'état, tous ses dépendants sont notifies automatiquement.

S'abonner a une chaîne YouTube : tu es notifie a chaque nouvelle vidéo sans vérifier manuellement.

class EventEmitter {
  #subs = new Map();
  on(event, fn) { this.#subs.set(event, [...(this.#subs.get(event) ?? []), fn]); }
  emit(event, data) { this.#subs.get(event)?.forEach(fn => fn(data)); }
}

Cas d'usage : Systèmes de notifications, réactivé UI (React state), EventEmitter Node.js.

Anti-pattern : Oublier de se désabonner — fuite mémoire classique.
#architecture#interview#gof#behavioral

Onion Architecture

Architecture 🟡 Mid

Variante de Clean Architecture avec des couches concentriques : Domain Model, Domain Services, Application Services, Infrastructure. Dépendances vers le centre.

Les couches d'un oignon : chaque couche ne connaît que celle juste en dessous, le coeur est pur.

// Couches de l'interieur vers l'exterieur
// 1. Domain: Entity, ValueObject
// 2. Domain Services: business rules
// 3. Application: use cases, orchestration
// 4. Infrastructure: DB, HTTP, messaging

Cas d'usage : Applications enterprise avec logique métier complexe et multiple intégrations.

Anti-pattern : Infrastructure au centre qui force le domaine a dépendre d'implémentations concrètes.
#architecture#interview#architecture-style

Outbox Pattern

Architecture 🔴 Senior

Écrit les evenements dans une table outbox dans la même transaction que les données métier. Un processus sépare lit et publie ces evenements.

La boite 'courrier départ' au bureau : tu deposes ta lettre, et le facteur passe la relever plus tard.

await db.transaction(async (tx) => {
  await tx.insert('orders', order);
  await tx.insert('outbox', {
    event: 'OrderCreated', payload: order
  });
});

Cas d'usage : Garantir la cohérence entre l'état local et les evenements publies en microservices.

Anti-pattern : Publier l'evenement après le commit — si le publish échoué, l'état est incohérent.
#architecture#interview#microservices#distributed

Prototype

Architecture 🟡 Mid

Créé de nouveaux objets en clonant une instance existante plutôt qu'en la construisant from scratch. Utile quand la création est coûteuse.

Photocopier un document modèle puis modifier juste le nom et la date sur chaque copie.

const baseConfig = { theme: 'dark', lang: 'fr' };
const userConfig = { ...baseConfig, lang: 'en' };
// Ou: structuredClone(baseConfig);

Cas d'usage : Cloner des objets de configuration ou des entités de jeu avec des états precalcules.

Anti-pattern : Copie superficielle quand l'objet contient des références imbriquées (shallow vs deep clone).
#architecture#interview#gof#creational

Proxy

Architecture 🟡 Mid? entretien

Fournit un substitut ou un intermédiaire contrôlant l'accès a un objet. Peut ajouter lazy loading, cache, logging ou contrôle d'accès.

Un agent immobilier : il représente le propriétaire et filtre les visiteurs avant de leur donner accès.

const handler = {
  get(target, prop) {
    console.log(`Access: ${prop}`);
    return target[prop];
  }
};
const proxy = new Proxy(obj, handler);

Cas d'usage : Lazy loading d'images, cache transparent, protection d'accès, logging d'appels API.

Anti-pattern : Utiliser un proxy quand un simple appel de méthode suffirait — complexité inutile.
#architecture#interview#gof#structural

Pub/Sub

Architecture 🟡 Mid

Modèle de messagerie ou les émetteurs (publishers) envoient des messages a des canaux sans connaître les récepteurs (subscribers). Decouplage total.

Un journal : l'éditeur publie sans savoir qui lit, les abonnes reçoivent sans connaître l'éditeur personnellement.

// Redis Pub/Sub
await redis.publish('orders', JSON.stringify(order));
// Subscriber
redis.subscribe('orders', (msg) => {
  processOrder(JSON.parse(msg));
});

Cas d'usage : Communication inter-services dans les microservices, notifications temps réel, event streaming.

Anti-pattern : Utiliser Pub/Sub pour des appels synchrones — pas de garantie d'ordre ni de livraison.
#architecture#interview#messaging

Repository

Architecture 🟡 Mid

Abstrait l'accès aux données en encapsulant la logique de persistance derrière une interface de collection. Le domaine ignore la source de données.

Une bibliothécaire : tu demandes un livre par titre, elle sait ou le trouver sans que tu connaisses le système de classement.

class UserRepo {
  async findById(id) { return db.users.findOne({ id }); }
  async save(user) { return db.users.upsert(user); }
  async findByEmail(e) { return db.users.findOne({ email: e }); }
}

Cas d'usage : Découpler le domaine métier du framework ORM ou de la base de données.

Anti-pattern : Repository avec des méthodes spécifiques a l'ORM qui fuient dans le domaine.
#architecture#interview#ddd#best-practice

REST (Richardson Maturity Model)

Architecture 🟡 Mid

Style architectural pour APIs web base sur les ressources, les verbes HTTP et l'hypermedia. Le modèle de Richardson définit 4 niveaux de maturité (0 a 3).

Un plan de ville : les rues sont les URLs, les panneaux sont les méthodes HTTP, les liens sont les directions vers d'autres lieux.

// Niveau 2: resources + verbes HTTP
GET    /api/users       // Liste
GET    /api/users/42    // Detail
POST   /api/users       // Creation
PUT    /api/users/42    // Mise a jour
DELETE /api/users/42    // Suppression

Cas d'usage : APIs web standard, communication inter-services, APIs publiques.

Anti-pattern : POST /api/getUsers avec le verbe dans l'URL — niveau 0 du modèle de Richardson.
#architecture#interview#api

Retry Pattern

Architecture 🟢 Junior

Retente automatiquement une opération échouée avec un délai croissant (backoff exponentiel). Gère les erreurs transitoires.

Rappeler quelqu'un qui ne répond pas : tu attends 1 min, puis 5 min, puis 15 min avant de réessayer.

async function retry(fn, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try { return await fn(); }
    catch(e) { await sleep(2 ** i * 1000); }
  }
  throw new Error('Max retries reached');
}

Cas d'usage : Appels réseau, envoi d'emails, opérations cloud avec erreurs transitoires.

Anti-pattern : Retry sans backoff ni limite — bombarder un service déjà en difficulté.
#architecture#interview#resilience

Saga

Architecture 🔴 Senior

Gère les transactions distribuées via une séquence d'étapes locales avec des actions compensatoires en cas d'échec. Alternative a 2PC.

Organiser un voyage : réserver vol, hôtel, voiture. Si l'hôtel est indisponible, tu annules le vol déjà réservé.

const saga = [
  { exec: bookFlight, comp: cancelFlight },
  { exec: bookHotel,  comp: cancelHotel },
];
// Execute chaque etape; en cas d'echec, compense en ordre inverse

Cas d'usage : Transactions multi-services dans les microservices (commande, paiement, livraison).

Anti-pattern : Transactions distribuées 2PC qui verrouillent les ressources trop longtemps.
#architecture#interview#microservices#distributed

Screaming Architecture

Architecture 🟡 Mid

La structure des dossiers doit crier le domaine métier, pas le framework. On devrait deviner le métier en regardant l'arborescence.

Un plan de maison : on voit 'cuisine', 'chambre', 'salon' — pas 'mur', 'tuyau', 'câble électrique'.

// Mauvais: controllers/, services/, repositories/
// Bon:
src/
  ordering/      // Feature metier
  inventory/     // Feature metier
  shipping/      // Feature metier

Cas d'usage : Rendre le code navigable par concept métier plutôt que par pattern technique.

Anti-pattern : Dossiers par type technique (controllers, services, models) qui cachent le domaine.
#architecture#interview#best-practice

Separation of Concerns

Architecture 🟢 Junior

Découpé un programme en sections distinctes, chacune traitant une préoccupation spécifique. Minimise le chevauchement de responsabilités.

Les rayons d'un supermarché : fruits, viande, boissons — chaque rayon a sa spécialité.

// Separe: route, validation, business, persistence
router.post('/users', validate(schema), async (req, res) => {
  const user = await userService.create(req.body);
  res.json(user);
});

Cas d'usage : Fondement de toute architecture en couches : UI, logique, données.

Anti-pattern : Composant qui fait requête HTTP + validation + logique métier + rendu HTML.
#architecture#interview#principle

Serverless

Architecture 🟡 Mid

Modèle ou le cloud gère l'infrastructure. Le code s'exécute en fonctions éphémères déclenchées par des evenements, facturées a l'exécution.

Un taxi : tu paies la course, pas la voiture. Pas de parking, pas d'entretien.

// AWS Lambda
export const handler = async (event) => {
  const body = JSON.parse(event.body);
  const result = await processOrder(body);
  return { statusCode: 200, body: JSON.stringify(result) };
};

Cas d'usage : Workloads imprévisibles, APIs légères, traitement d'evenements, prototypage rapide.

Anti-pattern : Cold start ignore pour des APIs a faible latence — pas adapte aux appels synchrones critiques.
#architecture#interview#cloud

Service Locator

Architecture 🟡 Mid

Registre central qui fournit des services a la demande. Considère comme un anti-pattern car il cache les dépendances au lieu de les rendre explicites.

Les Pages Jaunes : tu cherches un plombier sans savoir lequel tu auras. Le problème : tu ne vois pas les dépendances.

class ServiceLocator {
  static #services = new Map();
  static register(name, svc) { this.#services.set(name, svc); }
  static get(name) { return this.#services.get(name); }
}

Cas d'usage : Legacy code ou l'injection de dépendances n'est pas disponible.

Anti-pattern : Ce pattern EST l'anti-pattern : dépendances cachées, tests difficiles, couplage au locator.
#architecture#interview#anti-pattern

Shared Kernel

Architecture 🔴 Senior

Partie de code ou de modèle partagée entre deux Bounded Contexts. Changée uniquement par accord mutuel des deux équipes.

Un mur mitoyen entre deux maisons : les deux propriétaires doivent se mettre d'accord avant de le modifier.

// shared-kernel/
//   types/Money.ts       - Partage entre Sales et Billing
//   types/CustomerId.ts  - ID commun
// Tout changement necessite accord des deux equipes

Cas d'usage : Partager des value objects ou des types communs entre deux contextes collaboratifs.

Anti-pattern : Shared kernel qui grossit et devient un monolithe déguisé.
#architecture#interview#ddd

Sidecar

Architecture 🔴 Senior

Déploie des fonctionnalités annexes dans un processus ou conteneur sépare, attache au service principal. Découplé les concerns transversaux.

Le side-car d'une moto : un passager (le proxy) voyage a cote sans modifier la moto elle-même.

# docker-compose.yml
services:
  app:
    image: my-app
  envoy-sidecar:
    image: envoyproxy/envoy
    network_mode: 'service:app'

Cas d'usage : Service mesh (Istio/Envoy), logging, monitoring, mTLS sans modifier le code applicatif.

Anti-pattern : Mettre trop de logique dans le sidecar — il doit rester un helper transparent.
#architecture#interview#microservices#cloud

Singleton

Architecture 🟢 Junior

Pattern qui garantit qu'une classe n'a qu'une seule instance et fournit un point d'accès global. Souvent considère comme un anti-pattern en contexte d'injection de dépendances.

Le président d'un pays : il n'y en a qu'un seul a la fois, et tout le monde sait comment le contacter.

class DB {
  static #instance;
  static getInstance() {
    if (!DB.#instance) DB.#instance = new DB();
    return DB.#instance;
  }
}

Cas d'usage : Connexion base de données ou logger quand on ne dispose pas de conteneur DI.

Anti-pattern : État global cache qui rend les tests unitaires impossibles et crée du couplage fort.
#architecture#interview#gof#creational

SOA (Service-Oriented Architecture)

Architecture 🟡 Mid

Architecture ou les fonctionnalités sont exposées comme des services réutilisables communiquant via des protocoles standardises. Prédécesseur des microservices.

Les services publics d'une ville : poste, mairie, hôpital — chacun rend un service spécifique accessible a tous.

// Service SOAP classique (legacy)
<wsdl:service name="UserService">
  <wsdl:port binding="tns:UserBinding">
    <soap:address location="http://api/users"/>
  </wsdl:port>
</wsdl:service>

Cas d'usage : Entreprises avec systèmes hétérogènés nécessitant interopérabilité via ESB.

Anti-pattern : ESB qui devient un point central de logique métier — bottleneck organisationnel.
#architecture#interview#architecture-style

SOLID

Architecture 🟢 Junior

Cinq principes de conception OO : Single Responsibility, Open/Closed, Liskov Substitution, Interface Ségrégation, Dependency Inversion. Fondamentaux du code maintenable.

Les cinq règles d'or de la construction : chacune empêche un type de défaut structurel.

// S: une classe, une raison de changer
// O: ouvert a l'extension, ferme a la modification
// L: les sous-types substituent le type parent
// I: interfaces specifiques > interface generale
// D: dependre des abstractions, pas des concretions

Cas d'usage : Guide de design pour écrire du code flexible, testable et maintenable.

Anti-pattern : God class qui fait tout — viole le S, et par effet domino tous les autres principes.
#architecture#interview#principle#best-practice

Specification

Architecture 🔴 Senior

Encapsulé une règle métier dans un objet réutilisable et composable. Les spécifications peuvent être combinées avec AND, OR, NOT.

Les filtres d'une recherche immobilière : 3 chambres ET jardin ET moins de 300k — chaque critère est un filtre composable.

class ActiveUserSpec {
  isSatisfiedBy(user) { return user.active && !user.banned; }
}
class AndSpec {
  constructor(a, b) { this.a = a; this.b = b; }
  isSatisfiedBy(x) { return this.a.isSatisfiedBy(x) && this.b.isSatisfiedBy(x); }
}

Cas d'usage : Règles métier complexes réutilisées dans les requêtes, validations et autorisations.

Anti-pattern : Dupliquer les règles métier dans le repository, le service et le contrôleur.
#architecture#interview#ddd

State

Architecture 🟡 Mid? entretien

Permet a un objet de modifier son comportement quand son état interne change. L'objet semble changer de classe.

Un distributeur de boissons : son comportement change selon qu'il attend une pièce, a reçu le paiement ou est en rupture.

class Order {
  setState(state) { this.state = state; }
  next() { this.state.next(this); }
}
class PendingState {
  next(order) { order.setState(new PaidState()); }
}

Cas d'usage : Machine a états pour workflows (commande, paiement), connexions réseau, UI.

Anti-pattern : Gros switch/case sur l'état au lieu d'encapsuler le comportement dans des classes d'état.
#architecture#interview#gof#behavioral

Strangler Fig

Architecture 🟡 Mid

Migre progressivement un système legacy en remplaçant ses fonctionnalités pièce par pièce derrière une façade, jusqu'a ce que l'ancien système soit éliminé.

Un figuier étrangleur qui pousse autour d'un arbre : le nouveau système grandit autour de l'ancien jusqu'a le remplacer.

app.use('/api/users', (req, res) => {
  if (featureFlag('new-users-service'))
    return proxy(req, newService);
  return proxy(req, legacyService);
});

Cas d'usage : Migration d'un monolithe vers des microservices sans big-bang risque.

Anti-pattern : Réécriture complète (big-bang) — projet risque qui échoue souvent.
#architecture#interview#migration

Strategy

Architecture 🟢 Junior

Définit une famille d'algorithmes interchangeables encapsulés séparément. Le client choisit l'algorithme a utiliser au runtime.

Choisir son moyen de transport : vélo, bus ou voiture — la destination est la même, la stratégie change.

const strategies = {
  credit: (amount) => chargeCard(amount),
  paypal: (amount) => paypalCheckout(amount),
};
const pay = strategies[method];

Cas d'usage : Algorithmes de tri, stratégies de paiement, politiques de retry configurables.

Anti-pattern : if/else ou switch sur le type d'algorithme éparpillés dans tout le code.
#architecture#interview#gof#behavioral

Tell, Don't Ask

Architecture 🟡 Mid

Dis a un objet ce qu'il doit faire au lieu de lui demander son état puis décider a sa place. Favorise l'encapsulation du comportement.

Dire au taxi 'emmené-moi a l'aéroport' au lieu de lui demander la carte et conduire toi-même.

// Ask (mauvais):
if (account.getBalance() >= amount) account.setBalance(...);
// Tell (bon):
account.withdraw(amount); // la logique est interne

Cas d'usage : Éliminer les Anemic Domain Models en mettant la logique dans les objets du domaine.

Anti-pattern : Getters/setters partout avec la logique métier dans les services.
#architecture#interview#principle

Template Method

Architecture 🟡 Mid

Définit le squelette d'un algorithme dans une méthode, en déléguant certaines étapes aux sous-classes. Structure sans rigidité.

Une recette de cuisine : les étapes sont fixes (préparer, cuire, servir) mais chaque chef personnalise les détails.

class Report {
  generate() {
    this.fetchData();
    this.format();
    this.export();
  }
  // sous-classes implementent fetchData, format, export
}

Cas d'usage : Pipelines de traitement, génération de rapports, tests avec setup/teardown.

Anti-pattern : Trop d'étapes abstraites rendant les sous-classes impossible a implémenter correctement.
#architecture#interview#gof#behavioral

Ubiquitous Language

Architecture 🟡 Mid

Langage commun partage entre développeurs et experts métier dans un Bounded Context. Le code utilise les mêmes termes que le métier.

Parler la même langue dans une équipe internationale : pas de traduction, pas de malentendu.

// Mauvais: class DataProcessor { handleItem() {} }
// Bon: class InvoiceGenerator { issueInvoice() {} }
// Les termes metier sont dans le code

Cas d'usage : Réduire les malentendus entre devs et métier, rendre le code auto-documentant.

Anti-pattern : Termes techniques dans le code métier (DataManager, Helper, Processor).
#architecture#interview#ddd

Unit of Work

Architecture 🔴 Senior

Maintient une liste d'objets modifies pendant une transaction et coordonne l'écriture des changements en une seule opération atomique.

Un panier d'achat : tu ajoutes/supprimes des articles, et tout est valide en une seule fois au passage en caisse.

class UnitOfWork {
  #changes = [];
  track(entity) { this.#changes.push(entity); }
  async commit() {
    await db.transaction(tx => this.#changes.forEach(e => tx.save(e)));
  }
}

Cas d'usage : Sauvegarder plusieurs entités modifiées en une transaction atomique (ORM comme EF Core).

Anti-pattern : Sauvegarder chaque entité individuellement sans transactionnalite.
#architecture#interview#ddd

Value Object

Architecture 🟡 Mid

Objet immutable défini par ses attributs, sans identité propre. Deux value objects avec les mêmes attributs sont égaux. Pas de setter.

Un billet de 20 euros : tu ne te soucies pas de QUEL billet c'est, seule la valeur compte.

class Money {
  constructor(readonly amount: number, readonly currency: string) {}
  add(other: Money) {
    if (this.currency !== other.currency) throw Error('Mismatch');
    return new Money(this.amount + other.amount, this.currency);
  }
}

Cas d'usage : Modéliser des concepts sans identité : Money, Émail, Address, DateRange.

Anti-pattern : Value object mutable — perd sa garantie d'égalité structurelle et d'immutabilite.
#architecture#interview#ddd

Vertical Slice Architecture

Architecture 🟡 Mid

Organise le code par feature (tranche verticale) plutôt que par couche technique. Chaque slice contient tout : handler, logique, persistance.

Couper un gâteau verticalement : chaque part contient toutes les couches (genoise, crème, glaçâge).

// features/create-user/
//   handler.ts    - HTTP handler
//   command.ts    - business logic
//   repository.ts - data access
//   test.ts       - tests

Cas d'usage : Équipes feature qui veulent minimiser les conflits de merge et le couplage inter-features.

Anti-pattern : Partager trop de code entre slices — revient a créer des couches déguisées.
#architecture#interview#architecture-style

Visitor

Architecture 🔴 Senior

Sépare un algorithme de la structure d'objets sur laquelle il opère. Permet d'ajouter de nouvelles opérations sans modifier les classes existantes.

Un inspecteur qui visite différents types de bâtiments : même démarche, mais le rapport diffère selon le bâtiment.

class TaxVisitor {
  visitBook(b) { return b.price * 0.05; }
  visitFood(f) { return f.price * 0.10; }
}
// item.accept(visitor)

Cas d'usage : Calculs sur un AST (compilateur), sérialisation polymorphe, rapports multi-formats.

Anti-pattern : Ajouter de nouveaux types de noeuds fréquemment — le visitor doit être modifie a chaque fois.
#architecture#interview#gof#behavioral

WebSocket vs SSE vs WebTransport

Architecture 🔴 Senior

Trois transports pour le temps réel. WebSocket : bidirectionnel, sur TCP, universel, mais sans reconnexion native. SSE (Server-Sent Events) : unidirectionnel serveur→client sur HTTP simple, reconnexion automatique, idéal pour notifications et flux de LLM. WebTransport : construit sur HTTP/3 (QUIC), flux multiples sans blocage en tête de ligne, datagrammes non fiables pour le jeu ou la vidéo ; Baseline depuis Safari 26.4 en mars 2026 (Chrome 97+, Firefox 114+).

Le téléphone (WebSocket, on se parle tous les deux), la radio (SSE, on écoûte), et la fibre multi-canaux (WebTransport : plusieurs conversations et une vidéo sur la même ligne, sans que l'une bloque l'autre).

// SSE : le plus simple pour du serveur → client (ex. streaming d'un LLM)
const es = new EventSource('/api/stream');
es.onmessage = (e) => appendToken(JSON.parse(e.data));  // reconnexion auto

// WebSocket : bidirectionnel (chat, jeu, curseurs collaboratifs)
const ws = new WebSocket('wss://api.example.com/rt');
ws.onmessage = (e) => handle(JSON.parse(e.data));
ws.send(JSON.stringify({ type: 'join', room: 'r1' }));

// WebTransport : HTTP/3, flux multiples + datagrammes (Baseline 2026)
const wt = new WebTransport('https://api.example.com:4433/wt');
await wt.ready;
const writer = wt.datagrams.writable.getWriter();
writer.write(new TextEncoder().encode('pos:12,48')); // perte tolérée

Cas d'usage : Choisir : notifications ou tokens d'IA → SSE ; chat, jeu au tour par tour, édition collaborative → WebSocket ; jeu temps réel, vidéo, très nombreux flux → WebTransport.

Anti-pattern : Ouvrir un WebSocket pour un simple flux de notifications descendant : SSE aurait suffi, avec reconnexion gratuite et compatibilité proxy.
#architecture#real-time#networking

YAGNI (You Aren't Gonna Need It)

Architecture 🟢 Junior

Ne pas implémenter une fonctionnalité tant qu'elle n'est pas réellement nécessaire. Les besoins futurs imagines se matérialisent rarement tels quels.

Ne pas construire un garage pour 4 voitures quand tu n'en as qu'une — et tu déménageras peut-être.

// YAGNI violé:
class User {
  // 'au cas ou on aurait besoin de multi-tenant'
  tenantId?: string;
  // 'au cas ou on supporterait l'i18n'
  locale?: string;
}

Cas d'usage : Éviter le code mort et la complexité prématurée en se concentrant sur le besoin actuel.

Anti-pattern : Ajouter des abstractions 'au cas ou' qui ne servent jamais et alourdissent le code.
#architecture#interview#principle