Tecniche di Pair Programming con Claude Sonnet 3.5

Dopo aver esplorato le basi della collaborazione con Claude, vediamo come portare l’interazione al livello successivo. La chiave sta nel sapere come strutturare il dialogo per ottenere il massimo dall’IA.
Refactoring Collaborativo
Quando dobbiamo rifattorizzare codice complesso, Claude brilla nell’analisi e nei suggerimenti. Ecco un esempio reale:
Io: Ho questo controller monolitico di 500 righe che gestisce tutte le operazioni sugli ordini.
Come posso rifattorizzarlo?
Claude: Per aiutarti efficacemente, avrei bisogno di vedere:
1. Il codice del controller
2. Le dipendenze principali
3. I pattern di utilizzo più comuni
Puoi condividere queste informazioni?
Io: [condivido il codice del controller]
Claude: Analizziamo il codice step by step. Vedo diverse responsabilità mescolate:
- Autenticazione e autorizzazione
- Validazione degli input
- Logica di business degli ordini
- Notifiche
- Logging
Propongo di iniziare separando questi concetti.
Partiamo dall'autenticazione.
Vuoi vedere come estrarre questa parte in un servizio separato?
Io: Sì, mostrami come separare l'autenticazione
Claude: Creiamo prima l'interfaccia del servizio di autenticazione:
interface AuthenticationService {
validateToken(token: string): Promise<User>;
checkPermissions(user: User, resource: string): Promise<boolean>;
}
Questo permette di:
1. Testare il controller con un mock dell'autenticazione
2. Cambiare implementazione senza modificare il controller
3. Riutilizzare la logica in altri controller
Vuoi vedere l'implementazione completa?
[il dialogo continua...]
Esempio di Prompt Engineering per Review del Codice
Per ottenere una code review efficace, struttura il prompt così:
Puoi fare una code review di questa classe? Focus su:
- Principi SOLID
- Gestione errori
- Performance
- Sicurezza
[codice da revisionare]
Claude: Analizzerò il codice secondo i criteri richiesti.
SOLID:
- Single Responsibility: La classe gestisce sia autenticazione che logging
- Open/Closed: Manca un'interfaccia per estendere i metodi di auth
Gestione Errori:
- catch generico potrebbe nascondere errori critici
- mancano log strutturati per il debugging
Performance:
- La cache viene invalidata troppo frequentemente
- Query al DB non ottimizzate
Sicurezza:
- Password hash non usa salt
- Token JWT senza scadenza
Vuoi che approfondiamo uno di questi aspetti?
Dev: Approfondiamo la parte sicurezza
Claude: Ecco le modifiche necessarie per la sicurezza:
1. Password hashing:
import { hash, compare } from 'bcrypt';
// Prima
password: await crypto.hash(password)
// Dopo
const SALT_ROUNDS = 12;
password: await hash(password, SALT_ROUNDS)
JWT token:
// Prima
jwt.sign({ userId }, SECRET_KEY)
// Dopo
jwt.sign({
userId,
exp: Math.floor(Date.now() / 1000) + (60 * 60), // 1h
iat: Math.floor(Date.now() / 1000)
}, SECRET_KEY)
Vuoi che aggiunga anche rate limiting e protezione da brute force?
Refactoring Guidato dall’IA
Per il refactoring, usa prompt incrementali:
Dev: Devo rifattorizzare questo controller monolitico:
[codice controller 300 righe]
Claude: Iniziamo identificando le responsabilità:
1. Gestione autenticazione
2. Validazione input
3. Logica di business
4. Risposte HTTP
Suggerirei di iniziare separando l'autenticazione. Procediamo step by step?
Dev: Sì, iniziamo dall'autenticazione
Claude: Prima estraiamo l'interfaccia:
interface AuthService {
validateToken(token: string): Promise<User>;
refreshToken(token: string): Promise<string>;
}
Ora creiamo l'implementazione...
Debugging Collaborativo
Claude eccelle nell’analisi degli errori e nel suggerire soluzioni. Esempio:
Io: Ho questo errore in produzione che non riesco a riprodurre localmente:
TypeError: Cannot read property 'items' of undefined
at OrderProcessor.calculateTotal (orderProcessor.ts:45)
Claude: Per debuggare questo errore, ho bisogno di sapere:
1. Il codice di OrderProcessor
2. Da dove vengono i dati degli items
3. In quali condizioni si verifica l'errore
4. I log di produzione relativi all'errore
Puoi fornirmi queste informazioni?
Io: [condivido il codice e i log]
Claude: Guardando il codice e i log, vedo due possibili scenari:
1. OrderProcessor riceve un ordine undefined quando il database è sovraccarico
2. La race condition nella riga 43 può causare un accesso a items prima che l'ordine sia completamente caricato
Suggerirei di aggiungere questi controlli:
calculateTotal(order: Order) {
if (!order) {
throw new OrderNotFoundError('Order is undefined');
}
if (!order.items) {
throw new InvalidOrderError('Order has no items');
}
// resto del codice...
}
Vuoi che ti mostri anche come aggiungere logging strutturato per tracciare meglio questi casi?
Test Generation
Claude può aiutare a identificare casi edge e generare test:
Io: Devo scrivere test per questo servizio di pagamento. Quali scenari devo testare?
Claude: Analizziamo il servizio per identificare gli scenari critici. Vedo che gestisce:
- Pagamenti con carta
- PayPal
- Bonifici bancari
Ogni metodo di pagamento ha i suoi casi edge. Partiamo dai pagamenti con carta:
describe('CreditCardPayment', () => {
it('processa pagamento valido', async () => {
// implementazione test
});
it('gestisce carta scaduta', async () => {
// implementazione test
});
it('gestisce fondi insufficienti', async () => {
// implementazione test
});
});
Vuoi vedere l'implementazione dettagliata di questi test o preferisci procedere con gli scenari PayPal?
[il dialogo continua...]
Best Practices di Interazione
Per ottenere il massimo da Claude:
Fornisci Contesto Completo
Io: Come posso migliorare questo codice?
[condivido codice order.php]
Claude: Per darti suggerimenti pertinenti, avrei bisogno di sapere:
- Qual è lo scopo di questo codice
- In quale contesto viene utilizzato
- Quali sono i requisiti non funzionali
- Quali vincoli tecnici esistono
Puoi fornirmi queste informazioni?
Io: È un sistema di gestione ordini per un e-commerce. Usa PHP 7.4 e MySQL. Deve gestire circa 1000 ordini al giorno.
Claude: Grazie per il contesto. Vedo diverse aree di miglioramento:
1. Manca la gestione degli errori
2. Non c'è validazione degli input
3. Le query potrebbero essere ottimizzate
Vuoi che iniziamo dalla gestione errori?
Io: Sì, mostrami come implementeresti la gestione errori
Claude: Ecco un esempio di gestione strutturata degli errori...
[continua il dialogo con implementazione dettagliata]
Iterazione Incrementale
Io: Ho un problema di performance con questo endpoint.
Claude: Affrontiamo il problema step by step:
1. Posso vedere il codice dell'endpoint?
2. Hai dati sulle performance attuali?
3. Ci sono vincoli di tempo di risposta?
Io: L'endpoint fa una ricerca prodotti. Risponde in 3 secondi e vorremmo stare sotto il secondo.
[condivido codice]
Claude: Analizziamo i potenziali colli di bottiglia:
1. La query non usa indici
2. Manca la paginazione
3. C'è N+1 query problem
Iniziamo ottimizzando la query. Posso vedere lo schema del database?
Io: [condivido schema]
Claude: Ok, suggerirei queste modifiche immediate:
1. Aggiungere indice composito su (categoria, prezzo)
2. Implementare paginazione
3. Eager loading delle relazioni
Vuoi vedere l'implementazione di uno di questi?
Riassumiamo in alcunti punti le best practices per Dialogare con Claude
Fornisci Contesto: Includi sempre:
- Versioni delle dipendenze
- Constraints del progetto
- Casi d’uso specifici
Chiedi Spiegazioni: Se una soluzione non è chiara, fatti spiegare il ragionamento
- Verifica le Soluzioni: Non implementare ciecamente i suggerimenti
- Iterazione Progressiva: Affronta un problema alla volta
Limiti e Soluzioni
Claude ha dei limiti che devi conoscere:
- Non Può Testare il Codice: Fornisci sempre feedback sull’implementazione
- Contesto Limitato: Aggiorna Claude sulle modifiche precedenti
- Pattern Teorici: Adatta i suggerimenti al tuo caso specifico
Conclusione
Il pair programming avanzato con Claude è più efficace quando:
- Vengono effettuati prompt specifici
- Riceve contesto completo
- Può analizzare il problema incrementalmente
- Viene guidato con domande specifiche
Nel prossimo articolo della serie, vedremo come utilizzare Claude per l’ottimizzazione del codice.