MFormations
Modern Backend Engineering

Chapitre 21

21 - Livres Recommandés

21 - Livres Recommandés

Chapitre 21 : Livres Fondamentaux pour l'Ingénieur Backend

Introduction

Ce chapitre présente des résumés détaillés des livres essentiels pour tout ingénieur backend. Chaque résumé couvre les concepts clés, les exemples pratiques, et comment appliquer ces connaissances dans vos projets.


1. Designing Data-Intensive Applications

Auteur : Martin Kleppmann Éditeur : O'Reilly Media Année : 2017 Pages : 616 Difficulté : Avancée Note : ★★★★★ (4.8/5)

Pourquoi lire ce livre

"Designing Data-Intensive Applications" (DDIA) est considéré comme la bible des systèmes distribués. Il couvre les fondations de la fiabilité, de la scalabilité et de la maintenabilité des systèmes de données. Indispensable pour tout ingénieur backend travaillant sur des systèmes à grande échelle.

Partie I : Fondations des Systèmes de Données

Chapitre 1 : Fiabilité, Scalabilité, Maintenabilité

Fiabilité : Le système continue de fonctionner correctement même en cas de panne.

  • Pannes hardware : Disques, RAM, réseau (redondance, RAID, replication)
  • Pannes software : Bugs, processus zombies, cascading failures (isolation)
  • Erreurs humaines : La cause la plus fréquente (tests, déploiements progressifs, sandbox)

Scalabilité : Le système peut faire face à l'augmentation de la charge.

  • Latence vs débit : Percentiles (p50, p95, p99, p999) pour mesurer l'expérience utilisateur
  • Head-of-line blocking : Un appel lent peut bloquer d'autres appels
  • Approches : Scaling vertical (plus gros serveur) vs horizontal (plus de serveurs)

Maintenabilité : Le système est facile à faire évoluer et à opérer.

  • Operability : Facilité d'exploitation
  • Simplicity : Complexité accidentelle vs essentielle
  • Evolvability : Facilité de changement

Chapitre 2 : Modèles de Données et Langages de Requêtes

SQL vs NoSQL : Le grand débat.

  • SQL : Schéma rigide, jointures, transactions ACID, maturité
  • Document (MongoDB) : Schéma flexible, relations limitées, aggrégation
  • Graphe (Neo4j) : Relations complexes, traversées, recommandations
  • Key-Value (Redis) : Cache, sessions, compteurs

Normalisation vs Dénormalisation :

  • Normalisé : Évite la duplication, jointures coûteuses
  • Dénormalisé : Lectures rapides, écritures complexes (maintenir les copies)

Le problème de l'Object-Relational Mismatch : Les ORMs tentent de combler le fossé entre le modèle objet et le modèle relationnel, mais avec des compromis.

Chapitre 3 : Stockage et Récupération

Index : Structures pour accélérer les lectures.

B-Trees :

  • Structure d'arbre équilibré
  • Insertion/suppression sans réorganisation complète
  • Adapté aux workloads mixtes (lecture + écriture)
  • Utilisé par PostgreSQL, MySQL, SQLite

LSM-Trees (Log-Structured Merge-Tree) :

  • Écritures séquentielles rapides
  • Compaction asynchrone en arrière-plan
  • Meilleur pour les écritures intensives
  • Utilisé par Cassandra, RocksDB, LevelDB

Stockage en colonnes :

  • Pour les workloads analytiques (OLAP)
  • Compression efficace (colonnes similaires)
  • Agrégations rapides sans charger les colonnes inutiles

Chapitre 4 : Encodage et Évolution

Sérialisation : Comment représenter les données en mémoire et sur le réseau.

Formats :

  • JSON/XML : Lisibles, sans schéma, volumineux
  • Avro : Schéma requis, compact, évolution forward/backward
  • Protocol Buffers : Schéma requis, très compact, champs optionnels
  • Thrift : Similaire à Protobuf, Facebook origin

Compatibilité :

  • Backward : Le nouveau code lit les anciennes données
  • Forward : L'ancien code lit les nouvelles données
  • Databased schema evolution avec migrations

Partie II : Données Distribuées

Chapitre 5 : Réplication

Pourquoi répliquer : Haute disponibilité, latence réduite, tolérance aux pannes.

Modes de réplication :

  • Synchrone : Tous les nœuds confirment avant de répondre au client. Forte cohérence, latence élevée.
  • Asynchrone : Le leader répond immédiatement, les followers rattrapent. Performant, perte possible de données.
  • Semi-synchrone : Un follower doit confirmer (quorum write).

Modèles de réplication :

  • Leader-based (single-leader) : Un leader accepte les écritures
  • Multi-leader : Plusieurs leaders (conflits de write-write)
  • Leaderless (Dynamo-style) : Tous les nœuds acceptent les écritures

Problèmes de cohérence :

  • Read-after-write : Lire ses propres écritures
  • Monotonic read : Ne pas voir les données régresser
  • Consistent prefix read : Voir les données dans l'ordre

Chapitre 6 : Partitionnement (Sharding)

Pourquoi partitionner : Scalabilité horizontale, distribuer la charge.

Stratégies de partitionnement :

  • Par plage de clés : Simple, mais hotspots possibles
  • Par hash de clé : Distribution uniforme, mais perte du tri
  • Par hash consistent : Ajout/suppression de nœuds minimal

Index secondaires :

  • Local index : Chaque partition a son index (scatter/gather)
  • Global index : Index partitionné séparément (écritures plus lentes)

Rebalancing : Ajouter/supprimer des nœuds sans downtime.

  • Fixed number of partitions : Plusieurs partitions par nœud
  • Dynamic partitioning : Les partitions se divisent/fusionnent
  • Consistent hashing : Anneau de hachage

Chapitre 7 : Transactions

ACID revisité :

  • Atomicité : Tout ou rien, même en cas de crash
  • Cohérence : Les invariants sont respectés
  • Isolation : Les transactions concurrentes sont isolées
  • Durabilité : Les données persistent après un crash

Anomalies d'isolation :

  • Dirty read : Lire des données non commitées
  • Dirty write : Écrire par-dessus des données non commitées
  • Non-repeatable read : Lire deux fois, résultats différents
  • Phantom read : Nouvelles lignes apparaissent entre deux lectures

Niveaux d'isolation :

  • Read Uncommitted : Aucune protection
  • Read Committed : Pas de dirty read (la plupart des bases)
  • Repeatable Read : Pas de non-repeatable read (PostgreSQL, MySQL InnoDB)
  • Serializable : Transaction comme si séquentielle (plus lent)

MVCC (Multi-Version Concurrency Control) :

  • Chaque transaction voit un snapshot cohérent
  • Permet lecture sans bloquer écriture
  • Garbage collection des vieilles versions

Transactions distribuées :

  • Two-Phase Commit (2PC) : Phase prepare + phase commit, protocole coûteux
  • SAGA pattern : Séquence de transactions locales avec compensation
  • TCC (Try-Confirm/Cancel) : Phase de réservation puis confirmation

Chapitre 8 : Le Problème de la Cohérence Distribuée

Théorème CAP :

  • Cohérence, Disponibilité, Partition tolerance
  • On ne peut avoir que 2 des 3 en cas de partition réseau
  • CP : C + P (sacrifie la disponibilité)
  • AP : A + P (sacrifie la cohérence stricte)
  • CA : C + A (ne gère pas les partitions, impraticable en pratique)

Modèles de cohérence :

  • Strong consistency : Tous les nœuds voient la même chose
  • Eventual consistency : Convergence à terme
  • Causal consistency : Liens de causalité respectés
  • Read-your-writes : Lire ses écritures

Clock skew et NTP : Les horloges des machines ne sont jamais parfaitement synchronisées. Utiliser des logical clocks (Lamport, vector clocks) pour ordonner les événements.

Partie III : Traitement Dérivé

Chapitre 9 : Batch Processing

MapReduce : Paradigme de traitement batch distribué.

  • Map : Filtrer et transformer chaque enregistrement
  • Shuffle : Regrouper par clé
  • Reduce : Agréger les résultats groupés

Aspects importants :

  • Data locality : Déplacer le code vers les données plutôt que l'inverse
  • Input immutability : Les entrées ne sont pas modifiées
  • Determinism : Même entrée = même sortie
  • Fault tolerance : Rejouer les tâches échouées

Outils modernes : Apache Spark, Apache Flink, Google Dataflow

Chapitre 10 : Stream Processing

Différences avec le batch :

  • Temps réel vs différé
  • Événements vs lots
  • Stateful vs stateless

Modèles de messagerie :

  • Direct messaging : UDP, HTTP, RPC
  • Message broker : Kafka, RabbitMQ, Amazon SQS
  • Log-based : Kafka (log segmenté, répliqué)

Problèmes de stream :

  • Late arriving events : Comment gérer des événements en retard ?
  • Windowing : Tumbling, sliding, session windows
  • Out-of-order events : Gérer le désordre (watermarks)

Exactly-once semantics :

  • At-most-once : Au plus une fois (perte possible)
  • At-least-once : Au moins une fois (doublons possibles)
  • Exactly-once : Exactement une fois (idempotent, transactionnel)

Chapitre 11 : The Future of Data Systems

  • Data Integration : Unifier batch et stream (Kappa architecture)
  • Dataflow : Gérer le flux de données de bout en bout
  • Weaving together : Composition de systèmes de données
  • Ethics : Responsabilité des ingénieurs sur les données

Leçons Clés pour le Backend

  1. Connaître ses bases de données : Comprendre les trade-offs entre les modèles
  2. Les transactions simplifient la vie : Mais elles ont un coût en performance
  3. La cohérence distributive est un spectre : Pas seulement "cohérent" ou "pas cohérent"
  4. Les pannes arrivent : Concevoir pour la résilience, pas pour le cas parfait
  5. L'évolution du schéma est inévitable : Planifier les migrations dès le départ
  6. La mesure des performances est complexe : Percentiles, pas moyennes

2. Clean Architecture

Auteur : Robert C. Martin (Uncle Bob) Éditeur : Prentice Hall Année : 2017 Pages : 432 Difficulté : Intermédiaire Note : ★★★★★ (4.5/5)

Pourquoi lire ce livre

"Clean Architecture" étend les principes de "Clean Code" à l'architecture logicielle. Il montre comment structurer une application pour qu'elle reste maintenable, testable, et flexible face au changement.

Partie I : Introduction

Le Paradigme de la Programmation

  • Structured programming : Contrôle direct (séquences, boucles, conditions)
  • Object-oriented programming : Polymorphisme, encapsulation
  • Functional programming : Immutabilité, aucune side effect

L'Objectif de l'Architecture

Une bonne architecture :

  • Maximise le nombre de décisions non faites (options ouvertes)
  • Rend le système facile à comprendre, déployer, opérer
  • Permet de retarder les décisions d'infrastructure
  • Protège le code métier des détails techniques

Partie II : Les Principes SOLID

Single Responsibility Principle (SRP)

Une classe ne devrait avoir qu'une seule raison de changer.

  • Raison de changer = acteur qui demande le changement
  • Séparer les responsabilités par acteur métier
  • Ne pas mélanger UI, business logic, persistance dans la même classe

Open-Closed Principle (OCP)

Ouvert à l'extension, fermé à la modification.

  • Ajouter du comportement sans modifier le code existant
  • Utiliser l'héritage, le polymorphisme, les interfaces
  • Exemple : Strategy pattern, Decorator pattern

Liskov Substitution Principle (LSP)

Une sous-classe doit pouvoir remplacer sa classe de base.

  • Le contrat de la classe parent doit être respecté
  • Ne pas affaiblir les préconditions
  • Ne pas renforcer les postconditions
  • Exemple : Square héritant de Rectangle est une violation LSP

Interface Segregation Principle (ISP)

Les interfaces ne devraient pas imposer des méthodes inutilisées.

  • Préférer plusieurs interfaces spécifiques
  • Éviter les "fat interfaces"
  • Les clients ne dépendent pas de méthodes qu'ils n'utilisent pas

Dependency Inversion Principle (DIP)

Dépendre des abstractions, pas des concrétions.

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

Partie III : Les Composants

Cohésion des Composants

  • REP : Reuse/Release Equivalence Principle
  • CCP : Common Closure Principle (changements liés ensemble)
  • CRP : Common Reuse Principle (ne pas forcer à dépendre de choses inutilisées)

Couplage des Composants

  • ADP : Acyclic Dependencies Principle (pas de cycles dans le graphe de dépendances)
  • SDP : Stable Dependencies Principle (dépendre dans la direction de la stabilité)
  • SAP : Stable Abstractions Principle (la stabilité doit aller avec l'abstraction)

Partie IV : L'Architecture

L'Architecture Hexagonale (Ports & Adapters)

          ┌─────────────┐
          │   Domain    │
          │   (Use Cases)│
          └──────┬──────┘
                 │
      ┌──────────┼──────────┐
      │          │          │
  ┌───▼───┐ ┌───▼───┐ ┌───▼───┐
  │  Web  │ │  DB   │ │  API  │
  │(Input)│ │(Output)│ │(Third)│
  └───────┘ └───────┘ └───────┘
  • Le domaine est le centre : Pas de dépendance vers l'extérieur
  • Les ports : Interfaces définies par le domaine
  • Les adapteurs : Implémentations techniques (HTTP, SQL, etc.)
  • Dependency Rule : Les dépendances pointent vers l'intérieur

Screaming Architecture

L'architecture devrait "crier" son intension : un système de santé n'a pas la même architecture qu'un système e-commerce, même s'ils utilisent les mêmes frameworks.

The Clean Architecture

Controllers → Use Cases → Entities
     ↓             ↓           ↓
   Presenters   Gateways   Data Access

Règle de dépendance : Les cercles extérieurs peuvent dépendre des cercles intérieurs, jamais l'inverse.

Partie V : Détails

La Base de Données est un Détail

  • La base de données n'est pas le modèle métier
  • Le schéma relationnel n'est pas le modèle objet
  • L'ORM est un détail d'implémentation
  • Le stockage peut changer sans impacter le business logic

Le Web est un Détail

  • HTTP, REST, GraphQL sont des détails de transport
  • L'architecture ne devrait pas dépendre du framework web
  • Le routing et la sérialisation sont périphériques

Les Frameworks sont des Détails

  • Les frameworks sont des outils, pas des fondations
  • S'appuyer sur les frameworks rend dépendant de leurs mises à jour
  • Isoler le code métier des frameworks

Application Pratique

Structure de projet Clean Architecture :

src/
  domain/           # Entités, value objects, aggregates
    entities/
    value-objects/
    events/
  application/      # Use cases, ports
    use-cases/
    ports/
      in/          # Input ports (controllers appellent)
      out/         # Output ports (repositories)
  infrastructure/  # Adapters, frameworks
    persistence/
    web/
    messaging/

Leçons Clés

  1. Le code métier est le plus important : Protégez-le des détails techniques
  2. Les frameworks sont des serviteurs, pas des maîtres
  3. La testabilité est une propriété architecturale
  4. Les dépendances doivent toutes pointer vers l'intérieur
  5. Une bonne architecture permet de retarder les décisions
  6. Les use cases sont le squelette de l'application

3. Building Microservices

Auteur : Sam Newman Éditeur : O'Reilly Media Année : 2021 (2ème édition) Pages : 612 Difficulté : Intermédiaire-avancé Note : ★★★★★ (4.6/5)

Pourquoi lire ce livre

"Building Microservices" de Sam Newman est le guide de référence pour concevoir, construire et opérer des microservices. Cette seconde édition intègre les retours d'expérience d'une décennie d'adoption des microservices.

Partie I : Fondations

Chapitre 1 : Qu'est-ce qu'un Microservice ?

Définition :

Les microservices sont des services autonomes, indépendamment déployables, qui collaborent entre eux, chacun possédant son propre modèle de données.

Caractéristiques :

  • Indépendance de déploiement : Déployer sans impacter les autres
  • Modelisation par domaine : Chaque service couvre un bounded context
  • Ownership : Une équipe possède un service de bout en bout
  • Isolation des données : Chaque service a sa propre base
  • Réseau comme frontière : Communication via le réseau

Chapitre 2 : Le Modèle Technologique

Quand utiliser les microservices ?

  • Équipes nombreuses (>2 pizza teams)
  • Domaines complexes (DDD)
  • Cycles de déploiement indépendants
  • Exigences de scalabilité différentes par service

Quand éviter les microservices ?

  • Projet simple/débutant
  • Petite équipe (<5 personnes)
  • Domaines transactionnels complexes
  • Phase d'exploration (pivot rapide)

Partie II : Construction

Chapitre 3 : Communication Inter-Services

Sync vs Async :

  • Synchrone (HTTP, gRPC) : Simple, familier, mais couplage temporel
  • Asynchrone (Messaging) : Découplé, résilient, mais complexe

Patterns de communication :

  • Request/Response : Appel direct
  • Event-driven : Publier des événements
  • CQRS : Séparer lectures et écritures
  • Saga : Transactions distribuées

API Design :

  • REST : Hypermédia, idempotence, statut codes
  • gRPC : Performant, streaming, protobuf
  • GraphQL : Requêtes flexibles, surcharge possible

Chapitre 4 : Implémentation

Choix technologiques :

  • Langage approprié au service
  • Base de données adaptée au besoin
  • Framework consistant au sein du service

External Configuration :

  • Variables d'environnement
  • Service de configuration (Consul, etcd)
  • Feature flags

Health checking :

  • Liveness probe (est-ce vivant ?)
  • Readiness probe (est-ce prêt à servir ?)
  • Health endpoint exhaustif

Partie III : Opérations

Chapitre 5 : Déploiement

Stratégies :

  • Blue/Green : Deux environnements, bascule instantanée
  • Canary : Progression graduelle du trafic
  • Rolling update : Mise à jour progressive des instances

Containerisation :

  • Docker pour la standardisation
  • Orchestration (Kubernetes)
  • Images immutables

Chapitre 6 : Testing

Pyramide de test des microservices :

      ╱ E2E ╲
     ╱ Integration ╲
    ╱ Contract Tests ╲
   ╱ Component Tests  ╲
  ╱  Unit Tests (base)  ╲
  • Unit tests : Logique métier, rapides et fiables
  • Component tests : Service isolé, dépendances mockées
  • Contract tests : Accords entre services (Pact)
  • Integration tests : Service + dépendances réelles
  • E2E tests : Flux complets, lents et fragiles

Chapitre 7 : Monitoring

  • Logs centralisés : ELK, Loki
  • Métriques : RED (Rate, Errors, Duration) / USE (Utilization, Saturation, Errors)
  • Tracing distribué : OpenTelemetry, Jaeger, Zipkin
  • Alerting : Basé sur SLO/SLI

Chapitre 8 : Sécurité

  • API Gateway : Point d'entrée unique, auth centralisée
  • JWT : Tokens porteurs d'identité
  • Service mesh : mTLS, autorisation par service
  • OAuth2 / OpenID Connect : Délégation d'authentification
  • Secrets management : Vault, sealed secrets

Partie IV : Organisation

Chapitre 9 : Ownership et Couplage

  • Bounded Context (DDD) : Frontière naturelle des services
  • Team Topologies : Conway's Law en action
  • Service boundaries : Ne pas partager de base de données

Types de services :

  • Business domain services : Cœur métier
  • Infrastructure services : Techniques (messaging, monitoring)
  • Edge services : API Gateway, BFF

Chapitre 10 : Évolution

  • Strangler Fig Pattern : Remplacer progressivement un monolithe
  • Feature branches vs Trunk-based development
  • Internal Open Source : Contribution cross-équipe

Leçons Clés

  1. Ne commencez pas par des microservices : Commencez monolithe, extrayez progressivement
  2. L'indépendance de déploiement est l'objectif principal
  3. La communication asynchrone augmente la résilience
  4. Chaque service doit posséder sa propre base de données
  5. Les contrats doivent être testés (Pact)
  6. L'observabilité est cruciale : Logs, métriques, traces
  7. Les équipes doivent être alignées sur les services

4. The Pragmatic Programmer

Auteurs : Andrew Hunt, David Thomas Éditeur : Addison-Wesley Année : 1999 (2ème édition: 2019) Pages : 352 Difficulté : Débutant-intermédiaire Note : ★★★★☆ (4.4/5)

Pourquoi lire ce livre

"The Pragmatic Programmer" est un classique qui transcende les technologies. Il enseigne une philosophie de développement : être pragmatique signifie prendre des décisions éclairées, responsables, et toujours chercher à améliorer sa pratique.

Philosophie : Le Programneur Pragmatique

Caractéristiques :

  • Early adopter : Tester les nouvelles technologies
  • Questionneur : Remettre en question les choix
  • Penseur critique : Peser les pour et les contre
  • Réaliste : Comprendre les compromis

Section 1 : Une Approche Pragmatique

The Cat Ate My Source Code

Responsabilité personnelle : Assumez la responsabilité de votre travail. Si vous faites une erreur, admettez-la et proposez des solutions, pas des excuses.

Software Entropy

La fenêtre brisée : Ne laissez pas le "désordre" s'installer. Réparez les petites choses qui ne vont pas dès que vous les voyez. Un code mal entretenu attire plus de code mal entretenu.

Stone Soup and Boiled Frogs

Le changement incrémental : Plutôt que de demander une révolution, montrez un petit résultat convaincant (Stone Soup). Méfiez-vous du changement graduel qui empire la situation (Boiled Frog).

Good Enough Software

Savoir s'arrêter : La perfection n'est pas atteignable. Savoir quand "assez bien" est vraiment assez bien pour le client. Ne sacrifiez pas la qualité pour la perfection.

Your Knowledge Portfolio

Investir dans sa connaissance : Traitez vos compétences comme un portefeuille d'investissement.

  • Investir régulièrement (lecture, side projects)
  • Diversifier (plusieurs langages, domaines)
  • Équilibrer risque et sécurité (learning vs earning)
  • Réévaluer périodiquement

Communicate!

La communication est une compétence : Savoir documenter, présenter, écouter. Adapter le message à l'audience. Connaître le "pourquoi" avant le "comment".

Section 2 : Une Approche Pragmatique

The Evils of Duplication

DRY (Don't Repeat Yourself) : Chaque connaissance doit avoir une représentation unique et non ambiguë dans le système.

Types de duplication :

  • Imposée : Documentation qui répète le code
  • Involontaire : Copier-coller ignorant
  • Impatiente : Solution rapide qui duplique
  • Inter-développeurs : Communication insuffisante

Orthogonality

L'orthogonalité : Des changements indépendants doivent être indépendants.

Avantages :

  • Changements localisés
  • Testabilité améliorée
  • Réutilisabilité
  • Moins de risques de régression

Application :

  • Séparation des couches
  • Pas de dépendances circulaires
  • Modules faiblement couplés

Reversibility

Gardez les options ouvertes : Rien n'est permanent. Les choix technologiques (framework, base de données, cloud) ne devraient pas être irréversibles.

Tracer Bullets

Le code traceur : Au lieu de spécifier tout le système avant de coder, construisez un squelette fonctionnel de bout en bout.

Avantages :

  • Feedback immédiat
  • Découverte précoce des problèmes
  • Démo utilisateur rapide
  • Base pour ajouter des fonctionnalités

Prototypes and Post-it Notes

Prototyper pour apprendre : Un prototype répond à une question à moindre coût. Jetez-le après usage.

Ce qu'on peut prototyper :

  • Architecture
  • Nouvelles fonctionnalités
  • UX / UI flows
  • Modèles de données

Domain Languages

Parler le langage du domaine : Créez des mini-langages (DSL) qui reflètent le vocabulaire métier.

Estimating

Estimer n'est pas promettre : L'estimation est une approximation. Un ordre de grandeur (x2, x4, x8) est souvent plus utile qu'une fausse précision.

Section 3 : Le Processus

The Power of Plain Text

Le texte brut comme format de stockage : Utilisez des formats lisibles (JSON, YAML, CSV) pour la persistance. Ils survivent aux outils et plateformes.

Shell Games

Maîtrisez votre shell : L'investissement dans la maîtrise du terminal (scripting, pipes, automation) rapporte énormément.

Source Code Control

Le contrôle de version comme filet de sécurité : Tout doit être versionné (code, config, scripts, documentation). Commitez tôt, commitez souvent.

Debugging

Debugger est un art :

  • Ne paniquez pas, analysez
  • Reproduisez le bug avant de le corriger
  • Cherchez la cause racine, pas les symptômes
  • Changez une variable à la fois
  • Rubber duck debugging

Text Manipulation

Apprenez un langage de manipulation de texte : Perl, Python, awk, ou même bash. Utile pour transformer des données, générer du code, analyser des logs.

Code Generators

Générez du code répétitif : Templates, codegen, scaffolding. Évitez la duplication.

Section 4 : Le Code

Design by Contract

Les contrats définissent les responsabilités :

  • Préconditions : Ce que la fonction attend
  • Postconditions : Ce que la fonction garantit
  • Invariants : Ce qui ne change pas

Dead Programs Tell No Lies

Échouer tôt : Détecter et signaler les erreurs le plus tôt possible, idéalement à la compilation.

Assertive Programming

Les assertions ne remplacent pas les tests : Utilisez des assertions pour documenter les invariants et détecter les bugs.

How to Balance Resources

Acquérir puis libérer : Toute ressource (mémoire, fichier, lock, connexion) doit être libérée. Utilisez RAII en C++, using en C#, finally en Java, ou defer en Go.

Don't Outrun Your Headlights

Ne dépassez pas la portée de vos phares : Allez à la vitesse où vous pouvez prendre des décisions éclairées. Le refactoring est plus rapide que le big design up front.

Section 5 : Les Outils

Version Control

Git, mais aussi la connaissance des workflows (merge vs rebase, branching strategies)

Debuggers

Savoir utiliser son debugger en conditions réelles : breakpoints conditionnels, expression evaluation, remote debugging.

Profilers

Performance Driven Development : Profiler avant d'optimiser. Les hotspots sont rarement où on les imagine.

Test Harnesses

Tester n'est pas optionnel : Tests unitaires, intégration, acceptation. L'automation est clé.

Leçons Clés

  1. Soyez responsable de votre code : Ne rejetez pas la faute
  2. DRY, mais pas trop : L'abstraction intempestive est aussi nuisible
  3. Investissez dans votre boîte à outils : Shell, éditeur, debugger
  4. Le code traceur pour l'exploration, les prototypes pour l'apprentissage
  5. Estimer est difficile : Prévoyez des marges
  6. La communication est aussi importante que le code
  7. Le changement est inévitable : Concevez pour le changement

5. System Design Interview

Auteur : Alex Xu Éditeur : Independently published Année : 2021 Pages : 280 Difficulté : Intermédiaire Note : ★★★★☆ (4.5/5)

Pourquoi lire ce livre

"System Design Interview" prépare aux entretiens de conception de systèmes des grandes entreprises (FAANG). Chaque chapitre présente un problème classique d'architecture et le résout étape par étape.

Framework Système

Les 4 étapes

1. Comprendre le problème et définir le scope

  • Poser des questions clarifiant le périmètre
  • Ne pas présumer des besoins
  • Identifier les features clés vs nice-to-have

2. Proposer une architecture de haut niveau

  • Dessiner le diagramme (whiteboard)
  • Identifier les composants principaux
  • Discuter des trade-offs

3. Approfondir la conception

  • Détail des composants clés
  • Data flow
  • APIs et interfaces

4. Discussion sur la scalabilité

  • Goulots d'étranglement
  • Optimisations possibles
  • Compromis retenus

Études de Cas

1. Conception d'un URL Shortener (bit.ly)

Exigences :

  • 100M URLs créées par mois
  • Redirections rapides (< 10ms)
  • URLs courtes (6-7 caractères)
  • Analytics (clics par URL)
  • Disponibilité > 99.9%

Solution :

Diagramme en cours de génération...

Data model :

CREATE TABLE urls (
  id BIGSERIAL PRIMARY KEY,
  short_key VARCHAR(7) UNIQUE NOT NULL,
  original_url TEXT NOT NULL,
  user_id BIGINT REFERENCES users(id),
  created_at TIMESTAMP DEFAULT NOW(),
  expires_at TIMESTAMP,
  clicks BIGINT DEFAULT 0
);

CREATE INDEX idx_short_key ON urls(short_key);

ID Generation : Base62 encoding (62^7 = 3.5 trillion combinaisons)

  • Snowflake ID pattern
  • Pre-generated keys en cache

Redirection :

  • CDN pour short_key → original_url
  • Redis cache (TTL: 1 hour)
  • 301 redirect permanent vs 302 temporary
  • Analytics async via Kafka

Scalabilité :

  • Read replicas PostgreSQL
  • Cache Redis cluster
  • CDN pour redirections
  • Sharding par hash de short_key

2. Conception d'un Chat System (WhatsApp)

Exigences :

  • 1-to-1 et group chat
  • Messages temps réel
  • 100M DAU
  • Messages persistants (history)
  • Chiffrement de bout en bout

Architecture :

Client ←WebSocket→ Chat Service (Session)
                        │
              ┌─────────┼─────────┐
              │         │         │
         Message    Presence   Notification
         Service    Service    Service
              │         │
         Message     Online
          Store      Store
         (Cassandra) (Redis)

WebSocket Management :

  • Persistent connection manager
  • Session store (Redis)
  • Heartbeat pour détecter les déconnexions

Message Flow :

  1. Client envoie message via WebSocket
  2. Chat Service ajoute message_id (seq local)
  3. Message Service stocke (Cassandra, partitionné par conversation)
  4. Presence Service vérifie l'état du destinataire
  5. Si online, message immédiat via WebSocket
  6. Si offline, push notification (APNS/FCM)
  7. Sync des messages manquants à la reconnexion

Data Model Cassandra :

CREATE TABLE messages (
  conversation_id UUID,
  created_at TIMESTAMP,
  message_id TIMEUUID,
  sender_id UUID,
  content TEXT,
  message_type INT,
  PRIMARY KEY (conversation_id, created_at, message_id)
) WITH CLUSTERING ORDER BY (created_at DESC);

3. Conception d'un News Feed (Facebook)

Exigences :

  • 500M DAU
  • Feed personnalisé
  • Posts, photos, vidéos
  • Real-time updates
  • Scroll infini

Stratégies :

  • Fan-out on write : Pré-calculer le feed pour chaque follower
  • Fan-out on read : Calculer à la demande
  • Hybrid : Pour les célébrités (read), pour les amis (write)

Architecture Feed :

Post Service → Queue → Fanout Service → Feed Cache (Redis)
                                           │
Client ←→ Feed Service ←── Feed Cache

Feed Ranking :

  • Relevancy score (ML model)
  • Recency (décroissance temporelle)
  • Affinity (fréquence d'interaction)
  • Content type (video > photo > text)
  • Diversity (éviter domination)

ML Model Features :

  • User engagement history
  • Post interactions rate
  • Time since post
  • Relationship strength
  • Content category preference

Scalabilité :

  • Feed cache Redis Cluster (sharding par user_id)
  • Batch pre-computation aux heures creuses
  • Load shedding en pic
  • Personalized ranking via ML service

4. Conception d'un Système de Paiement (Stripe)

Exigences :

  • Traitement de paiements
  • Gestion des échecs et retours
  • Idempotence (ne pas débiter deux fois)
  • Conformité PCI DSS
  • Reporting et analytics

Architecture :

Client → API Gateway → Payment Service
                           │
                    ┌──────┴──────┐
                    │             │
            Payment Provider    Accounting
            (Stripe, Adyen)     Service
                                     │
                               Ledger DB
                              (Immutable)

Idempotency :

  • Clé d'idempotence dans le header
  • Stockée dans Redis avec TTL
  • Même clé = même résultat, pas de charge

État d'une transaction :

Initiated → Processing → Completed
    │            │
    ▼            ▼
Failed     Refunded → Refunded

Saga Pattern :

1. Reserve funds (Payment Service)
2. Update inventory (Inventory Service)
3. Confirm payment
4. Send confirmation email

Si échec à l'étape 2 : Release funds (compensation)

5. Conception d'un Système de Notification

Types : Push (mobile), SMS, Email, In-app

Architecture :

Notification Service
    │
    ├──→ Template Service
    ├──→ Rate Limiter (Redis)
    ├──→ Priority Queue
    │
    └──→ Channel Gateways
         ├── APNS (iOS)
         ├── FCM (Android)
         ├── Twilio (SMS)
         ├── SES/SendGrid (Email)
         └── WebSocket (In-app)

Rate Limiting par canal :

  • Redis sorted set (sliding window)
  • Limites configurables par type et priorité
  • Priority levels (critical, high, normal, low)

Leçons Clés

  1. Framework structuré : Scope → High-level → Deep-dive → Scale
  2. Les trade-offs sont importants : Montrez que vous comprenez les compromis
  3. Chiffres de dimensionnement : QPS, storage, bandwidth, cache size
  4. Designs résilients : SPOF, circuit breaker, retry, fallback
  5. Data consistency : CAP theorem, eventual vs strong consistency
  6. Always be ready to discuss trade-offs : Il n'y a pas de solution parfaite

Conclusion : Plan de Lecture

Par ordre de priorité

  1. Designing Data-Intensive Applications — Systèmes distribués (fondations)
  2. Clean Architecture — Architecture logicielle (structure)
  3. Building Microservices — Microservices (pratique)
  4. The Pragmatic Programmer — Philosophie (fondations du métier)
  5. System Design Interview — Préparation entretiens (cas concrets)

Par niveau

NiveauLivrePourquoi
DébutantThe Pragmatic ProgrammerFondations du métier
IntermédiaireClean ArchitectureArchitecture et design
IntermédiaireBuilding MicroservicesArchitecture distribuée
AvancéDesigning Data-Intensive ApplicationsSystèmes distribués
EntretiensSystem Design InterviewPratique et cas concrets