Domande per il Colloquio di Senior Backend Developer (Python): Guida Completa

Milad Bonakdar
Autore
Padroneggia lo sviluppo backend avanzato in Python con domande essenziali per il colloquio che coprono la progettazione del sistema, l'ottimizzazione del database, la concorrenza e l'architettura. Preparazione perfetta per i colloqui di senior backend developer.
Introduzione
Questa guida completa contiene 30 domande essenziali per il colloquio che coprono lo sviluppo backend avanzato in Python. Queste domande sono progettate per aiutare gli sviluppatori backend senior a prepararsi per i colloqui, trattando concetti chiave in Python avanzato, progettazione del sistema, ottimizzazione del database e sicurezza. Ogni domanda include una risposta dettagliata, una valutazione della rarità e una valutazione della difficoltà.
Come sviluppatore senior, ci si aspetta che tu non solo conosca il "come", ma anche il "perché" e i compromessi coinvolti nelle tue decisioni tecniche.
Concetti avanzati di Python (8 domande)
1. Come funziona la gestione della memoria di Python e qual è il ruolo del Garbage Collector?
Risposta: Python utilizza un heap privato per gestire la memoria, dove sono archiviati tutti gli oggetti e le strutture dati. Il programmatore non può accedere direttamente a questo heap; è gestito dal gestore di memoria di Python.
- Conteggio dei riferimenti: Il meccanismo principale. Ogni oggetto ha un conteggio dei riferimenti. Quando scende a zero, la memoria viene deallocata.
- Garbage Collector (GC): Gestisce i riferimenti ciclici che il conteggio dei riferimenti non può intercettare. Viene eseguito periodicamente per trovare e ripulire questi cicli.
- GC generazionale: Il GC di Python divide gli oggetti in tre generazioni (0, 1, 2). I nuovi oggetti iniziano nella generazione 0. Se sopravvivono a una raccolta, si spostano alla generazione successiva. Le generazioni più vecchie vengono raccolte meno frequentemente per migliorare le prestazioni.
Rarità: Comune Difficoltà: Difficile
2. Spiega il Global Interpreter Lock (GIL) e il suo impatto sulla concorrenza. Come lo si aggira?
Risposta: Il GIL è un mutex che protegge l'accesso agli oggetti Python, impedendo a più thread nativi di eseguire contemporaneamente bytecode Python. Ciò rende CPython thread-safe, ma limita i programmi CPU-bound a un singolo core.
- Impatto: Il multi-threading è efficace per le attività I/O-bound (in attesa di rete/disco) ma non per le attività CPU-bound (calcoli pesanti).
- Aggirare il GIL:
- Multiprocessing: Utilizzare il modulo
multiprocessingper creare processi separati, ciascuno con il proprio interprete Python e spazio di memoria. - Estensioni C: Scrivere codice critico per le prestazioni in C/C++ e rilasciare il GIL durante l'esecuzione.
- Interpreti alternativi: Utilizzare Jython o IronPython (che non hanno un GIL), anche se CPython è lo standard.
- Multiprocessing: Utilizzare il modulo
Rarità: Molto comune Difficoltà: Difficile
3. Cosa sono le Metaclassi in Python e quando dovresti usarle?
Risposta:
Una metaclasse è "la classe di una classe". Proprio come una classe definisce il comportamento di un'istanza, una metaclasse definisce il comportamento di una classe. In Python, anche le classi sono oggetti e sono istanze di type (la metaclasse predefinita).
- Utilizzo: È possibile intercettare la creazione della classe per modificare automaticamente la classe.
- Casi d'uso:
- Registrazione automatica delle classi (ad esempio, per i plugin).
- Applicazione di standard di codifica (ad esempio, garantire che tutte le classi abbiano docstring).
- Implementazione del pattern Singleton.
- I framework ORM (come Django) li utilizzano per mappare gli attributi della classe ai campi del database.
Esempio:
Rarità: Non comune Difficoltà: Difficile
4. Spiega la differenza tra __new__ e __init__.
Risposta:
__new__: Un metodo statico responsabile della creazione di una nuova istanza di una classe. È il primo passo nella creazione dell'istanza. Restituisce la nuova istanza. Raramente lo si sovrascrive a meno che non si stiano sottoclassando tipi immutabili (comestr,int,tuple) o implementando un Singleton.__init__: Un metodo di istanza responsabile della inizializzazione dell'istanza creata. Viene chiamato dopo__new__. Non restituisce nulla.
Rarità: Media Difficoltà: Media
5. Come funziona asyncio in Python? Spiega l'Event Loop.
Risposta:
asyncio è una libreria per scrivere codice concorrente utilizzando la sintassi async/await. Utilizza un modello di multitasking cooperativo a thread singolo.
- Event Loop: Il cuore di
asyncio. Esegue attività asincrone e callback, esegue operazioni di I/O di rete ed esegue sottoprocessi. Commuta tra le attività quando sono in attesa di I/O (utilizzandoawait), consentendo ad altre attività di essere eseguite nel frattempo. - Coroutines: Funzioni definite con
async def. Possono essere messe in pausa e riprese.
Rarità: Comune Difficoltà: Difficile
6. Cosa sono i Decoratori Python e come puoi creare un decoratore che accetti argomenti?
Risposta: I decoratori sono funzioni che modificano il comportamento di altre funzioni o classi. Per accettare argomenti, è necessaria una struttura di funzione nidificata a tre livelli.
Esempio:
Rarità: Media Difficoltà: Media
7. Spiega il concetto di Context Managers e l'istruzione with.
Risposta:
I context manager consentono di allocare e rilasciare le risorse esattamente quando lo si desidera. L'utilizzo più comune è l'istruzione with.
- Meccanismo: Implementano i metodi
__enter__e__exit__.__enter__: Imposta il contesto e restituisce la risorsa.__exit__: Pulisce la risorsa (chiude il file, rilascia il blocco) anche se si verifica un'eccezione.
contextlib: Il decoratore@contextmanagerconsente di creare context manager utilizzando i generatori.
Rarità: Comune Difficoltà: Facile
8. Qual è la differenza tra @staticmethod e @classmethod?
Risposta:
@staticmethod: Non riceve un primo argomento implicito (néselfnécls). Si comporta come una normale funzione ma appartiene allo spazio dei nomi della classe. Utilizzato per funzioni di utilità che non necessitano di accedere allo stato della classe o dell'istanza.@classmethod: Riceve la classe (cls) come primo argomento implicito. Può accedere allo stato della classe e modificarlo. Comunemente usato per i metodi factory che creano istanze della classe in modi diversi.
Rarità: Comune Difficoltà: Facile
Progettazione e architettura del sistema (8 domande)
9. Come progetteresti un URL Shortener (come bit.ly)?
Risposta: Questa è una classica domanda di progettazione del sistema.
- Requisiti: Accorciare URL lunghi, reindirizzare URL brevi all'originale, alta disponibilità, bassa latenza.
- Database: Un archivio Key-Value (NoSQL) come DynamoDB o Redis è adatto per ricerche veloci. Anche un DB relazionale va bene, ma potrebbe aver bisogno di scalabilità.
- Algoritmo:
- Codifica Base62: Convertire un ID univoco (intero a incremento automatico) in Base62 (a-z, A-Z, 0-9).
- Hashing: MD5/SHA256 dell'URL, prendere i primi 7 caratteri (rischio di collisione).
- Scalabilità:
- Caching: Redis/Memcached per memorizzare nella cache i reindirizzamenti popolari (regola 80/20).
- Load Balancing: Distribuire il traffico su più server web.
- Database Sharding: Partizionare i dati in base al prefisso dell'URL breve.
Rarità: Molto comune Difficoltà: Difficile
10. Spiega il teorema CAP.
Risposta: In un archivio dati distribuito, è possibile garantire solo due dei seguenti tre: coerenza, disponibilità e tolleranza alla partizione:
- Coerenza (C): Ogni lettura riceve la scrittura più recente o un errore.
- Disponibilità (A): Ogni richiesta riceve una risposta (non di errore), senza la garanzia che contenga la scrittura più recente.
- Tolleranza alla partizione (P): Il sistema continua a funzionare nonostante un numero arbitrario di messaggi venga eliminato (o ritardato) dalla rete tra i nodi.
- Realtà: In un sistema distribuito, P è obbligatoria. È necessario scegliere tra CP (Coerenza rispetto alla disponibilità) e AP (Disponibilità rispetto alla coerenza).
Rarità: Comune Difficoltà: Media
11. Architettura a microservizi vs. monolitica: quando scegliere quale?
Risposta:
- Monolite: Singola codebase, singola unità di distribuzione.
- Pro: Semplice da sviluppare/testare/distribuire inizialmente, debug più semplice, nessuna latenza di rete tra i componenti.
- Contro: Difficile scalare parti specifiche, stretto accoppiamento, blocco tecnologico, tempi di compilazione lunghi.
- Caso d'uso: Startup in fase iniziale, applicazioni semplici, piccoli team.
- Microservizi: Raccolta di piccoli servizi indipendenti che comunicano tramite API.
- Pro: Scalabilità indipendente, tecnologia agnostica per servizio, isolamento dei guasti, più facile per i team di grandi dimensioni lavorare in parallelo.
- Contro: Operazioni complesse (distribuzione, monitoraggio), latenza di rete, sfide di coerenza dei dati (transazioni distribuite).
- Caso d'uso: Sistemi di grandi dimensioni e complessi, team in rapida espansione, necessità di scalabilità indipendente.
Rarità: Comune Difficoltà: Media
12. Cos'è il Load Balancing e quali sono i diversi algoritmi?
Risposta: Il load balancing distribuisce il traffico di rete in entrata su più server per garantire che nessun singolo server sopporti un carico eccessivo.
- Algoritmi:
- Round Robin: Distribuisce le richieste in sequenza.
- Least Connections: Invia la richiesta al server con il minor numero di connessioni attive.
- IP Hash: Utilizza l'IP del client per determinare quale server riceve la richiesta (utile per la persistenza della sessione).
- Tipi:
- L4 (Transport Layer): Basato su IP e porta (più veloce).
- L7 (Application Layer): Basato sul contenuto (URL, cookie, intestazioni) (più intelligente).
Rarità: Comune Difficoltà: Media
13. Come gestisci la Caching in un sistema backend?
Risposta: La caching memorizza copie dei dati in una posizione di archiviazione temporanea per un accesso più rapido.
- Livelli:
- Lato client: Caching del browser.
- CDN: Memorizza nella cache gli asset statici più vicini all'utente.
- Load Balancer/Reverse Proxy: Varnish, Nginx.
- Applicazione: In-memory (locale) o distribuita (Redis/Memcached).
- Database: Cache delle query.
- Strategie:
- Cache-Aside (Lazy Loading): L'app controlla la cache; se manca, legge il DB e aggiorna la cache.
- Write-Through: L'app scrive nella cache e nel DB in modo sincrono.
- Write-Back: L'app scrive nella cache; la cache scrive nel DB in modo asincrono (rischio di perdita di dati).
- Eviction: LRU (Least Recently Used), LFU (Least Frequently Used), TTL (Time To Live).
Rarità: Comune Difficoltà: Difficile
14. Cos'è il Database Sharding?
Risposta: Lo sharding è un metodo per dividere e archiviare un singolo set di dati logici in più database. È una forma di scalabilità orizzontale.
- Orizzontale vs. Verticale: Verticale = macchina più grande; Orizzontale = più macchine.
- Sharding Key: La logica utilizzata per distribuire i dati (ad esempio, UserID % NumberOfShards).
- Sfide:
- Joins: I join tra shard sono costosi o impossibili.
- Transazioni: Le transazioni distribuite sono complesse (Two-Phase Commit).
- Rebalancing: Spostare i dati quando si aggiungono nuovi shard è difficile.
Rarità: Media Difficoltà: Difficile
15. Spiega il concetto di Idempotenza nelle API REST.
Risposta: Un'operazione idempotente è un'operazione che può essere applicata più volte senza modificare il risultato oltre l'applicazione iniziale.
- Metodi sicuri: GET, HEAD, OPTIONS (non modificano lo stato).
- Metodi idempotenti: PUT, DELETE. Chiamare DELETE su una risorsa 10 volte ha lo stesso effetto di chiamarla una volta (la risorsa è sparita).
- Non idempotente: POST. Chiamare POST 10 volte potrebbe creare 10 risorse.
- Implementazione: Utilizzare una chiave di idempotenza (ID univoco) nell'intestazione della richiesta. Il server verifica se ha già elaborato questo ID.
Rarità: Media Difficoltà: Media
16. Cos'è un Reverse Proxy e perché usarlo?
Risposta: Un reverse proxy si trova davanti a uno o più server web e inoltra loro le richieste del client.
- Vantaggi:
- Load Balancing: Distribuzione del traffico.
- Sicurezza: Nasconde l'identità/IP dei server backend; può gestire la terminazione SSL.
- Caching: Memorizzazione nella cache di contenuti statici.
- Compressione: Compressione delle risposte (gzip) per risparmiare larghezza di banda.
- Esempi: Nginx, HAProxy.
Rarità: Comune Difficoltà: Facile
Database e ottimizzazione (7 domande)
17. Spiega i modelli di coerenza ACID vs. BASE.
Risposta:
- ACID (Relazionale): Atomicità, Coerenza, Isolamento, Durabilità. Si concentra sulla forte coerenza. Le transazioni sono tutto o niente.
- BASE (NoSQL):
- Basically Available: Il sistema garantisce la disponibilità.
- Soft state: Lo stato del sistema può cambiare nel tempo, anche senza input.
- Eventual consistency: Il sistema alla fine diventerà coerente una volta che smetterà di ricevere input.
- Compromesso: ACID fornisce sicurezza e coerenza; BASE fornisce disponibilità e scalabilità.
Rarità: Media Difficoltà: Media
18. Come ottimizzi una query SQL lenta?
Risposta:
- Analisi: Utilizzare
EXPLAINoEXPLAIN ANALYZEper comprendere il piano di esecuzione della query. - Indicizzazione: Assicurarsi che le colonne utilizzate nelle clausole
WHERE,JOINeORDER BYsiano indicizzate. Evitare l'eccessiva indicizzazione (rallenta le scritture). - Seleziona solo ciò di cui hai bisogno: Evitare
SELECT *. - Evitare il problema N+1: Utilizzare
JOINo il caricamento eager (negli ORM) invece di eseguire una query per ogni riga in un ciclo. - Denormalizzazione: Se i join sono troppo costosi, prendere in considerazione la duplicazione dei dati (compromesso: coerenza dei dati).
- Partizionamento: Dividere le tabelle di grandi dimensioni in parti più piccole.
Rarità: Molto comune Difficoltà: Media
19. Quali sono i diversi tipi di indici di database?
Risposta:
- B-Tree: Il predefinito e più comune. Buono per query di intervallo e controlli di uguaglianza.
- Hash Index: Buono solo per i controlli di uguaglianza (chiave = valore). Molto veloce ma non supporta le query di intervallo.
- GiST / GIN: Utilizzato per tipi di dati complessi come la ricerca full-text, i dati geometrici o JSONB (in PostgreSQL).
- Clustered vs. Non-Clustered:
- Clustered: Le righe di dati sono archiviate fisicamente nell'ordine dell'indice. Solo uno per tabella (di solito PK).
- Non-Clustered: Una struttura separata che punta alle righe di dati.
Rarità: Media Difficoltà: Difficile
20. Spiega il problema della query N+1 e come risolverlo.
Risposta: Il problema N+1 si verifica quando il codice esegue N istruzioni di query aggiuntive per recuperare gli stessi dati che avrebbero potuto essere recuperati durante l'esecuzione della query principale.
- Scenario: Si recupera un elenco di 10 autori (1 query). Quindi, per ogni autore, si recuperano i suoi libri (10 query). Totale = 11 query.
- Soluzione:
- SQL: Utilizzare un
JOINper recuperare autori e libri in una singola query. - ORM (Django): Utilizzare
select_related(per chiavi esterne/one-to-one) oprefetch_related(per many-to-many/chiavi esterne inverse).
- SQL: Utilizzare un
Rarità: Molto comune Difficoltà: Media
21. Redis vs. Memcached: Quale scegliere?
Risposta:
- Memcached: Semplice, volatile, multi-thread. Buono per la semplice caching key-value (frammenti HTML, dati di sessione).
- Redis: Archivio key-value avanzato.
- Strutture dati: Supporta elenchi, insiemi, insiemi ordinati, hash, bitmap, hyperloglog.
- Persistenza: Può salvare i dati su disco (RDB, AOF).
- Replicazione: Replicazione master-slave integrata.
- Pub/Sub: Supporta il message brokering.
- Scelta: Utilizzare Redis se sono necessarie strutture dati complesse, persistenza o ordinamento. Utilizzare Memcached per una caching semplice e ad alta velocità se è necessario il multi-threading.
Rarità: Media Difficoltà: Media
22. Cos'è la normalizzazione del database?
Risposta: La normalizzazione è il processo di organizzazione dei dati in un database per ridurre la ridondanza e migliorare l'integrità dei dati.
- 1NF: Valori atomici (nessun elenco nelle celle), righe univoche.
- 2NF: 1NF + nessuna dipendenza parziale (tutti gli attributi non chiave dipendono dalla intera chiave primaria).
- 3NF: 2NF + nessuna dipendenza transitiva (gli attributi non chiave dipendono solo dalla chiave primaria).
- Compromesso: Una normalizzazione più elevata significa più tabelle e più join (letture più lente). La denormalizzazione viene spesso utilizzata per i sistemi ad alta intensità di lettura.
Rarità: Comune Difficoltà: Facile
23. Come gestisce PostgreSQL la concorrenza (MVCC)?
Risposta: PostgreSQL utilizza Multi-Version Concurrency Control (MVCC).
- Meccanismo: Quando una riga viene aggiornata, Postgres non sovrascrive i vecchi dati. Invece, crea una nuova versione della riga.
- Lettori: I lettori vedono un'istantanea coerente del database com'era quando è iniziata la loro transazione. Non bloccano gli scrittori.
- Scrittori: Gli scrittori creano nuove versioni. Bloccano altri scrittori sulla stessa riga ma non bloccano i lettori.
- Vacuuming: Le vecchie versioni (tuple morte) che non sono più visibili a nessuna transazione devono essere ripulite dal processo
VACUUMper recuperare spazio.
Rarità: Non comune Difficoltà: Difficile
Sicurezza e DevOps (7 domande)
24. Spiega OAuth 2.0 e il suo flusso.
Risposta: OAuth 2.0 è un framework di autorizzazione che consente alle applicazioni di ottenere un accesso limitato agli account utente su un servizio HTTP (come Google, Facebook) senza esporre la password dell'utente.
- Ruoli: Resource Owner (Utente), Client (App), Authorization Server, Resource Server (API).
- Flusso (Authorization Code Grant):
- L'utente fa clic su "Accedi con Google".
- L'utente viene reindirizzato al server di autenticazione di Google.
- L'utente approva l'accesso.
- Google reindirizza all'app con un "Authorization Code".
- L'app scambia il codice con un "Access Token" (back-channel).
- L'app utilizza l'Access Token per accedere all'API.
Rarità: Comune Difficoltà: Difficile
25. Cos'è JWT (JSON Web Token) e in cosa differisce da Session Auth?
Risposta:
- Session Auth: Il server crea una sessione, la archivia in DB/Cache e invia un ID di sessione (cookie) al client. Stateful.
- JWT: Stateless. Il server genera un token contenente l'identità dell'utente e lo firma con una chiave segreta. Il client archivia il token e lo invia con ogni richiesta. Il server verifica la firma. Nessuna ricerca nel DB necessaria.
- Pro di JWT: Scalabile (stateless), buono per i microservizi, mobile-friendly.
- Contro di JWT: Difficile da revocare (necessità di blacklisting/scadenza breve), la dimensione del token è maggiore.
Rarità: Molto comune Difficoltà: Media
26. Quali sono i primi 10 rischi per la sicurezza di OWASP? Indicane alcuni.
Risposta: Un documento standard di sensibilizzazione per sviluppatori e sicurezza delle applicazioni web.
- Injection: SQL, NoSQL, OS injection.
- Broken Authentication: Password deboli, session hijacking.
- Sensitive Data Exposure: Mancata crittografia dei dati in transito/a riposo.
- XML External Entities (XXE): Attacchi contro i parser XML.
- Broken Access Control: Utenti che agiscono al di fuori delle loro autorizzazioni previste.
- Security Misconfiguration: Account predefiniti, messaggi di errore dettagliati.
- Cross-Site Scripting (XSS): Iniezione di script dannosi.
Rarità: Comune Difficoltà: Media
27. Cos'è CI/CD?
Risposta:
- Continuous Integration (CI): Gli sviluppatori uniscono frequentemente le modifiche del codice in un repository centrale. Vengono eseguiti build e test automatizzati per verificare le modifiche. Obiettivo: rilevare rapidamente gli errori.
- Continuous Deployment (CD): Distribuzione automatica del codice in produzione dopo aver superato CI.
- Continuous Delivery: Preparazione automatica del codice per il rilascio, ma potrebbe essere necessaria l'approvazione manuale per la spinta finale.
Rarità: Comune Difficoltà: Facile
28. Spiega Docker vs. Macchine virtuali.
Risposta:
- Macchine virtuali (VM): Virtualizzano l'hardware. Ogni VM ha un sistema operativo completo (Guest OS), kernel e app. Pesante, avvio lento.
- Docker (Container): Virtualizza il sistema operativo. I container condividono il kernel del sistema operativo host, ma hanno spazi utente isolati (bins/libs). Leggero, avvio veloce, portatile.
Rarità: Comune Difficoltà: Facile
29. Cos'è Kubernetes?
Risposta: Kubernetes (K8s) è una piattaforma open source di orchestrazione di container. Automatizza la distribuzione, la scalabilità e la gestione di applicazioni containerizzate.
- Caratteristiche:
- Service Discovery & Load Balancing: Espone i container.
- Self-healing: Riavvia i container non riusciti.
- Automated Rollouts/Rollbacks: Aggiorna le app senza tempi di inattività.
- Secret & Configuration Management: Gestisce i dati sensibili.
Rarità: Media Difficoltà: Media
30. Come proteggi un'applicazione web Python?
Risposta:
- Input Validation: Sanitizza tutti gli input (moduli, corpi API, parametri di query).
- SQL Injection: Utilizzare ORM o query parametrizzate. Mai concatenazione di stringhe.
- XSS: Esegui l'escape dell'output dell'utente nei modelli (Jinja2 lo fa per impostazione predefinita).
- CSRF: Utilizzare i token CSRF per le richieste che modificano lo stato.
- Dependencies: Mantieni aggiornate le librerie (utilizza
pip-audito Snyk). - HTTPS: Applica SSL/TLS.
- Headers: Imposta le intestazioni di sicurezza (HSTS, X-Frame-Options, CSP).
- Secrets: Non commettere mai segreti su Git. Utilizzare le variabili di ambiente.
Rarità: Comune Difficoltà: Media



