✨ Clean Code: L’Arte della Manutenibilità
“Scrivi sempre codice come se la persona che dovrà mantenerlo fosse un violento psicopatico che sa dove abiti.” — Robert C. Martin (Uncle Bob)
::: info Clean Code non significa codice “perfetto”, ma codice leggibile, testabile e manutenibile. Un codice è pulito quando sembra scritto da qualcuno a cui importa del proprio lavoro e dei colleghi. :::
1. Nomi Significativi (Meaningful Names)
Variabili, funzioni e classi devono rivelare l’intento. Se hai bisogno di un commento per spiegare cosa fa una variabile, il nome è sbagliato.
- ❌ Bad:
d = 86400 # seconds in a day - ✅ Good:
SECONDS_IN_A_DAY = 86400 - ❌ Bad:
def get_vals(lst): ... - ✅ Good:
def filter_active_users(users: List[User]) -> List[User]: ...
2. Funzioni: Piccole e Focalizzate (S.R.P.)
Una funzione deve fare una sola cosa e farla bene. Se una funzione ha più di 20 righe, probabilmente sta facendo troppo.
Esempio di Refactoring (Python)
❌ Codice Sporco (Fa troppe cose):
def process_data(data):
# Validation
if not data:
return False
# Formatting
formatted = data.strip().lower()
# Saving
with open("log.txt", "a") as f:
f.write(formatted)
return True
✅ Clean Code (Responsabilità separate):
def is_valid(data: str) -> bool:
return bool(data and data.strip())
def format_entry(data: str) -> str:
return data.strip().lower()
def save_to_log(entry: str, filename: str = "log.txt") -> None:
with open(filename, "a") as f:
f.write(entry)
# Orchestration is now clear
def process_data_clean(data: str) -> bool:
if not is_valid(data):
return False
entry = format_entry(data)
save_to_log(entry)
return True
3. I Principi S.O.L.I.D. (Sintesi)
Questi 5 principi sono le fondamenta della programmazione orientata agli oggetti moderna:
- Single Responsibility: Una classe deve avere un solo motivo per cambiare.
- Open/Closed: Il software deve essere aperto all’estensione, ma chiuso alla modifica.
- Liskov Substitution: Le sottoclassi devono poter sostituire le classi base senza rompere il sistema.
- Interface Segregation: Meglio molte interfacce specifiche che una generica (“monolitica”).
- Dependency Inversion: Dipendi dalle astrazioni, non dalle implementazioni concrete.
4. Commenti: Solo il “Perché”, mai il “Cosa”
Il codice dovrebbe spiegare cosa sta facendo. I commenti servono solo a spiegare perché è stata presa una decisione non ovvia o complessa.
// ❌ Bad: Spiega l'ovvio
i++; // increment i
// ✅ Good: Spiega un vincolo tecnico o di business
// We use a 10ms delay here to allow the hardware sensor to stabilize
// after the power-on sequence.
std::this_thread::sleep_for(std::chrono::milliseconds(10));
5. Testabilità
Il codice pulito è intrinsecamente facile da testare. Se non riesci a scrivere uno Unit Test per una funzione, significa che la funzione è troppo accoppiata o troppo complessa.
- Usa la Dependency Injection per passare i servizi (es. database) alle funzioni invece di crearli internamente. In questo modo puoi passarne dei “mock” durante i test.
⚖️ Critical Spirit: Pragmatismo vs Dogmatismo
Non diventare un fanatico del Clean Code a scapito delle performance o delle scadenze.
- Performance: In C++, a volte il codice più “pulito” (astrazioni pesanti) può essere più lento. In sezioni critiche (Hot Paths), la performance vince sull’estetica.
- Contesto: Uno script “usa e getta” per migrare dati non ha bisogno della stessa pulizia di un core engine finanziario.
Ultimo aggiornamento: {{UPDATE_DATE}} | Tags: #CleanCode #SOLID #BestPractices #Refactoring