Cosa ci insegna “A Philosophy of Software Design”

Nei giorni scorsi Andrea ha condiviso con il team una video-intervista davvero interessante: Gergely Orosz (The Pragmatic Engineer) intervista il professor John Ousterhout, autore del libro A Philosophy of Software Design. La trovate qui sotto.

Questa intervista ruota attorno a un libro che ha avuto un impatto importante su di me e sul team. Lo abbiamo scoperto durante la pandemia grazie a Iacopo, ed è diventato uno degli appuntamenti più significativi del nostro book club di team.

“A Philosophy of Software Design” è uno dei testi fondamentali nella mia crescita come engineer. Ousterhout non offre ricette facili o best practice da applicare in modo meccanico: propone piuttosto un nuovo modo di pensare al codice. Un modo che rende il software più umano, più collaborativo, e soprattutto più duraturo nel tempo. Consiglio questo libro a chiunque scriva codice.

Il libro si apre con una frase emblematica:

Writing computer software is one of the purest creative activities in the history of the human race

Qui sotto trovate un riassunto dell’intervista, buona lettura.

Una carriera tra accademia e industria

Doing both has actually made me better at both
John Ousterhout ha sempre desiderato lavorare sia nel mondo accademico che in quello industriale. Dopo il dottorato, ha seguito il consiglio di iniziare dalla carriera accademica, approdando a Berkeley, dove ha trascorso 14 anni fruttuosi.
Tuttavia, col tempo è cresciuta in lui la voglia di costruire software reale e affrontare sfide pratiche, il che lo ha portato a lasciare l’università per tuffarsi nel mondo delle startup nella Silicon Valley.
Durante i successivi 14 anni, ha lavorato a Sun Microsystems e ha fondato alcune aziende. Nonostante i risultati fossero solo “moderatamente” soddisfacenti, ha imparato moltissimo. Tuttavia, sentiva che la sua vera passione era insegnare e riflettere sulle fondamenta della progettazione del software. Questo lo ha spinto a tornare nel mondo accademico, accettando una posizione a Stanford.
Per Ousterhout, il passaggio continuo tra industria e accademia ha arricchito entrambe le esperienze. L’esposizione a contesti diversi gli ha dato una prospettiva unica, permettendogli di affrontare sia l’insegnamento che la progettazione pratica con maggiore profondità.

Le vere differenze tra industria e accademia

In academia, if a project doesn’t work, you just say “oops” and move on. In a company, you can’t do that
Nonostante le apparenze, Ousterhout sostiene che lavorare nell’industria, soprattutto in startup, non sia così diverso dall’accademia: in entrambi i casi si lavora in piccoli team su progetti innovativi. Tuttavia, il contesto industriale introduce una varietà di interlocutori – come venditori, investitori e manager – che raramente si incontrano nel mondo accademico.
Una differenza sostanziale è nella cultura del fallimento. Nel mondo accademico è accettato che un progetto possa fallire, mentre nel mondo industriale spesso si cerca di “salvare la faccia”, alimentando pressioni e strategie di marketing che a volte sfociano nell’inganno. Questo aspetto è uno dei motivi per cui Ousterhout ha preferito tornare all’università.
L’onestà intellettuale e la libertà di dire “non ha funzionato” sono per lui elementi centrali per un lavoro sano e produttivo. Questo contrasta con le dinamiche dell’industria, dove anche gli insuccessi vanno “mascherati” per sopravvivere.

Tactical Tornadoes: genio o caos?

Tactical tornadoes leave a wave of destruction behind and typically other engineers must clean up the messes
Ousterhout introduce il concetto di “tactical tornado”: programmatori incredibilmente rapidi nel consegnare codice, ma che operano in modo esclusivamente tattico, trascurando la qualità a lungo termine. Sono spesso considerati eroi dalle aziende per la loro produttività apparente, ma lasciano dietro di sé un codice difficile da mantenere.
La loro figura è diffusa in startup e contesti dove la velocità è più apprezzata della sostenibilità tecnica. Tuttavia, il danno cumulativo generato da queste persone – debito tecnico, mancanza di coerenza architetturale – può avere un costo altissimo per l’organizzazione nel lungo termine.
Per Ousterhout, il vero “10x engineer” è colui che crea design puliti e facili da evolvere, anche se scrive meno codice. È una figura strategica, che pensa al futuro del sistema più che alla consegna immediata.

L’impatto dell’AI sulla programmazione

Software design is going to become more and more important… and it’s sad that we don’t teach it in our universities at all
Con l’esplosione degli strumenti AI e LLM, la scrittura di codice di basso livello sta diventando sempre più automatizzata. Ousterhout osserva che queste tecnologie sono simili ai “tactical tornadoes”: producono codice rapidamente, spesso su richiesta, ma non necessariamente con una buona architettura.
Il vero punto interrogativo riguarda la capacità dell’AI di affrontare compiti di progettazione ad alto livello. Secondo Ousterhout, al momento gli strumenti non mostrano capacità significative in questo campo. Per questo, la progettazione software diventerà ancora più centrale nel lavoro degli sviluppatori umani.
Purtroppo, sottolinea con rammarico, il design software non viene insegnato sistematicamente nelle università. I corsi si concentrano su linguaggi e strumenti, ma trascurano le competenze necessarie per progettare sistemi complessi, esattamente quelle che l’AI fatica a replicare.

Che cos’è davvero il design del software?

Decomposition is the most important idea in all of computer science
Per Ousterhout, la progettazione software è un problema di decomposizione: prendere un sistema complesso e suddividerlo in componenti più piccoli e indipendenti. Questo processo è al centro di tutta l’informatica, e distingue la progettazione dall’implementazione vera e propria.
Con l’evoluzione degli strumenti, oggi è possibile creare applicazioni intere partendo da template o prompt AI. Ma la capacità di decidere come suddividere un sistema rimane una competenza umana. La progettazione non è solo struttura, ma anche empatia per chi dovrà leggere e mantenere il codice.
In un mondo in cui l’AI scriverà sempre più codice, Ousterhout crede che il valore degli ingegneri si sposterà verso le decisioni di design. Saper progettare bene diventerà il vero “superpotere” nel software engineering.

Oltre TDD e Design Patterns

There’s so much more to design than just picking one of a half a dozen patterns
Ousterhout riflette sulla diminuzione dell’interesse verso metodologie come il Test-Driven Development (TDD) e i design patterns classici (come quelli del “Gang of Four”). Negli anni 2000, queste pratiche erano molto in voga e considerate fondamentali per una buona progettazione. Tuttavia, oggi sembrano essere diventate meno centrali nel dibattito tecnico.
Secondo il professore, TDD non è propriamente una tecnica di design e, anzi, potrebbe ostacolare una buona progettazione perché induce a pensare solo a piccoli passi, senza considerare l’architettura nel suo insieme. I design pattern, invece, rappresentano solo soluzioni prefabbricate per problemi comuni e coprono una minima parte del lavoro di design.
La progettazione vera richiede creatività, riflessione sui compromessi, e capacità di astrarre problemi complessi, elementi che vanno ben oltre l’applicazione meccanica di pattern o test.

Due strategie per affrontare il design

The actual process of design is some combination… an iterative kind of back and forth
Quando si inizia a progettare un sistema, esistono due approcci principali: top-down e bottom-up. Nel primo si parte dalla visione globale e si suddivide progressivamente in componenti. Nel secondo, si costruiscono prima elementi locali per poi integrarli. Ousterhout spiega che nessuno dei due approcci funziona da solo: il design è sempre un processo iterativo che alterna visione d’insieme e dettaglio.
Il problema è che, spesso, i progettisti inesperti adottano un approccio bottom-up perché più immediato, trascurando l’architettura generale. Questo può portare a soluzioni poco coerenti. Al contrario, un design esclusivamente top-down rischia di non tener conto delle complessità reali che emergono durante lo sviluppo.
La verità sta nel mezzo: bisogna essere pronti a sperimentare, sbagliare e correggere. Il buon design nasce da un continuo ciclo di tentativi, feedback e miglioramenti.

Come gestire la complessità

There are things you can do to eliminate complexity completely… and others where you must hide it
La gestione della complessità è al centro della progettazione software. Ousterhout distingue due strategie principali: la prima consiste nell’eliminare del tutto la complessità, ad esempio evitando casi speciali attraverso un design più generale. La seconda, inevitabile in molti casi, consiste nel nascondere la complessità dietro interfacce ben progettate.
Non tutta la complessità può essere evitata. Alcuni aspetti sono intrinsecamente complicati, ma è fondamentale che restino isolati in punti precisi del sistema, così da non contaminare il resto del codice.
Un buon design deve saper usare entrambe le strategie. Eliminare la complessità dove possibile e modularizzarla altrove permette di costruire sistemi più semplici da capire, evolvere e manutenere.

Deep Modules: semplificare nascondendo

You want the most functionality you can get for the simplest possible interface
Il concetto di “deep module” è centrale nella filosofia di Ousterhout. Un modulo “profondo” ha un’interfaccia semplice ma incapsula molta logica interna, mentre un modulo “superficiale” ha un’interfaccia estesa ma poca sostanza. Il primo è preferibile perché riduce il carico cognitivo per chi lo utilizza.
I moduli profondi nascondono la complessità e proteggono gli altri componenti del sistema dai dettagli implementativi. Questo favorisce la coerenza architetturale e migliora la manutenibilità.
Un errore comune, secondo Ousterhout, è frammentare eccessivamente il codice – ad esempio spingendosi troppo nella direzione del “Clean Code” – perdendo così la profondità. A volte unire due moduli correlati porta a una struttura più profonda e semplice.

Errori: meglio non doverli gestire

Every exception you throw is imposing complexity on the users of your class
Ousterhout considera la gestione degli errori una delle principali fonti di complessità nei sistemi software. Ogni eccezione introduce un caso speciale che l’utente del modulo deve gestire, aumentando il rischio di bug e difficoltà nella manutenzione.
Il suggerimento è cercare di “definire gli errori fuori dall’esistenza”, cioè progettare i moduli in modo che certe condizioni problematiche non possano nemmeno verificarsi. Così, si semplifica il codice e si riducono le possibilità di errore.
Attenzione, però: questa filosofia può essere fraintesa. Eliminare gli errori non significa ignorarli. È necessario valutare caso per caso, con empatia verso l’utente del modulo, riducendo al minimo le eccezioni reali e fornendo interfacce robuste e prevedibili.

Il valore di ripensare la prima idea

Smart people often underperform because they insist on implementing the first idea that comes to mind
Un tema ricorrente nei corsi di Ousterhout è l’importanza di non fermarsi alla prima idea. Molti programmatori brillanti si innamorano della propria intuizione iniziale, ma questo li porta a ignorare alternative migliori e a limitare la qualità del design.
Progettare due volte – ossia esplorare almeno un’alternativa concreta prima di decidere – non è una perdita di tempo. Anche se si spende solo l’1-2% del tempo totale del progetto a confrontare idee, i benefici in termini di semplicità, chiarezza e stabilità possono essere enormi.
Il vero progettista sa fare compromessi, valutare scenari alternativi e scegliere la soluzione che meglio gestisce la complessità. Il design non è un atto istantaneo, ma un processo esplorativo.

Documenti di design: la lezione da Uber

Durante la sua esperienza a Uber, si è affermata la pratica di scrivere documenti di design prima di implementare un sistema. Questi documenti includevano obiettivi, scelte architetturali, e – cosa fondamentale – una sezione con le alternative considerate. Questo approccio obbligava a confrontare diverse soluzioni prima di impegnarsi su una sola strada.
Secondo Ousterhout, questa pratica è perfettamente in linea con l’idea di progettare due volte. Anche se apparentemente richiede più tempo, migliora la qualità delle decisioni, stimola il confronto e previene errori a lungo termine.
Nel contesto di un progetto, dedicare anche solo l’1–2% del tempo totale alla valutazione di più alternative può generare un impatto sproporzionatamente positivo sul risultato finale.

Empatia: la dote nascosta del buon designer

The most important attribute of a really good designer is the ability to change their mindset
Per Ousterhout, un buon progettista non deve solo pensare alla funzionalità interna del modulo, ma anche mettersi nei panni dell’utente – che sia un altro sviluppatore o il cliente finale. Questa capacità di cambiare prospettiva è ciò che rende possibile creare interfacce semplici, intuitive e robuste.
L’empatia è spesso sottovalutata nell’ingegneria del software, ma è alla base di ogni buon design. Quando si progettano interfacce o API, bisogna evitare di esporre dettagli inutili e offrire un’esperienza prevedibile e coerente.
Questa capacità ha valore anche nei contesti sociali: pensare come l’altro riduce incomprensioni, migliora la collaborazione e rende il software più umano.

Design Review: il potere della collaborazione

When multiple people think about a design, you usually end up with better ideas
Le design review sono incontri nei quali un team discute e valuta piani progettuali prima di iniziare a scrivere codice. Ousterhout ne sottolinea il valore, affermando che coinvolgere più menti porta quasi sempre a soluzioni migliori rispetto al lavoro individuale.
Durante la sua carriera e nei suoi corsi a Stanford, ha sempre incentivato queste pratiche, seppur con approcci informali. L’importante è evitare la “paralisi da analisi”, trovando il giusto equilibrio tra discussione e azione.
Una cultura del confronto aperto, dove si esplorano alternative e si discutono i trade-off, è alla base dei team ad alte prestazioni.

Lavagne e idee: la forza della presenza fisica

There’s something special about in-person just getting your ideas out there
Ousterhout celebra l’uso delle lavagne fisiche come strumenti potenti per stimolare la creatività nei team. Nei contesti più innovativi, è comune vedere lavagne ovunque: servono per esprimere idee rapidamente, visualizzare problemi e costruire soluzioni collaborative.
Rispetto agli strumenti digitali, le lavagne favoriscono una comunicazione più fluida e istintiva, specie in discussioni complesse dove diagrammi e flussi aiutano a chiarire i concetti.
La collaborazione di persona, specialmente durante la fase di ideazione, ha un impatto significativo sulla qualità del design. Anche in un mondo sempre più remoto, questo tipo di interazione resta insostituibile.

Discussioni strategiche alla lavagna

Everyone’s argument goes on the board and the discussion just naturally reaches a point
Ousterhout ha sviluppato una tecnica per facilitare le decisioni nei team: durante una riunione, tutte le argomentazioni pro e contro vengono scritte su una lavagna. Ogni partecipante è libero di contribuire, ma nessuno può ripetere punti già espressi.
Questo approccio permette di strutturare il confronto, evitando circoli viziosi e discussioni senza fine. Al termine, si effettua un “voto di paglia” (straw poll) per capire quale opzione abbia il consenso maggiore.
Sorprendentemente, anche quando le discussioni sembrano molto polarizzate, questo metodo porta spesso a decisioni quasi unanimi. È uno strumento potente per sbloccare team intelligenti e motivati.

Il giusto equilibrio tra design e azione

Design permeates the entire development process
Ousterhout rifiuta l’idea che si debba scegliere tra progettazione anticipata e sviluppo iterativo. Secondo lui, la progettazione dovrebbe essere continua, presente in ogni fase: dalla pianificazione iniziale al debugging finale.
Un minimo di design iniziale è fondamentale per orientare lo sviluppo, ma bisogna essere pronti a modificare le scelte man mano che emergono nuovi elementi. È inutile pianificare tutto in anticipo, ma è anche dannoso iniziare a codificare senza una visione.
Il segreto sta nell’agilità mentale: partire con un’ipotesi, testarla nel codice, e poi riflettere e adattare. La progettazione non finisce mai.

Perché scrivere “A Philosophy of Software Design”

Ousterhout ha deciso di scrivere il libro dopo anni di frustrazione nel constatare che nessun corso universitario insegnava veramente la progettazione software. Non strumenti, non processi, ma il pensiero progettuale vero e proprio.
Dopo essere tornato a Stanford, ha creato un corso per colmare questo vuoto. Il libro è nato come estensione naturale di quel corso: una raccolta di principi e riflessioni maturate in anni di esperienza sia accademica che industriale.
Per l’autore, il design è una delle attività creative più profonde dell’ingegneria, e merita lo stesso livello di attenzione e sistematizzazione della scrittura o della matematica.

Le novità della seconda edizione

The notion of depth captures the trade-offs and keeps you from going astray
Nella seconda edizione del libro, Ousterhout ha ampliato il concetto di “profondità” (depth) per guidare meglio le decisioni di design. Questo principio aiuta a bilanciare la complessità nascosta con la semplicità delle interfacce.
Ha anche affrontato critiche e malintesi legati alla sua posizione su metodi brevi e microservizi. Spesso, la spinta verso la frammentazione estrema compromette la chiarezza e aumenta il debito cognitivo.
La nuova edizione punta a fornire strumenti concettuali più solidi per evitare approcci troppo estremi, promuovendo un design centrato sulla coerenza e sulla comprensibilità.

Il corso a Stanford: imparare come si progetta

l corso di Ousterhout a Stanford è costruito sull’idea che il design software possa essere insegnato anche a chi ha appena imparato a programmare. Ispirato ai laboratori di scrittura, il metodo didattico prevede che ogni studente realizzi un progetto, riceva un feedback dettagliato e lo riscriva più volte. Questo processo iterativo permette di interiorizzare i concetti, migliorare concretamente e sviluppare una maggiore consapevolezza progettuale.

Il progetto centrale del corso è la realizzazione del protocollo di consenso Raft, articolato in due fasi. Gli studenti iniziano da zero, senza schemi o indicazioni predefinite, affrontando le complessità reali dei sistemi distribuiti. Tutti ricevono una code review personalizzata, con decine di commenti mirati, e sono tenuti a rielaborare il codice sulla base del feedback ricevuto, proprio come accade nei laboratori di scrittura.

Questo approccio intensivo e strutturato ha un impatto profondo: gli studenti non solo imparano a scrivere codice, ma acquisiscono un modo di pensare più riflessivo e professionale. Imparano a progettare software con rigore e chiarezza, e spesso portano queste competenze nel mondo del lavoro, dove riescono a distinguersi anche rispetto a colleghi con maggiore esperienza.

Conclusioni

Nella parte finale dell’intervista, Ousterhout riflette brevemente su alcuni temi a bruciapelo. Quando gli viene chiesto di consigliare libri, ammette che non ci sono molte risorse valide là fuori, ma segnala una lista disponibile sul suo sito web.
Esprime anche interesse per il feedback: è sempre aperto a critiche costruttive, perché considera il design un campo ancora in evoluzione. Nessuno ha tutte le risposte, e la comunità degli sviluppatori dovrebbe sentirsi parte di un percorso collettivo di apprendimento.
Il messaggio finale è chiaro: più che trasmettere verità assolute, l’obiettivo del suo lavoro – sia nei corsi che nel libro – è stimolare una maggiore consapevolezza. Se più persone iniziano a pensare seriamente al design, la qualità del software globale potrà solo migliorare.

Published by

Salvatore Cordiano

Empathetic Rebel Engineer

Leave a Reply

Your email address will not be published. Required fields are marked *