Questions d'entretien pour Développeur Backend Senior (Python) : Guide Complet

Milad Bonakdar
Auteur
Maîtrisez le développement backend Python avancé avec des questions d'entretien essentielles couvrant la conception de systèmes, l'optimisation de bases de données, la concurrence et l'architecture. Préparation idéale pour les entretiens de développeur backend senior.
Introduction
Ce guide complet contient 30 questions d'entretien essentielles couvrant le développement backend Python avancé. Ces questions sont conçues pour aider les développeurs backend seniors à se préparer aux entretiens en abordant les concepts clés de Python avancé, la conception de systèmes, l'optimisation de bases de données et la sécurité. Chaque question comprend une réponse détaillée, une évaluation de la rareté et une évaluation de la difficulté.
En tant que développeur senior, on attend de vous que vous connaissiez non seulement le "comment", mais aussi le "pourquoi" et les compromis impliqués dans vos décisions techniques.
Concepts Python avancés (8 Questions)
1. Comment fonctionne la gestion de la mémoire de Python et quel est le rôle du Garbage Collector ?
Réponse : Python utilise un tas privé pour gérer la mémoire, où tous les objets et structures de données sont stockés. Le programmeur ne peut pas accéder directement à ce tas ; il est géré par le gestionnaire de mémoire de Python.
- Comptage de références : Le mécanisme principal. Chaque objet a un nombre de références. Lorsqu'il tombe à zéro, la mémoire est libérée.
- Garbage Collector (GC) : Gère les références cycliques que le comptage de références ne peut pas détecter. Il s'exécute périodiquement pour trouver et nettoyer ces cycles.
- GC générationnel : Le GC de Python divise les objets en trois générations (0, 1, 2). Les nouveaux objets commencent dans la génération 0. S'ils survivent à une collection, ils passent à la génération suivante. Les générations plus anciennes sont collectées moins fréquemment pour améliorer les performances.
Rareté : Courant Difficulté : Difficile
2. Expliquez le verrouillage global de l'interpréteur (GIL) et son impact sur la concurrence. Comment le contourner ?
Réponse : Le GIL est un mutex qui protège l'accès aux objets Python, empêchant plusieurs threads natifs d'exécuter simultanément des bytecodes Python. Cela rend CPython thread-safe mais limite les programmes liés au CPU à un seul cœur.
- Impact : Le multi-threading est efficace pour les tâches liées aux E/S (attente du réseau/disque) mais pas pour les tâches liées au CPU (calculs lourds).
- Contourner le GIL :
- Multiprocessing : Utilisez le module
multiprocessingpour créer des processus séparés, chacun avec son propre interpréteur Python et son propre espace mémoire. - Extensions C : Écrivez le code critique pour les performances en C/C++ et libérez le GIL pendant son exécution.
- Interpréteurs alternatifs : Utilisez Jython ou IronPython (qui n'ont pas de GIL), bien que CPython soit la norme.
- Multiprocessing : Utilisez le module
Rareté : Très courant Difficulté : Difficile
3. Que sont les métaclasses en Python et quand devez-vous les utiliser ?
Réponse :
Une métaclasse est "la classe d'une classe". Tout comme une classe définit le comportement d'une instance, une métaclasse définit le comportement d'une classe. En Python, les classes sont aussi des objets, et ce sont des instances de type (la métaclasse par défaut).
- Utilisation : Vous pouvez intercepter la création de classe pour modifier la classe automatiquement.
- Cas d'utilisation :
- Enregistrer automatiquement les classes (par exemple, pour les plugins).
- Appliquer les normes de codage (par exemple, s'assurer que toutes les classes ont des docstrings).
- Implémentation du modèle Singleton.
- Les frameworks ORM (comme Django) les utilisent pour mapper les attributs de classe aux champs de base de données.
Exemple :
Rareté : Rare Difficulté : Difficile
4. Expliquez la différence entre __new__ et __init__.
Réponse :
__new__: Une méthode statique responsable de la création d'une nouvelle instance d'une classe. C'est la première étape de la création d'instance. Elle renvoie la nouvelle instance. Vous la surchargez rarement, sauf si vous sous-classez des types immuables (commestr,int,tuple) ou si vous implémentez un Singleton.__init__: Une méthode d'instance responsable de l'initialisation de l'instance créée. Elle est appelée après__new__. Elle ne renvoie rien.
Rareté : Moyenne Difficulté : Moyenne
5. Comment fonctionne asyncio en Python ? Expliquez la boucle d'événements.
Réponse :
asyncio est une bibliothèque permettant d'écrire du code concurrent à l'aide de la syntaxe async/await. Elle utilise un modèle de multitâche coopératif à thread unique.
- Boucle d'événements : Le cœur d'
asyncio. Elle exécute des tâches et des callbacks asynchrones, effectue des opérations d'E/S réseau et exécute des sous-processus. Elle bascule entre les tâches lorsqu'elles attendent des E/S (en utilisantawait), ce qui permet à d'autres tâches de s'exécuter entre-temps. - Coroutines : Fonctions définies avec
async def. Elles peuvent être mises en pause et reprises.
Rareté : Courant Difficulté : Difficile
6. Que sont les décorateurs Python et comment pouvez-vous créer un décorateur qui accepte des arguments ?
Réponse : Les décorateurs sont des fonctions qui modifient le comportement d'autres fonctions ou classes. Pour accepter des arguments, vous avez besoin d'une structure de fonction imbriquée à trois niveaux.
Exemple :
Rareté : Moyenne Difficulté : Moyenne
7. Expliquez le concept des gestionnaires de contexte et l'instruction with.
Réponse :
Les gestionnaires de contexte vous permettent d'allouer et de libérer des ressources précisément quand vous le souhaitez. L'utilisation la plus courante est l'instruction with.
- Mécanisme : Ils implémentent les méthodes
__enter__et__exit__.__enter__: Configure le contexte et renvoie la ressource.__exit__: Nettoie la ressource (ferme le fichier, libère le verrou) même si une exception se produit.
contextlib: Le décorateur@contextmanagervous permet de créer des gestionnaires de contexte à l'aide de générateurs.
Rareté : Courant Difficulté : Facile
8. Quelle est la différence entre @staticmethod et @classmethod ?
Réponse :
@staticmethod: Ne reçoit pas d'argument implicite en premier (niselfnicls). Elle se comporte comme une fonction régulière mais appartient à l'espace de noms de la classe. Utilisée pour les fonctions utilitaires qui n'ont pas besoin d'accéder à l'état de la classe ou de l'instance.@classmethod: Reçoit la classe (cls) comme premier argument implicite. Elle peut accéder à l'état de la classe et le modifier. Couramment utilisée pour les méthodes de fabrique qui créent des instances de la classe de différentes manières.
Rareté : Courant Difficulté : Facile
Conception et architecture du système (8 Questions)
9. Comment concevriez-vous un raccourcisseur d'URL (comme bit.ly) ?
Réponse : Il s'agit d'une question classique de conception de système.
- Exigences : Raccourcir les URL longues, rediriger les URL courtes vers l'original, haute disponibilité, faible latence.
- Base de données : Un magasin clé-valeur (NoSQL) comme DynamoDB ou Redis est approprié pour les recherches rapides. Une base de données relationnelle est également acceptable, mais pourrait nécessiter une mise à l'échelle.
- Algorithme :
- Encodage Base62 : Convertir un ID unique (entier à incrémentation automatique) en Base62 (a-z, A-Z, 0-9).
- Hachage : MD5/SHA256 de l'URL, prendre les 7 premiers caractères (risque de collision).
- Mise à l'échelle :
- Mise en cache : Redis/Memcached pour mettre en cache les redirections populaires (règle 80/20).
- Équilibrage de charge : Répartir le trafic sur plusieurs serveurs Web.
- Partitionnement de la base de données : Partitionner les données en fonction du préfixe de l'URL courte.
Rareté : Très courant Difficulté : Difficile
10. Expliquez le théorème CAP.
Réponse : Dans un magasin de données distribué, vous ne pouvez garantir que deux des trois éléments suivants : cohérence, disponibilité et tolérance au partitionnement :
- Cohérence (C) : Chaque lecture reçoit l'écriture la plus récente ou une erreur.
- Disponibilité (A) : Chaque requête reçoit une réponse (sans erreur), sans la garantie qu'elle contienne l'écriture la plus récente.
- Tolérance au partitionnement (P) : Le système continue de fonctionner malgré un nombre arbitraire de messages supprimés (ou retardés) par le réseau entre les nœuds.
- Réalité : Dans un système distribué, P est obligatoire. Vous devez choisir entre CP (Cohérence sur Disponibilité) et AP (Disponibilité sur Cohérence).
Rareté : Courant Difficulté : Moyenne
11. Microservices vs. Architecture monolithique : Quand choisir lequel ?
Réponse :
- Monolithe : Base de code unique, unité de déploiement unique.
- Avantages : Simple à développer/tester/déployer initialement, débogage plus facile, pas de latence réseau entre les composants.
- Inconvénients : Difficile de mettre à l'échelle des parties spécifiques, couplage étroit, verrouillage technologique, longs délais de construction.
- Cas d'utilisation : Startups en phase de démarrage, applications simples, petites équipes.
- Microservices : Collection de petits services indépendants communiquant via des API.
- Avantages : Mise à l'échelle indépendante, agnostique à la technologie par service, isolation des pannes, plus facile pour les grandes équipes de travailler en parallèle.
- Inconvénients : Opérations complexes (déploiement, surveillance), latence réseau, défis de cohérence des données (transactions distribuées).
- Cas d'utilisation : Systèmes volumineux et complexes, équipes à mise à l'échelle rapide, besoin de mise à l'échelle indépendante.
Rareté : Courant Difficulté : Moyenne
12. Qu'est-ce que l'équilibrage de charge et quels sont les différents algorithmes ?
Réponse : L'équilibrage de charge distribue le trafic réseau entrant sur plusieurs serveurs pour garantir qu'aucun serveur ne supporte une charge trop importante.
- Algorithmes :
- Round Robin : Distribue les requêtes séquentiellement.
- Least Connections : Envoie la requête au serveur avec le moins de connexions actives.
- IP Hash : Utilise l'adresse IP du client pour déterminer quel serveur reçoit la requête (utile pour la persistance de session).
- Types :
- L4 (Transport Layer) : Basé sur l'adresse IP et le port (plus rapide).
- L7 (Application Layer) : Basé sur le contenu (URL, cookies, en-têtes) (plus intelligent).
Rareté : Courant Difficulté : Moyenne
13. Comment gérez-vous la mise en cache dans un système backend ?
Réponse : La mise en cache stocke des copies de données dans un emplacement de stockage temporaire pour un accès plus rapide.
- Couches :
- Côté client : Mise en cache du navigateur.
- CDN : Met en cache les ressources statiques plus près de l'utilisateur.
- Équilibrage de charge/Proxy inverse : Varnish, Nginx.
- Application : En mémoire (locale) ou distribuée (Redis/Memcached).
- Base de données : Cache de requête.
- Stratégies :
- Cache-Aside (Lazy Loading) : L'application vérifie le cache ; en cas d'absence, lit la base de données et met à jour le cache.
- Write-Through : L'application écrit dans le cache et la base de données de manière synchrone.
- Write-Back : L'application écrit dans le cache ; le cache écrit dans la base de données de manière asynchrone (risque de perte de données).
- Éviction : LRU (Least Recently Used), LFU (Least Frequently Used), TTL (Time To Live).
Rareté : Courant Difficulté : Difficile
14. Qu'est-ce que le partitionnement de base de données ?
Réponse : Le partitionnement est une méthode de division et de stockage d'un seul ensemble de données logique dans plusieurs bases de données. C'est une forme de mise à l'échelle horizontale.
- Horizontal vs. Vertical : Vertical = machine plus grosse ; Horizontal = plus de machines.
- Clé de partitionnement : La logique utilisée pour distribuer les données (par exemple, UserID % NombreDePartitions).
- Défis :
- Jointures : Les jointures entre partitions sont coûteuses ou impossibles.
- Transactions : Les transactions distribuées sont complexes (validation en deux phases).
- Rééquilibrage : Le déplacement de données lors de l'ajout de nouvelles partitions est difficile.
Rareté : Moyenne Difficulté : Difficile
15. Expliquez le concept d'idempotence dans les API REST.
Réponse : Une opération idempotente est une opération qui peut être appliquée plusieurs fois sans modifier le résultat au-delà de l'application initiale.
- Méthodes sûres : GET, HEAD, OPTIONS (ne modifient pas l'état).
- Méthodes idempotentes : PUT, DELETE. Appeler DELETE sur une ressource 10 fois a le même effet que de l'appeler une fois (la ressource a disparu).
- Non-Idempotent : POST. Appeler POST 10 fois peut créer 10 ressources.
- Implémentation : Utilisez une clé d'idempotence (ID unique) dans l'en-tête de la requête. Le serveur vérifie s'il a déjà traité cet ID.
Rareté : Moyenne Difficulté : Moyenne
16. Qu'est-ce qu'un proxy inverse et pourquoi l'utiliser ?
Réponse : Un proxy inverse se trouve devant un ou plusieurs serveurs Web et leur transmet les requêtes des clients.
- Avantages :
- Équilibrage de charge : Distribution du trafic.
- Sécurité : Masque l'identité/l'adresse IP des serveurs backend ; peut gérer la terminaison SSL.
- Mise en cache : Mise en cache du contenu statique.
- Compression : Compression des réponses (gzip) pour économiser la bande passante.
- Exemples : Nginx, HAProxy.
Rareté : Courant Difficulté : Facile
Base de données et optimisation (7 Questions)
17. Expliquez les modèles de cohérence ACID vs. BASE.
Réponse :
- ACID (Relationnel) : Atomicité, Cohérence, Isolation, Durabilité. Se concentre sur une forte cohérence. Les transactions sont tout ou rien.
- BASE (NoSQL) :
- Basically Available : Le système garantit la disponibilité.
- Soft state : L'état du système peut changer au fil du temps, même sans entrée.
- Eventual consistency : Le système finira par devenir cohérent une fois qu'il cessera de recevoir des entrées.
- Compromis : ACID offre sécurité et cohérence ; BASE offre disponibilité et évolutivité.
Rareté : Moyenne Difficulté : Moyenne
18. Comment optimiser une requête SQL lente ?
Réponse :
- Analyser : Utilisez
EXPLAINouEXPLAIN ANALYZEpour comprendre le plan d'exécution de la requête. - Indexation : Assurez-vous que les colonnes utilisées dans les clauses
WHERE,JOINetORDER BYsont indexées. Évitez la sur-indexation (ralentit les écritures). - Sélectionnez uniquement ce dont vous avez besoin : Évitez
SELECT *. - Évitez le problème N+1 : Utilisez des
JOINou le chargement anticipé (dans les ORM) au lieu d'exécuter une requête pour chaque ligne dans une boucle. - Dénormalisation : Si les jointures sont trop coûteuses, envisagez de dupliquer les données (compromis : cohérence des données).
- Partitionnement : Divisez les grandes tables en morceaux plus petits.
Rareté : Très courant Difficulté : Moyenne
19. Quels sont les différents types d'index de base de données ?
Réponse :
- B-Tree : Le type par défaut et le plus courant. Bon pour les requêtes de plage et les vérifications d'égalité.
- Hash Index : Bon pour les vérifications d'égalité uniquement (key = value). Très rapide mais ne prend pas en charge les requêtes de plage.
- GiST / GIN : Utilisé pour les types de données complexes comme la recherche en texte intégral, les données géométriques ou JSONB (dans PostgreSQL).
- Clustered vs. Non-Clustered :
- Clustered : Les lignes de données sont stockées physiquement dans l'ordre de l'index. Un seul par table (généralement PK).
- Non-Clustered : Une structure séparée qui pointe vers les lignes de données.
Rareté : Moyenne Difficulté : Difficile
20. Expliquez le problème de requête N+1 et comment le résoudre.
Réponse : Le problème N+1 se produit lorsque votre code exécute N instructions de requête supplémentaires pour récupérer les mêmes données qui auraient pu être récupérées lors de l'exécution de la requête principale.
- Scénario : Vous récupérez une liste de 10 auteurs (1 requête). Ensuite, pour chaque auteur, vous récupérez leurs livres (10 requêtes). Total = 11 requêtes.
- Solution :
- SQL : Utilisez une
JOINpour récupérer les auteurs et les livres en une seule requête. - ORM (Django) : Utilisez
select_related(pour les clés étrangères/un à un) ouprefetch_related(pour les plusieurs à plusieurs/clés étrangères inversées).
- SQL : Utilisez une
Rareté : Très courant Difficulté : Moyenne
21. Redis vs. Memcached : Lequel choisir ?
Réponse :
- Memcached : Simple, volatile, multi-thread. Bon pour la mise en cache clé-valeur simple (fragments HTML, données de session).
- Redis : Magasin clé-valeur avancé.
- Structures de données : Prend en charge les listes, les ensembles, les ensembles triés, les hachages, les bitmaps, les hyperloglogs.
- Persistance : Peut enregistrer les données sur le disque (RDB, AOF).
- Réplication : Réplication maître-esclave intégrée.
- Pub/Sub : Prend en charge le courtage de messages.
- Choix : Utilisez Redis si vous avez besoin de structures de données complexes, de persistance ou de tri. Utilisez Memcached pour la mise en cache simple à haut débit si vous avez besoin du multi-threading.
Rareté : Moyenne Difficulté : Moyenne
22. Qu'est-ce que la normalisation de base de données ?
Réponse : La normalisation est le processus d'organisation des données dans une base de données pour réduire la redondance et améliorer l'intégrité des données.
- 1NF : Valeurs atomiques (pas de listes dans les cellules), lignes uniques.
- 2NF : 1NF + pas de dépendance partielle (tous les attributs non-clés dépendent de la totalité de la clé primaire).
- 3NF : 2NF + pas de dépendance transitive (les attributs non-clés dépendent uniquement de la clé primaire).
- Compromis : Une normalisation plus élevée signifie plus de tables et plus de jointures (lectures plus lentes). La dénormalisation est souvent utilisée pour les systèmes à forte lecture.
Rareté : Courant Difficulté : Facile
23. Comment PostgreSQL gère-t-il la concurrence (MVCC) ?
Réponse : PostgreSQL utilise le contrôle de concurrence multiversion (MVCC).
- Mécanisme : Lorsqu'une ligne est mise à jour, Postgres ne remplace pas les anciennes données. Au lieu de cela, il crée une nouvelle version de la ligne.
- Lecteurs : Les lecteurs voient un instantané cohérent de la base de données tel qu'il était lorsque leur transaction a commencé. Ils ne bloquent pas les écrivains.
- Écrivains : Les écrivains créent de nouvelles versions. Ils bloquent les autres écrivains sur la même ligne mais ne bloquent pas les lecteurs.
- Nettoyage : Les anciennes versions (tuples morts) qui ne sont plus visibles pour aucune transaction doivent être nettoyées par le processus
VACUUMpour récupérer de l'espace.
Rareté : Rare Difficulté : Difficile
Sécurité et DevOps (7 Questions)
24. Expliquez OAuth 2.0 et son flux.
Réponse : OAuth 2.0 est un framework d'autorisation qui permet aux applications d'obtenir un accès limité aux comptes d'utilisateurs sur un service HTTP (comme Google, Facebook) sans exposer le mot de passe de l'utilisateur.
- Rôles : Propriétaire de la ressource (utilisateur), Client (application), Serveur d'autorisation, Serveur de ressources (API).
- Flux (Autorisation par code d'autorisation) :
- L'utilisateur clique sur "Se connecter avec Google".
- L'utilisateur est redirigé vers le serveur d'authentification de Google.
- L'utilisateur approuve l'accès.
- Google redirige vers l'application avec un "code d'autorisation".
- L'application échange le code contre un "jeton d'accès" (canal de retour).
- L'application utilise le jeton d'accès pour accéder à l'API.
Rareté : Courant Difficulté : Difficile
25. Qu'est-ce que JWT (JSON Web Token) et en quoi est-il différent de l'authentification par session ?
Réponse :
- Authentification par session : Le serveur crée une session, la stocke dans la base de données/le cache et envoie un ID de session (cookie) au client. Avec état.
- JWT : Sans état. Le serveur génère un jeton contenant l'identité de l'utilisateur et le signe avec une clé secrète. Le client stocke le jeton et l'envoie avec chaque requête. Le serveur vérifie la signature. Aucune recherche dans la base de données n'est nécessaire.
- Avantages de JWT : Évolutif (sans état), bon pour les microservices, adapté aux mobiles.
- Inconvénients de JWT : Difficile à révoquer (nécessite une liste noire/une courte durée de validité), la taille du jeton est plus grande.
Rareté : Très courant Difficulté : Moyenne
26. Quels sont les 10 principaux risques de sécurité de l'OWASP ? Citez-en quelques-uns.
Réponse : Un document de sensibilisation standard pour les développeurs et la sécurité des applications Web.
- Injection : SQL, NoSQL, injection OS.
- Authentification cassée : Mots de passe faibles, détournement de session.
- Exposition de données sensibles : Ne pas chiffrer les données en transit/au repos.
- Entités externes XML (XXE) : Attaques contre les analyseurs XML.
- Contrôle d'accès cassé : Les utilisateurs agissent en dehors de leurs autorisations prévues.
- Mauvaise configuration de la sécurité : Comptes par défaut, messages d'erreur verbeux.
- Cross-Site Scripting (XSS) : Injection de scripts malveillants.
Rareté : Courant Difficulté : Moyenne
27. Qu'est-ce que CI/CD ?
Réponse :
- Intégration continue (CI) : Les développeurs fusionnent fréquemment les modifications de code dans un référentiel central. Des builds et des tests automatisés sont exécutés pour vérifier les modifications. Objectif : détecter rapidement les erreurs.
- Déploiement continu (CD) : Déploiement automatique du code en production après avoir passé CI.
- Livraison continue : Préparation automatique du code pour la publication, mais une approbation manuelle peut être nécessaire pour la publication finale.
Rareté : Courant Difficulté : Facile
28. Expliquez Docker vs. Machines virtuelles.
Réponse :
- Machines virtuelles (VM) : Virtualisent le matériel. Chaque VM a un système d'exploitation complet (système d'exploitation invité), un noyau et des applications. Lourd, démarrage lent.
- Docker (Conteneurs) : Virtualisent le système d'exploitation. Les conteneurs partagent le noyau du système d'exploitation hôte mais ont des espaces utilisateurs isolés (bins/libs). Léger, démarrage rapide, portable.
Rareté : Courant Difficulté : Facile
29. Qu'est-ce que Kubernetes ?
Réponse : Kubernetes (K8s) est une plateforme d'orchestration de conteneurs open source. Il automatise le déploiement, la mise à l'échelle et la gestion des applications conteneurisées.
- Fonctionnalités :
- Découverte de service et équilibrage de charge : Expose les conteneurs.
- Auto-guérison : Redémarre les conteneurs défaillants.
- Déploiements/restaurations automatisés : Met à jour les applications sans temps d'arrêt.
- Gestion des secrets et de la configuration : Gère les données sensibles.
Rareté : Moyenne Difficulté : Moyenne
30. Comment sécuriser une application Web Python ?
Réponse :
- Validation des entrées : Nettoyez toutes les entrées (formulaires, corps d'API, paramètres de requête).
- Injection SQL : Utilisez des ORM ou des requêtes paramétrées. N'utilisez jamais la concaténation de chaînes.
- XSS : Échappez la sortie utilisateur dans les modèles (Jinja2 le fait par défaut).
- CSRF : Utilisez des jetons CSRF pour les requêtes de changement d'état.
- Dépendances : Gardez les bibliothèques à jour (utilisez
pip-auditou Snyk). - HTTPS : Appliquez SSL/TLS.
- En-têtes : Définissez les en-têtes de sécurité (HSTS, X-Frame-Options, CSP).
- Secrets : Ne committez jamais de secrets dans Git. Utilisez des variables d'environnement.
Rareté : Courant Difficulté : Moyenne



