Quando si inizia a programmare, è facile pensare che il lavoro di uno sviluppatore consista principalmente nello scrivere codice. Dopotutto, è la parte più visibile del mestiere: editor aperto, tastiera, righe di codice che scorrono sullo schermo.

La realtà è diversa.

Il codice è solo il mezzo attraverso cui una soluzione viene implementata. Prima del codice c’è un’attività molto più importante, ovvero: capire il problema.

Il codice non risolve problemi

Può sembrare una provocazione, ma è così.

Il codice non risolve problemi.

Le persone risolvono problemi utilizzando il codice come strumento.

Se non hai compreso il problema:

  • Scriverai la soluzione sbagliata.
  • Introdurrai complessità inutile.
  • Perderai tempo a correggere errori che nascono da un’analisi incompleta.

Un programma perfettamente funzionante può essere comunque sbagliato se risolve il problema sbagliato.

La differenza tra programmare e sviluppare

rendiamo un esempio semplice.

Ti viene chiesto di creare un sistema di prenotazione per un ristorante.

Un approccio superficiale è:

  1. Quali tabelle devo creare?
  2. Quale framework devo usare?
  3. Come implemento il form?

Un approccio orientato al problem solving è:

  • Quante persone possono prenotare contemporaneamente?
  • Come gestisco gli orari occupati?
  • Cosa succede se un cliente annulla?
  • Come evito doppie prenotazioni?

Nel primo caso stai pensando al codice.

Nel secondo stai pensando al problema.

Ed è sempre il secondo approccio a produrre software migliore.

I migliori sviluppatori passano più tempo a pensare

Molti principianti immaginano che i developer più esperti scrivano codice velocemente perché conoscono meglio il linguaggio.

In parte è vero, ma spesso il motivo è un altro:

Passano molto tempo a ragionare prima di scrivere.

Analizzano:

  • requisiti;
  • casi limite;
  • vincoli;
  • possibili errori;
  • impatto delle scelte.

Quando iniziano a scrivere, gran parte del lavoro concettuale è già stata fatta.

Scomporre i problemi

Una delle abilità più importanti nello sviluppo software è la capacità di trasformare un problema complesso in problemi più piccoli.

Quando frequentavo l’università, durante una delle prime lezioni di programmazione, un docente disse una frase che mi è rimasta impressa negli anni:

L’informatica è l’arte di risolvere un problema scomponendolo in problemi più piccoli facilmente risolvibili.

All’epoca mi sembrava una definizione molto semplice, quasi banale. Con il tempo ho capito quanto fosse profonda.

Gran parte del lavoro di uno sviluppatore consiste proprio in questo: prendere un problema che appare complesso, confuso o troppo grande da affrontare e dividerlo in una serie di problemi più piccoli, ciascuno dei quali può essere compreso e risolto singolarmente.

C’è però una precisazione importante.

Scomporre un problema non significa dividerlo all’infinito.

Con l’esperienza ho capito che esiste una linea di demarcazione che non andrebbe superata. Se da un lato suddividere un problema lo rende più comprensibile, dall’altro un’eccessiva frammentazione può avere l’effetto opposto.

Quando iniziamo a creare troppi livelli di astrazione, troppi componenti o troppe orchestrazioni tra parti diverse del sistema, la complessità non diminuisce: si sposta.

A quel punto i piccoli problemi che sembravano semplici da gestire tornano a diventare enormi, perché per comprenderne uno è necessario capire come interagisce con decine di altri elementi.

È uno dei motivi per cui nel software la soluzione migliore raramente è la più sofisticata. Molto spesso è quella che riesce a mantenere il giusto equilibrio tra scomposizione e semplicità.

Saper dividere un problema è una competenza fondamentale. Sapere quando fermarsi lo è altrettanto.

Più un developer migliora in questa capacità, meno i problemi sembrano insormontabili.

Adesso facciamo un esempio di un problema che potrebbe capitare a chiunque a lavoro:

Devo creare un sistema di autenticazione.

Può sembrare enorme, ma può essere diviso in:

  1. Registrazione utente
  2. Salvataggio credenziali
  3. Verifica password
  4. Gestione sessione
  5. Logout
  6. Recupero password

All’improvviso il problema diventa molto più gestibile.

Questa capacità vale più della conoscenza di qualsiasi framework.

Il problema del “tutorial mindset”

Molti sviluppatori alle prime armi cercano immediatamente un tutorial.

È comprensibile, ma c’è un rischio, ovvero che invece di imparare a risolvere problemi, imparano a cercare soluzioni già pronte.

Quando il problema cambia leggermente:

  • il tutorial non basta
  • la documentazione sembra incomprensibile
  • tutto diventa più difficile

Il problem solving costruisce autonomia, i tutorial, da soli, no.

Come allenare il problem solving

Non esistono scorciatoie, è necessario esercitarsi.

Ecco alcune strategie utili secondo me:

  • progettare prima di scrivere codice
  • usare carta e penna per schematizzare
  • descrivere la soluzione in linguaggio naturale
  • scomporre il problema in passi semplici
  • chiedersi sempre “cosa succede se…?”

Come tutte le migliori metodologie, più lo fai, più diventa naturale, più diventa naturale e più porsi quelle domande diventa una buona abitudine e allora tutto ciò diventerà semplice come bere un bicchiere d’acqua.

Una precisazione sui tutorial

A questo punto, a chi è arrivato fin qui potrebbe sembrare che i tutorial siano qualcosa da evitare. Non è così. Anch’io, come probabilmente la maggior parte degli sviluppatori, ne ho seguiti molti. La differenza stava nell’obiettivo.

Non cercavo una soluzione già pronta da copiare, ma degli input utili per alimentare il ragionamento che stavo facendo. Il tutorial diventava uno strumento per osservare come qualcun altro aveva affrontato un problema simile al mio, capirne il ragionamento attorno a quel problema, per raccogliere idee e confrontare approcci.

In altre parole, non stavo delegando il problema al tutorial. Stavo usando il tutorial per ottenere nuovi spunti e continuare a ragionare autonomamente. È una differenza sottile ma fondamentale.

Chi usa un tutorial per trovare la risposta tende a bloccarsi quando il contesto cambia. Chi lo usa per comprendere il processo di ragionamento sviluppa invece una maggiore capacità di adattamento.

È un po’ come nello studio della matematica. Quando si affronta un teorema, non si cerca semplicemente di memorizzare ogni singolo passaggio. Si parte da un’ipotesi e, attraverso una serie di ragionamenti logici, si arriva alla dimostrazione.

Nella programmazione accade qualcosa di molto simile. Cercare di ricordare a memoria tutte le possibili soluzioni è praticamente impossibile: i problemi cambiano, i requisiti evolvono e le variabili in gioco sono troppe. Ciò che conta davvero è comprendere il processo che porta alla soluzione.

Per questo motivo ho sempre visto i tutorial come uno strumento per osservare il ragionamento di altri sviluppatori e arricchire il mio, non come una raccolta di risposte da imparare a memoria.

Un buon tutorial non dovrebbe sostituire il pensiero critico. Dovrebbe stimolarlo.

Conclusione

Scrivere codice è importante, ma il codice è l’ultima fase del processo, non la prima. Prima viene la comprensione del problema, poi arriva la progettazione della soluzione e solo alla fine arriva il codice.

Per questo motivo il problem solving viene prima della programmazione, perché non puoi implementare una buona soluzione a un problema che non hai ancora capito. Saresti qualcuno che usa il codice per risolvere problemi, ma un developer non è qualcuno che scrive codice, ma una persone che risolve problemi ponendosi le giuste domande e agendo di conseguenza.