Architecture 93 termes

93 termes affichés

TypeBestPractice Concept Pattern Principle
Niveau 🟢 Junior 🟡 Mid 🔴 Senior

Abstract Factory

Architecture 🟡 Mid

Fournit une interface pour creer des familles d'objets lies sans specifier leurs classes concretes. 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 : Creer des composants UI coherents par theme ou des connecteurs DB par provider.

Anti-pattern : Creer 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 electrique : ta prise francaise fonctionne dans une prise anglaise grace a l'adaptateur.

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

Cas d'usage : Integrer 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

Aggregate

Architecture 🔴 Senior

Groupe d'entites et de value objects traite comme une unite de coherence transactionnelle. Toutes les modifications passent par la racine d'agregat.

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 metier dans un perimetre transactionnel defini.

Anti-pattern : Agregats trop gros qui verrouillent trop de donnees — contention en prod.
#architecture#interview#ddd

Aggregate Root

Architecture 🔴 Senior

Entite principale d'un agregat qui sert de point d'entree unique. Les objets externes ne peuvent referencer que la racine, jamais les entites internes.

Le chef d'equipe : toute communication avec l'equipe passe par lui pour garantir la coherence.

// 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 : Proteger les invariants metier en forçant toutes les operations via un point d'entree unique.

Anti-pattern : Acceder directement aux entites internes de l'agregat depuis l'exterieur.
#architecture#interview#ddd

Ambassador

Architecture 🔴 Senior

Proxy helper deploye a cote d'un service pour gerer les connexions sortantes (retry, circuit breaker, monitoring). Variante du Sidecar.

Un ambassadeur diplomatique : il represente ton pays et gere 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 : Implementer 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 systeme externe ou legacy. Empeche les concepts etrangers de polluer votre modele.

Un traducteur-interprete 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 : Integrer un systeme 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

Point d'entree unique pour toutes les requetes client. Gere routage, authentification, rate limiting, aggregation et transformation.

La reception d'un hotel : 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 : Entree unifiee pour les microservices avec concerns transversaux centralises.

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

API Pagination (Cursor vs Offset)

Architecture 🟡 Mid

Offset : skip/limit simple mais instable sur les donnees qui changent. Cursor : basee sur un marqueur stable, performante a grande echelle.

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

Limite le nombre de requetes qu'un client peut faire dans un intervalle de temps. Protege contre les abus, le DDoS et la surcharge.

Le nombre max de retraits au distributeur par jour : protege 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, equite d'acces 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

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

Les editions d'un manuel scolaire : la v1 reste disponible pendant que la v2 est utilisee par les nouveaux etudiants.

// 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 controlez pas et qui ne migrent pas en meme temps.

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

Application Service

Architecture 🟡 Mid

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

Un chef de projet : il coordonne les equipes mais ne code pas lui-meme.

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 metier dans le service applicatif au lieu du domaine.
#architecture#interview#ddd

BFF (Backend for Frontend)

Architecture 🟡 Mid

Un backend dedie par type de client (web, mobile, IoT) qui adapte et agrege les donnees des services backend pour les besoins specifiques de chaque frontend.

Un assistant personnel par langue : chacun traduit et resume 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 donnees riches et le mobile de donnees legeres.

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

Bounded Context

Architecture 🟡 Mid

Frontiere explicite dans laquelle un modele de domaine particulier s'applique. Chaque contexte a son propre langage et ses propres regles.

Les departements d'une entreprise : 'client' signifie prospect en commercial et compte en comptabilite.

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

Cas d'usage : Decomposer un systeme complexe en sous-domaines autonomes avec des frontieres claires.

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

Bridge

Architecture 🔴 Senior

Decouple une abstraction de son implementation pour qu'elles puissent varier independamment. Evite l'explosion combinatoire de sous-classes.

Une telecommande universelle : la telecommande (abstraction) fonctionne avec n'importe quelle TV (implementation).

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) generent trop de sous-classes.

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

Builder

Architecture 🟢 Junior

Separe la construction d'un objet complexe de sa representation. Permet de construire etape par etape avec une API fluide.

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

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

Cas d'usage : Construction de requetes SQL, objets de configuration ou DTOs avec beaucoup de parametres optionnels.

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

Chain of Responsibility

Architecture 🟡 Mid

Passe une requete le long d'une chaine de handlers. Chaque handler decide de traiter la requete ou de la passer au suivant.

Le service client : operateur, 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 : Chaine trop longue sans handler par defaut — la requete tombe dans le vide.
#architecture#interview#gof#behavioral

Circuit Breaker

Architecture 🟡 Mid

Detecte les defaillances et empeche l'application de tenter des operations vouees a l'echec. Trois etats : ferme, ouvert, semi-ouvert.

Un disjoncteur electrique : il coupe le courant quand il detecte une surcharge pour proteger 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 eviter les cascades de pannes.

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

Clean Architecture

Architecture 🟡 Mid

Architecture en couches concentriques ou les dependances pointent vers l'interieur. Le domaine est au centre, independant des frameworks et de l'infrastructure.

Un oignon : chaque couche protege le coeur (domaine) des details exterieurs (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 metier riche qui doit survivre aux changements de frameworks.

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

Command

Architecture 🟡 Mid

Encapsule une requete comme un objet, permettant de parametrer, mettre en file d'attente, journaliser et annuler des operations.

Un bon de commande au restaurant : il capture l'intention, peut etre 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 : Systeme undo/redo, file de taches asynchrones, CQRS command side.

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

Composite

Architecture 🟡 Mid

Compose des objets en structures arborescentes pour representer des hierarchies partie-tout. Les clients traitent uniformement 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 meme facon.

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, systemes de fichiers, organigrammes.

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

Composition over Inheritance

Architecture 🟡 Mid

Favoriser la composition d'objets plutot que l'heritage de classes pour reutiliser du comportement. Plus flexible et moins fragile.

Les LEGO : tu assembles des pieces pour creer des formes variees, au lieu de mouler une piece 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'heritage simple ou le diamond problem.

Anti-pattern : Hierarchies d'heritage profondes (5+ niveaux) — fragiles et impossibles a comprendre.
#architecture#interview#principle

Content Negotiation

Architecture 🟡 Mid

Mecanisme HTTP ou le client et le serveur se mettent d'accord sur le format de la reponse 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 differents clients.

Anti-pattern : Ignorer le header Accept et toujours renvoyer JSON — mauvaise experience 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. Definit les contrats d'integration.

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

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

Cas d'usage : Visualiser et planifier les integrations entre sous-domaines d'un systeme complexe.

Anti-pattern : Integrer des contextes sans definir la relation — couplage implicite non gere.
#architecture#interview#ddd

Convention over Configuration

Architecture 🟡 Mid

Privilegier des conventions sensees par defaut plutot que de forcer une configuration explicite. Le developpeur ne configure que ce qui devie de la convention.

Une reunion hebdo toujours lundi 9h : pas besoin de reinviter chaque semaine, seules les exceptions sont signalees.

// 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 : reduire 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

Mecanisme de securite HTTP qui permet a un serveur d'indiquer quelles origines sont autorisees a acceder a ses ressources. Gere via des headers specifiques.

Le badge d'acces a un immeuble : seuls les employes autorises (origines) peuvent entrer dans certains etages (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 different 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 Segregation : separe les modeles de lecture (Query) et d'ecriture (Command). Permet d'optimiser chaque cote independamment.

Un guichet de banque : un guichet pour deposer (ecriture), 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/ecriture tres differents ou des modeles de lecture complexes.

Anti-pattern : Appliquer CQRS a un simple CRUD — complexite injustifiee.
#architecture#interview#architecture-style

CQS (Command Query Separation)

Architecture 🟡 Mid

Une methode est soit une commande (modifie l'etat, ne retourne rien) soit une query (retourne des donnees, ne modifie rien). Jamais les deux.

Au guichet : soit tu deposes un cheque (commande), soit tu consultes ton solde (query). Pas les deux en meme 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 previsible et plus facile a raisonner.

Anti-pattern : Methodes qui modifient l'etat et retournent des resultats — effets de bord caches.
#architecture#interview#principle

DataLoader

Architecture 🟡 Mid

Utilitaire qui batch et cache les requetes de donnees pour resoudre le probleme N+1 dans GraphQL. Regroupe les appels DB d'un meme tick en une seule requete.

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 entites liees pour eviter N+1 requetes.

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

Decorator

Architecture 🟡 Mid

Ajoute dynamiquement des responsabilites a un objet sans modifier sa classe. Offre une alternative flexible a l'heritage.

Ajouter des garnitures sur une pizza : chaque garniture enveloppe la precedente et ajoute son propre gout.

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 facon transparente.

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

Dependency Inversion Principle

Architecture 🟡 Mid

Les modules de haut niveau ne doivent pas dependre des modules de bas niveau. Les deux doivent dependre d'abstractions. Les abstractions ne dependent pas des details.

Une prise electrique : l'appareil et le reseau dependent 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 decoupler les couches.

Anti-pattern : import direct de l'implementation concrete dans le module de haut niveau.
#architecture#interview#principle

Domain Event

Architecture 🟡 Mid

Evenement significatif qui s'est produit dans le domaine metier. Nomme au passe (OrderPlaced, PaymentReceived). Declenche des reactions dans d'autres contextes.

L'annonce au micro dans un magasin : 'Nouveau produit disponible en rayon 3' — tous les interesses reagissent.

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

Cas d'usage : Decoupler les side effects (emails, analytics) de la logique metier principale.

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

Domain Service

Architecture 🟡 Mid

Service stateless qui encapsule une logique metier qui ne rentre naturellement dans aucune entite ou value object. Opere sur plusieurs agregats.

Un notaire : il ne possede 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 : Operations metier impliquant plusieurs agregats qui ne peuvent pas etre attribuees a un seul.

Anti-pattern : Domain service anemique qui ne fait que deleguer au repository — logique metier absente.
#architecture#interview#ddd

DRY (Don't Repeat Yourself)

Architecture 🟢 Junior

Chaque piece de connaissance doit avoir une representation unique et non ambigue dans le systeme. Evite la duplication de logique.

Une source unique de verite : 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 regles metier, validations et transformations pour eviter les incoherences.

Anti-pattern : DRY premature : abstraire du code qui se ressemble mais n'a pas la meme raison de changer.
#architecture#interview#principle

Entity (DDD)

Architecture 🟡 Mid

Objet du domaine defini par son identite unique plutot que par ses attributs. Deux entites avec les memes attributs mais des IDs differents sont distinctes.

Deux jumeaux identiques : meme apparence, mais ce sont deux personnes distinctes avec des identites differentes.

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

Cas d'usage : Modeliser des concepts metier qui ont un cycle de vie et une identite persistante.

Anti-pattern : Comparer des entites par valeur au lieu de par identite.
#architecture#interview#ddd

ETag / If-None-Match

Architecture 🟡 Mid

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

Un numero de version sur un document : si tu as deja la derniere 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 : Reduire la bande passante et la charge serveur pour les ressources rarement modifiees.

Anti-pattern : Generer un ETag couteux (hash de tout le body) sur chaque requete — annule le gain.
#architecture#interview#api#performance

Event Bus

Architecture 🟡 Mid

Canal central de communication par evenements au sein d'une application. Les composants publient et s'abonnent sans se connaitre 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 decouples.

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

Event Sourcing

Architecture 🔴 Senior

Stocke l'etat comme une sequence immuable d'evenements plutot que comme l'etat courant. L'etat se reconstruit en rejouant les evenements.

Un releve 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, systemes financiers, undo/redo, debug temporel.

Anti-pattern : Evenements mutables ou supprimes — on perd la propriete 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 systeme de sonnettes dans un restaurant : le cuisinier sonne quand le plat est pret, le serveur reagit.

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

Cas d'usage : Systemes reactifs, microservices decouples, traitement temps reel de flux de donnees.

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

Facade

Architecture 🟢 Junior

Fournit une interface simplifiee a un sous-systeme complexe. Cache la complexite derriere une API unifiee et facile a utiliser.

Le bouton 'demarrer' d'une voiture : un geste simple qui declenche demarreur, 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-systeme avec plusieurs classes interdependantes.

Anti-pattern : Transformer la facade en God Object qui fait tout au lieu de deleguer.
#architecture#interview#gof#structural

Factory Method

Architecture 🟢 Junior

Definit une interface pour creer un objet, mais laisse les sous-classes decider quelle classe instancier. Permet de deleguer la logique de creation.

Un restaurant avec une carte : tu choisis 'pizza' et la cuisine decide quelle recette exacte preparer.

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 creation varie selon le contexte et qu'on veut eviter les if/else dans le code client.

Anti-pattern : Mettre toute la logique de creation dans le constructeur au lieu de la deleguer.
#architecture#interview#gof#creational

Fail Fast

Architecture 🟢 Junior

Detecter et signaler les erreurs le plus tot possible plutot que de les propager silencieusement. Reduit le temps de debug et les effets de bord.

Le voyant moteur : mieux vaut s'arreter 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'entrees, assertions en debut de fonction, guard clauses.

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

Flyweight

Architecture 🔴 Senior

Partage efficacement des objets a grain fin pour economiser la memoire. Separe l'etat intrinseque (partage) de l'etat extrinseque (contextuel).

Les caracteres d'imprimerie : chaque lettre 'A' utilise le meme bloc metallique, 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'elements similaires (arbres dans un jeu, caracteres dans un editeur).

Anti-pattern : Creer une nouvelle instance pour chaque element alors que 90% de l'etat est identique.
#architecture#interview#gof#structural#performance

GraphQL

Architecture 🟡 Mid

Langage de requete pour APIs ou le client specifie exactement les donnees souhaitees. 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 donnees varies (mobile vs web), dashboards complexes.

Anti-pattern : Probleme N+1 : chaque field declenche une requete DB sans DataLoader.
#architecture#interview#api

gRPC

Architecture 🟡 Mid

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

Un talkie-walkie numerique : 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 reel, APIs internes.

Anti-pattern : Utiliser gRPC pour des APIs publiques consommees 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 reponses 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-documentees 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 exterieur. Isole le coeur metier.

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 donnees 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 coordonnees, 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'etre appele par lui.
#architecture#interview#principle

Idempotency

Architecture 🟡 Mid

Une operation idempotente produit le meme resultat qu'elle soit executee une ou plusieurs fois. Essentiel pour les retries et la fiabilite des APIs.

Appuyer sur le bouton d'un ascenseur deja allume : le resultat est le meme, 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, creation de ressources, toute operation qui peut etre retentee par le client.

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

Interface Segregation Principle

Architecture 🟡 Mid

Un client ne doit pas etre force de dependre d'interfaces qu'il n'utilise pas. Preferer plusieurs interfaces specifiques a une seule interface generale.

Une telecommande par appareil plutot qu'une telecommande 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 : Eviter les implementations vides ou les throws 'not supported' dans les classes.

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

Interpreter

Architecture 🔴 Senior

Definit une representation grammaticale pour un langage et un interpreteur pour evaluer ses expressions. Utilisee pour les DSL.

Un traducteur humain : il comprend la grammaire de la langue source et produit l'equivalent 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 regles metier, parseurs d'expressions mathematiques, langages de requetes.

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 elements 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 donnees 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 simplicite doit etre un objectif cle du design. La complexite inutile est le pire ennemi de la maintenabilite.

Un interrupteur on/off vs un panneau de controle de centrale nucleaire — choisis la simplicite adaptee.

// 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 resout le probleme 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. Evite les chaines d'appels (train wreck) qui creent 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 : Reduire le couplage entre objets et rendre le code plus resilient aux changements.

Anti-pattern : Chaines de getters qui exposent la structure interne de tout le graphe d'objets.
#architecture#interview#principle

Materialized Views

Architecture 🔴 Senior

Vues precalculees et stockees physiquement, optimisees pour la lecture. Mises a jour a partir des evenements ou des changements de donnees 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, requetes complexes cote lecture en CQRS.

Anti-pattern : Ne pas rafraichir les vues — donnees perimees sans que personne ne le sache.
#architecture#interview#performance

Mediator

Architecture 🟡 Mid

Definit un objet qui encapsule les interactions entre un ensemble d'objets. Reduit le couplage en empechant les objets de se referer directement.

La tour de controle d'un aeroport : 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 interdependants, chat rooms, systemes de workflow.

Anti-pattern : Le mediator devient un God Object qui contient toute la logique metier.
#architecture#interview#gof#behavioral

Memento

Architecture 🟡 Mid

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

La sauvegarde dans un jeu video : tu captures l'etat 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 editeur, snapshots d'etat, point de restauration transactionnel.

Anti-pattern : Stocker trop de mementos en memoire sans strategie de nettoyage.
#architecture#interview#gof#behavioral

Microservices

Architecture 🟡 Mid

Style architectural ou l'application est decomposee en services independants, deployables separement, communiquant via API ou messages.

Une equipe de specialistes independants : chacun fait son metier, ils communiquent par telephone.

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

Cas d'usage : Grandes equipes, scaling independant, polyglottisme technologique.

Anti-pattern : Distributed monolith : microservices fortement couples qui doivent etre deployes ensemble.
#architecture#interview#architecture-style

Middleware

Architecture 🟢 Junior

Fonction intermediaire inseree dans un pipeline de traitement. Chaque middleware peut modifier la requete/reponse ou court-circuiter la chaine.

Les controles de securite a l'aeroport : chaque etape verifie 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 responsabilite.
#architecture#interview#best-practice

Modular Monolith

Architecture 🟡 Mid

Monolithe organise en modules bien decouples avec des frontieres claires. Combine la simplicite du monolithe et la modularite des microservices.

Un immeuble d'appartements : un seul batiment, mais chaque appartement est independant 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 : Equipe moyenne qui veut de la modularite sans la complexite operationnelle des microservices.

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

Monolith

Architecture 🟢 Junior

Application deployee comme une seule unite ou tous les composants partagent le meme processus et la meme base de donnees. Simple mais limitant a l'echelle.

Un couteau suisse : tout est integre dans un seul outil, pratique au debut mais difficile a reparer piece par piece.

// 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, equipes reduites ou le monolithe est le choix rationnel.

Anti-pattern : Commencer en microservices quand un monolithe suffirait — complexite prematuree.
#architecture#interview#architecture-style

Null Object

Architecture 🟢 Junior

Remplace les verifications null par un objet neutre qui implemente l'interface attendue avec un comportement par defaut (no-op).

Un chauffeur fantome dans un taxi autonome : le siege conducteur est occupe par quelque chose qui ne fait rien mais le systeme fonctionne.

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

Cas d'usage : Eviter les verifications null repetitives pour des dependances 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 reinitialises prets a l'emploi pour eviter le cout de creation/destruction repetee. Gere le cycle de vie acquire/release.

Les caddies au supermarche : 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 reinitialiser les objets avant de les remettre dans le pool — donnees residuelles.
#architecture#interview#gof#creational#performance

Observer

Architecture 🟢 Junior

Definit une dependance un-a-plusieurs : quand un objet change d'etat, tous ses dependants sont notifies automatiquement.

S'abonner a une chaine YouTube : tu es notifie a chaque nouvelle video sans verifier 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 : Systemes de notifications, reactive UI (React state), EventEmitter Node.js.

Anti-pattern : Oublier de se desabonner — fuite memoire classique.
#architecture#interview#gof#behavioral

Onion Architecture

Architecture 🟡 Mid

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

Les couches d'un oignon : chaque couche ne connait 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 metier complexe et multiple integrations.

Anti-pattern : Infrastructure au centre qui force le domaine a dependre d'implementations concretes.
#architecture#interview#architecture-style

Outbox Pattern

Architecture 🔴 Senior

Ecrit les evenements dans une table outbox dans la meme transaction que les donnees metier. Un processus separe lit et publie ces evenements.

La boite 'courrier depart' 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 coherence entre l'etat local et les evenements publies en microservices.

Anti-pattern : Publier l'evenement apres le commit — si le publish echoue, l'etat est incoherent.
#architecture#interview#microservices#distributed

Prototype

Architecture 🟡 Mid

Cree de nouveaux objets en clonant une instance existante plutot qu'en la construisant from scratch. Utile quand la creation est couteuse.

Photocopier un document modele 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 entites de jeu avec des etats precalcules.

Anti-pattern : Copie superficielle quand l'objet contient des references imbriquees (shallow vs deep clone).
#architecture#interview#gof#creational

Proxy

Architecture 🟡 Mid

Fournit un substitut ou un intermediaire controlant l'acces a un objet. Peut ajouter lazy loading, cache, logging ou controle d'acces.

Un agent immobilier : il represente le proprietaire et filtre les visiteurs avant de leur donner acces.

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'acces, logging d'appels API.

Anti-pattern : Utiliser un proxy quand un simple appel de methode suffirait — complexite inutile.
#architecture#interview#gof#structural

Pub/Sub

Architecture 🟡 Mid

Modele de messagerie ou les emetteurs (publishers) envoient des messages a des canaux sans connaitre les recepteurs (subscribers). Decouplage total.

Un journal : l'editeur publie sans savoir qui lit, les abonnes recoivent sans connaitre l'editeur 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 reel, 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'acces aux donnees en encapsulant la logique de persistance derriere une interface de collection. Le domaine ignore la source de donnees.

Une bibliothecaire : tu demandes un livre par titre, elle sait ou le trouver sans que tu connaisses le systeme 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 : Decoupler le domaine metier du framework ORM ou de la base de donnees.

Anti-pattern : Repository avec des methodes specifiques 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 modele de Richardson definit 4 niveaux de maturite (0 a 3).

Un plan de ville : les rues sont les URLs, les panneaux sont les methodes 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 modele de Richardson.
#architecture#interview#api

Retry Pattern

Architecture 🟢 Junior

Retente automatiquement une operation echouee avec un delai croissant (backoff exponentiel). Gere les erreurs transitoires.

Rappeler quelqu'un qui ne repond pas : tu attends 1 min, puis 5 min, puis 15 min avant de reessayer.

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 reseau, envoi d'emails, operations cloud avec erreurs transitoires.

Anti-pattern : Retry sans backoff ni limite — bombarder un service deja en difficulte.
#architecture#interview#resilience

Saga

Architecture 🔴 Senior

Gere les transactions distribuees via une sequence d'etapes locales avec des actions compensatoires en cas d'echec. Alternative a 2PC.

Organiser un voyage : reserver vol, hotel, voiture. Si l'hotel est indisponible, tu annules le vol deja reserve.

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 distribuees 2PC qui verrouillent les ressources trop longtemps.
#architecture#interview#microservices#distributed

Screaming Architecture

Architecture 🟡 Mid

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

Un plan de maison : on voit 'cuisine', 'chambre', 'salon' — pas 'mur', 'tuyau', 'cable electrique'.

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

Cas d'usage : Rendre le code navigable par concept metier plutot 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

Decoupe un programme en sections distinctes, chacune traitant une preoccupation specifique. Minimise le chevauchement de responsabilites.

Les rayons d'un supermarche : fruits, viande, boissons — chaque rayon a sa specialite.

// 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, donnees.

Anti-pattern : Composant qui fait requete HTTP + validation + logique metier + rendu HTML.
#architecture#interview#principle

Serverless

Architecture 🟡 Mid

Modele ou le cloud gere l'infrastructure. Le code s'execute en fonctions ephemeres declenchees par des evenements, facturees a l'execution.

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 imprevisibles, APIs legeres, 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. Considere comme un anti-pattern car il cache les dependances au lieu de les rendre explicites.

Les Pages Jaunes : tu cherches un plombier sans savoir lequel tu auras. Le probleme : tu ne vois pas les dependances.

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 dependances n'est pas disponible.

Anti-pattern : Ce pattern EST l'anti-pattern : dependances cachees, tests difficiles, couplage au locator.
#architecture#interview#anti-pattern

Shared Kernel

Architecture 🔴 Senior

Partie de code ou de modele partagee entre deux Bounded Contexts. Changee uniquement par accord mutuel des deux equipes.

Un mur mitoyen entre deux maisons : les deux proprietaires 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 deguise.
#architecture#interview#ddd

Sidecar

Architecture 🔴 Senior

Deploie des fonctionnalites annexes dans un processus ou conteneur separe, attache au service principal. Decouple les concerns transversaux.

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

# 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'acces global. Souvent considere comme un anti-pattern en contexte d'injection de dependances.

Le president 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 donnees ou logger quand on ne dispose pas de conteneur DI.

Anti-pattern : Etat global cache qui rend les tests unitaires impossibles et cree du couplage fort.
#architecture#interview#gof#creational

SOA (Service-Oriented Architecture)

Architecture 🟡 Mid

Architecture ou les fonctionnalites sont exposees comme des services reutilisables communiquant via des protocoles standardises. Predecesseur des microservices.

Les services publics d'une ville : poste, mairie, hopital — chacun rend un service specifique 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 systemes heterogenes necessitant interoperabilite via ESB.

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

SOLID

Architecture 🟢 Junior

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

Les cinq regles d'or de la construction : chacune empeche un type de defaut 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 ecrire 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

Encapsule une regle metier dans un objet reutilisable et composable. Les specifications peuvent etre combinees avec AND, OR, NOT.

Les filtres d'une recherche immobiliere : 3 chambres ET jardin ET moins de 300k — chaque critere 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 : Regles metier complexes reutilisees dans les requetes, validations et autorisations.

Anti-pattern : Dupliquer les regles metier dans le repository, le service et le controleur.
#architecture#interview#ddd

State

Architecture 🟡 Mid

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

Un distributeur de boissons : son comportement change selon qu'il attend une piece, a recu 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 etats pour workflows (commande, paiement), connexions reseau, UI.

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

Strangler Fig

Architecture 🟡 Mid

Migre progressivement un systeme legacy en remplacant ses fonctionnalites piece par piece derriere une facade, jusqu'a ce que l'ancien systeme soit elimine.

Un figuier etrangleur qui pousse autour d'un arbre : le nouveau systeme 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 : Reecriture complete (big-bang) — projet risque qui echoue souvent.
#architecture#interview#migration

Strategy

Architecture 🟢 Junior

Definit une famille d'algorithmes interchangeables encapsules separement. Le client choisit l'algorithme a utiliser au runtime.

Choisir son moyen de transport : velo, bus ou voiture — la destination est la meme, la strategie change.

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

Cas d'usage : Algorithmes de tri, strategies de paiement, politiques de retry configurables.

Anti-pattern : if/else ou switch sur le type d'algorithme eparpilles 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 etat puis decider a sa place. Favorise l'encapsulation du comportement.

Dire au taxi 'emmene-moi a l'aeroport' au lieu de lui demander la carte et conduire toi-meme.

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

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

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

Template Method

Architecture 🟡 Mid

Definit le squelette d'un algorithme dans une methode, en deleguant certaines etapes aux sous-classes. Structure sans rigidite.

Une recette de cuisine : les etapes sont fixes (preparer, cuire, servir) mais chaque chef personnalise les details.

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

Cas d'usage : Pipelines de traitement, generation de rapports, tests avec setup/teardown.

Anti-pattern : Trop d'etapes abstraites rendant les sous-classes impossible a implementer correctement.
#architecture#interview#gof#behavioral

Ubiquitous Language

Architecture 🟡 Mid

Langage commun partage entre developpeurs et experts metier dans un Bounded Context. Le code utilise les memes termes que le metier.

Parler la meme langue dans une equipe 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 : Reduire les malentendus entre devs et metier, rendre le code auto-documentant.

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

Unit of Work

Architecture 🔴 Senior

Maintient une liste d'objets modifies pendant une transaction et coordonne l'ecriture des changements en une seule operation 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 entites modifiees en une transaction atomique (ORM comme EF Core).

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

Value Object

Architecture 🟡 Mid

Objet immutable defini par ses attributs, sans identite propre. Deux value objects avec les memes attributs sont egaux. 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 : Modeliser des concepts sans identite : Money, Email, Address, DateRange.

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

Vertical Slice Architecture

Architecture 🟡 Mid

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

Couper un gateau verticalement : chaque part contient toutes les couches (genoise, creme, glaçage).

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

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

Anti-pattern : Partager trop de code entre slices — revient a creer des couches deguisees.
#architecture#interview#architecture-style

Visitor

Architecture 🔴 Senior

Separe un algorithme de la structure d'objets sur laquelle il opere. Permet d'ajouter de nouvelles operations sans modifier les classes existantes.

Un inspecteur qui visite differents types de batiments : meme demarche, mais le rapport differe selon le batiment.

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), serialisation polymorphe, rapports multi-formats.

Anti-pattern : Ajouter de nouveaux types de noeuds frequemment — le visitor doit etre modifie a chaque fois.
#architecture#interview#gof#behavioral

YAGNI (You Aren't Gonna Need It)

Architecture 🟢 Junior

Ne pas implementer une fonctionnalite tant qu'elle n'est pas reellement necessaire. Les besoins futurs imagines se materialisent rarement tels quels.

Ne pas construire un garage pour 4 voitures quand tu n'en as qu'une — et tu demenageras peut-etre.

// 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 : Eviter le code mort et la complexite prematuree 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

Autres stacks

Advanced Ecosystem CSS-in-JS DevOps HTML / CSS JavaScript MongoDB Mongoose NestJS Personalities PHP PostgreSQL React Sass Styled-Components Tailwind CSS Testing TypeScript WordPress
← Retour au lexique complet