Sul lavoro e nella vita, tutti incontriamo ostacoli e insuccessi; la maggior parte di noi vive questi eventi come esperienze "brutte", da evitare.
Ma lo sono davvero?
Dopo anni di sviluppo software e project management, possiamo dire che una gran parte del valore di una squadra di lavoro consiste nella familiarità con avversità e fallimenti e nelle risposte, emotive e operative, che i membri della squadra sono riusciti a sviluppare e rodare nel tempo.
No, non stai per leggere un pezzo motivazionale in cui ti spieghiamo che devi stare fuori dalla comfort zone per vivere a pieno la tua vita e diventare te stesso. Invece, vorremmo provare a darti una piccola anteprima di quelli che sono i problemi quotidiani che un programmatore informatico affronta progetto dopo progetto, e che diventano tanto più presenti e sfidanti quanto più si diventa esperti e si viene investiti di maggiori responsabilità.
L'ostacolo è la via
La citazione è volontaria. Se non sai di cosa stiamo parlando, prova a cercare su internet il titolo "The obstacle is the way", libro di Ryan Holiday, un filosofo stoico contemporaneo dotato di molto sale in zucca.
Lo citiamo perché, a sua volta, Ryan cita un passaggio dei "Pensieri" di Marco Aurelio, altro filosofo stoico, nonché imperatore romano: secondo il buon Marco Aurelio, gli ostacoli che si frappongono tra noi e i nostri obiettivi molto spesso si rivelano essere esattamente i punti da cui è necessario passare per raggiungerli. Secondo questa lettura della realtà, gli ostacoli costituiscono al contempo un'avversità ma anche una bussola. Tanto per fare un esempio da parabola buddhista:
"se il tuo obiettivo è raggiungere la cima di una montagna, seguire la salita è esattamente ciò che ti porterà a destinazione".
Torniamo alla vita del programmatore: il nostro lavoro consiste nel risolvere problemi e dunque, ogni volta che un problema si frappone tra noi e la consegna, ci sta semplicemente indicando che c'è del lavoro da fare. La non-notizia è che quello è esattamente il motivo per cui veniamo pagati: se non ci fossero ostacoli, non ci sarebbe lavoro; allo stesso modo, tentare di eluderli è futile, perché la capacità di affrontarli costituisce ciò che fa la differenza tra il professionista e il dilettante. Ma quindi, di quali ostacoli stiamo parlando? Il primo sono chiaramente le competenze. Quelle valgono per ogni professione: il tiramisù ai pasticcieri, i ponti agli ingegneri, il software ai programmatori.
Restringendo il campo, per un programmatore gli ostacoli sono tutti quei passaggi obbligati da superare per arrivare sani e salvi alla consegna di un progetto, con un cliente soddisfatto e un bilancio di commessa in attivo.
Quali ostacoli incontra un programmatore informatico
Le scelte giuste vengono dall'esperienza, l'esperienza viene dalle scelte sbagliate.
Eraclito
Un pessimista vede una difficoltà in ogni opportunità; un ottimista vede un'opportunità in ogni difficoltà
Winston Churchill
Quelle che per un novizio sono le difficoltà più insormontabili, sono proprio quelle barriere che, una volta superate, faranno di lui un esperto. Con ciò vorremmo ribadire molto chiaramente il concetto: non è possibile diventare esperti aggirando gli ostacoli, ma solo passandoci attraverso.
Nel nostro mondo, gli ostacoli sono cose di questo tipo:
-
Scadenze stringenti
-
Opacità dei requisiti
-
Volatilità dei requisiti
-
Mancanza di competenze o conoscenze specifiche necessarie
-
Architettura studiata miseramente (poca manutenibilità)
-
Codice scritto miseramente (prono ad errori)
Embè? Queste sarebbero cose che non capitano agli esperti?
Non stiamo dicendo questo, assolutamente. Il punto è che un esperto queste situazioni le riconosce, le previene, le mitiga e, nei limiti del possibile, le risolve. Non esiste un progetto senza ostacoli: vengono fuori problemi anche quando si cerca di riprodurre un semplice tutorial, figurarsi in un progetto vero che deve funzionare nel mondo reale.
Iniziamo, dunque, a capire in che modo è possibile riconoscere e quindi prevedere l'arrivo di un ostacolo. In gergo si dice che i problemi si "annusano" e, nel caso del codice, si parla proprio di smell (puzza), con riferimento a caratteristiche del codice o del progetto che individuano una probabile fonte di problemi.
Distinguiamo subito due categorie di ostacoli: quelli che riguardano la progettazione e quelli che riguardano lo sviluppo.
Gli ostacoli di progettazione
Gli ostacoli di progettazione sono i primi che abbiamo elencato; riguardano 5 pilastri di un progetto: obiettivo, scadenze, costi, valore, qualità. I primi tre sono quelli definiti nel project management classico, gli ultimi due vengono individuati e aggiunti nell'ambito del project management di tipo agile, che raggruppa i primi tre sotto l'etichetta di vincoli.
In ogni progetto alcuni di questi pilastri saranno fissati, altri saranno prioritari ma flessibili, altri invece saranno liberi di discostarsi dalle aspettative.
Vediamo velocemente questi pilastri uno ad uno, poi procediamo:
-
L'obiettivo è lo scopo del progetto, ciò che dev'essere raggiunto o realizzato.
-
Le scadenze sono i termini temporali entro i quali dev'essere raggiunto l'obiettivo finale, o anche eventuali obiettivi intermedi.
-
I costi rappresentano la quantità di risorse lavorative ed economiche impiegate sul progetto.
-
Il valore è ciò che il cliente ottiene dal prodotto (incremento di produttività, di sicurezza, di guadagni, abbattimento di costi, ecc).
-
La qualità è una misura della bontà intrinseca del prodotto in termini di manutenibilità, fallibilità, durabilità, adattabilità, ecc.
L'ostacolo degli ostacoli: tutto fissato
Questa è una situazione in cui un project manager serio farà in modo di non trovarsi mai. Non è possibile prevedere tutto e non è possibile fissare tutti e 5 i parametri. Sia che si prenda in esame la tripletta "obiettivo/scadenze/costi", sia che si consideri "vincoli/valore/qualità", sarà sempre ideale averne uno fissato, uno flessibile e uno libero. È, dunque, sensato sentire puzza di… bruciato (o anche di peggio) quando un progetto viene presentato con tutti questi parametri fissati.
A quanto ne sappiamo, l'unico modo professionale per superare questo ostacolo è presentare una relazione più o meno formale ai responsabili del progetto (o eventualmente al cliente) spiegando che c'è un elevatissimo rischio che qualcuno di questi vincoli venga bucato e quindi esortando la controparte ad individuare almeno un vincolo imprescindibile e almeno un vincolo sacrificabile.
Gli ostacoli classici: pianificazione e requisiti
Questi sono gli ostacoli che mettono a repentaglio i pilastri del project management classico. Principalmente, stiamo parlando di scadenze irrealistiche e/o di una definizione grossolana oppure troppo esigente dei requisiti del prodotto. È chiaro che in questo caso a farne le spese dovrà essere necessariamente almeno uno dei tre pilastri classici:
-
Sacrificare l'obiettivo: significa che, per salvare costi e scadenze, è possibile fare una scrematura dei requisiti e arrivare in tempo e in budget con un prodotto meno ricco di funzionalità.
-
Sacrificare le scadenze: in questo caso semplicemente si accetta di consegnare in ritardo. L'arte di prendere tempo è una disciplina tutta da imparare, quando si sceglie questa via.
-
Sacrificare i costi: qui bisogna decidere se a farne le spese è il cliente o il fornitore. A prescindere, il punto è che in questo caso pur di non arrivare in ritardo si accetta di impiegare una quantità di risorse maggiore del previsto.
Per esperienza, il sacrificio dei costi è l'opzione meno desiderabile, anche se spesso è quello preferito dai piani alti dell'azienda, per evitare brutte figure, penali e altri tipi di problemi generalmente legati ai vincoli contrattuali della fornitura. Il punto è che sacrificare i costi espandendo il team si rivela spessissimo (ci sono studi che provano questo fenomeno) una strategia controproducente; l'unica opzione rimanente è il cosiddetto crunching, ossia spremere la squadra di sviluppo, facendo fare straordinari e sacrificando pause, ferie e finesettimana, tutto pur di salvare obiettivo e scadenze.
Il risultato di questa pratica è molto spesso quello di sacrificare uno dei pilastri del project management agile: la qualità.
Gli ostacoli agili: direzione ed esecuzione
Quando è scoppiato il caso Cyberpunk 2077, tutti i project manager del mondo sono andati a riprendere i loro libri di testo e ci hanno trovato esattamente le raccomandazioni su come non gestire un progetto. In giro troverete tantissime analisi su ciò che non ha funzionato nella realizzazione di questo videogioco.
I manager sono quei personaggi lavorativi convinti che un team di 9 donne possa produrre un neonato in un mese.
La progettazione con metodologia agile riconosce i pilastri della progettazione classica, ma in aggiunta prende a cuore due elementi fondamentali per la realizzazione di un buon prodotto: valore e qualità. Gli ostacoli agili mettono a repentaglio questi due pilastri, oppure gli altri tre (i vincoli) nell'insieme:
-
Il prodotto che è stato pensato non dà realmente valore al cliente.
-
Il modo in cui il progetto è stato pianificato e viene coordinato mette a repentaglio la qualità del prodotto.
-
Chi realizza il prodotto non ha ben chiara l'esigenza del cliente.
-
Il codice è scritto in modo frettoloso, grossolano, incoerente, ecc.
Anche in questo caso, bisognerà rendere sacrificabile almeno un pilastro su tre:
-
Sacrificare i vincoli: di fatto qui rientriamo nella casistica precedente, ma preserviamo il valore e la qualità del prodotto.
-
Sacrificare il valore: questa opzione può avere senso nel momento in cui ci si rivolge ad un mercato e non ad uno specifico committente. In tal caso stiamo semplicemente accettando di commercializzare un prodotto che può essere venduto ad un prezzo inferiore rispetto a prodotti analoghi. In ogni caso, consegneremo in tempo e in budget e realizzeremo comunque un prodotto di qualità, ma dovremo rivedere i margini di profitto.
-
Sacrificare la qualità: significa consegnare un prodotto che appare pienamente conforme a tutte le aspettative, ma che inevitabilmente creerà fastidi e insoddisfazioni al cliente e anche a chi dovrà fare manutenzione o fornire supporto. Generalmente sacrificare la qualità è quello che si fa quando si cerca di salvare tutti e tre i vincoli.
Gli ostacoli di sviluppo
Su questo fronte abbiamo solo un consiglio da dare: qualsiasi sia il tuo linguaggio di programmazione, il tuo stile, la tua architettura, il tuo framework di riferimento, non puoi non leggere (o alternativamente fruire di contenuti multimediali) qualcosa di approfondito sulle tematiche del refactoring, del clean code, dei code smells, eccetera. C'è tanta letteratura autorevole su questi argomenti.
La stessa Wikipedia cita diversi esempi di puzza che può provenire dai sorgenti di un progetto. Io qui mi limito a condensarli in alcune macro-categorie:
-
Calderoni: classi, funzioni o moduli pieni di funzionalità eterogenee non ben delineate e tutte collegate tra loro in modo caotico e imprevedibile. In questa categoria rientrano anche funzioni con più di 3 o 4 parametri e classi con più di 10 proprietà o metodi. Questo di solito deriva da una continua espansione di ciò che un componente deve fare, oppure da una scarsa chiarezza di cosa fa cosa all'interno del programma.
-
Ripetizioni: codice copia-incollato, magari riadattato appena appena. Questo denota scarsa capacità di astrazione o scarsa attitudine a costruire componenti riutilizzabili. In altre parole rivela una propensione del programmatore a lavorare molto con i diti e poco con la testa.
-
Ermetismo: non è una prerogativa ungarettiana, il codice ne è pieno. Nomi di variabili o funzioni troppo abbreviati, termini molto simili che non chiariscono la differenza tra due elementi, variabili che nascono per fare una cosa e poi ne fanno altre ma mantengono un nome inconsistente. Questa è un'abitudine che ci arriva dal mondo accademico: generalmente quando siamo principianti siamo abituati a chiamare le variabili a, b, c…; poi i progetti diventano complessi, ma le variabili rimangono a, b, c….
-
Cablaggi: in questa categoria (in inglese hardcoding) metto tutto ciò che rappresenta la compresenza di diversi livelli di astrazione: è il caso di parametri di configurazione (di solito stringhe di percorsi o indirizzi) "schiantati" nel codice, ma anche di complesse espressioni di basso livello (calcoli matematici, lunghi switch statements, cicli…) collocate in metodi o funzioni di alto livello, che dovrebbero descrivere un comportamento e non un'implementazione. Dal mio punto di vista, questo "odore" denota in qualche caso fretta, ma per lo più inesperienza. Il vantaggio di nascondere sotto un nome altamente descrittivo un'espressione poco leggibile è una cosa che si impara nel tempo. Generalmente, questa "puzza" è accompagnata anche dalla presenza di lunghi commenti esplicativi.
-
Incoerenza: nello stile o nei contenuti, l'incoerenza è un problema. Quella di stile rende meno leggibile il codice; sto parlando di norme di indentazione, della nomenclatura delle variabili, della spaziatura delle parentesi, eccetera. Quella di contenuto è anche peggiore, perché rende inconsistente il comportamento del software. In genere la prima è precursora* della seconda, quindi meglio fare attenzione a entrambe.
Ho cercato il femminile di precursore sul dizionario. Qualcuno ammette precursora, l'alternativa è precorritrice, che però francamente mi suona orrendo.
Sebbene questa categoria di ostacoli possa sembrare evitabile, possiamo garantire che, in una certa misura, è sostanzialmente impossibile scrivere del codice che sia esente da alcuno di questi vizi. Il punto è sempre: riconoscere, gestire e, se possibile, ridurre ai minimi termini.
Gestione del rischio 101
Il rischio è quasi sempre determinato dalla mancanza di informazioni, o dalla mancanza di controllo. Molto spesso, le informazioni mancanti saranno disponibili in futuro; possiamo quindi fare qualche riflessione su come mitigare i rischi derivanti dal presentarsi di uno o più ostacoli. Questo è il momento in cui l'ostacolo smette di essere un problema e inizia ad indicarci la via. Riguardo al controllo, in molti casi possiamo accontentarci di avere influenza sulle cose.
Slatentizzare i pericoli (affrontare le conversazioni spiacevoli)
La regola delle regole è che quando siamo testimoni di un problema, oppure se avvertiamo il rischio che insorga un problema, dobbiamo segnalarlo. Nella migliore delle ipotesi, il problema è già noto/gestito. Il peggior scenario non è quello in cui il problema sia concreto, ma quello in cui siamo gli unici ad avvertirlo. In questo caso, mettiamo a verbale la nostra segnalazione e cerchiamo (per quanto possibile) di prepararci all'eventualità che l'ostacolo si riveli concreto ed effettivamente problematico.
Nota fondamentale sui fischiettisti (traduzione libera di whistleblower, dall'inglese soffiatore di fischietto): puntare il dito verso un ostacolo serve solo nella misura in cui ci si prepara a superare tale ostacolo. Lo scopo di questa cosa non è scaricare barili o attendere di poter pronunciare la frase più inutile di tutte le frasi conosciute all'uomo: "io l'avevo detto".
Nota fondamentale sui terroristi: no, aumentare artificiosamente la portata percepita o persino reale di un problema non è il modo giusto per incentivarne la risoluzione. Può darsi che la nostra sensibilità rispetto al problema sia effettivamente eccessiva: se siamo in buona fede, dobbiamo sforzarci di sperare che sia così. Ben diverso è il discorso di anticipare i possibili problemi, in modo che questi vengano preventivamente affrontati. Questo significa avere dei piani d'azione da attivare al presentarsi di alcune problematiche eventuali, ma non significa che tutti i possibili problemi debbano essere risolti prima che inizi il progetto. Questo, nella realtà, solitamente non accade.
Posticipare le decisioni vincolanti
Questo consiglio può suonare un po' controintuitivo rispetto al precedente: dobbiamo anticipare le grane o posticiparle? Bisogna fare distinzione tra evento ed eventualità. Ciò che accade va affrontato; ciò che potrebbe accadere, richiede solo la nostra preparazione. Parlando di decisioni vincolanti, è meglio ragionare così: se una decisione rappresenta un punto di non ritorno, è meglio affrontarla nel modo più pigro possibile. Possiamo prepararci con largo anticipo al momento in cui la prenderemo, raccogliendo tutte le informazioni possibili, ma dobbiamo accettare che nuove consapevolezze emergeranno nel corso del progetto, prima che arrivi il momento in cui la decisione non è più rimandabile.
Influenzare ciò che non si può controllare
Possiamo pensare al rischio in termini di gradi di libertà: immaginando un progetto come un'equazione matematica, il rischio è rappresentato da tutte le variabili che restano indipendenti man mano che svolgiamo le nostre semplificazioni. Una volta che abbiamo ben chiari quali sono le variabili che resteranno libere, possiamo in ogni caso tentare di individuare un campo circoscritto in cui queste variabili oscilleranno. Per fare qualche esempio concreto:
-
è vero che non possiamo obbligare il committente a fornirci i loghi aziendali da inserire nel sito, ma possiamo concordarne preventivamente le dimensioni.
-
è vero che non possiamo immaginare che cosa l'utente si inventerà di inserire nei form, ma possiamo stabilire dei criteri di validazione a monte.
-
è vero che non possiamo essere sicuri che il software sarà esente da bachi, ma possiamo prevedere sistemi di logging efficaci e concordare delle strategie di error handling.
Un grazie speciale alle emozioni negative
Concludiamo con una riflessione sul piano generalmente più trascurato a livello professionale: quello psicologico. Piano piano l'umanità si sta accorgendo che la salute mentale e l'educazione emotiva sono parte integrante non solo della felicità individuale delle persone, ma anche della loro crescita professionale e capacità produttiva.
Non prendeteci per psicologi, ma per quello che stiamo cercando di esprimere, consideriamo fondamentalmente quattro tipi di emozioni:
-
Quelle "tutto bene": gioia, spensieratezza, estasi, felicità, fiducia, etc…
-
Quelle "ancora ancora": entusiasmo, eccitazione, desiderio, speranza, etc…
-
Quelle "così non va": rabbia, ansia, paura, riscatto, noia, etc…
-
Quelle "tutto male": tristezza, depressione, panico, frustrazione, disperazione, etc…
Sostanzialmente, possiamo raggrupparle a due a due tra quelle positive/negative oppure attivanti/deattivanti. La nostra capacità di mantenerci motivati (o di motivare gli altri) coincide con la capacità di nutrire e stimolare, nel bene (se possibile) o nel male (se necessario), le emozioni attivanti. Rispetto al rilevare ostacoli, dobbiamo un grazie speciale alle nostre emozioni negative, che ci dicono esattamente cosa non sta funzionando o cosa potrebbe non funzionare. Una nota rispetto alle emozioni negative deattivanti: quelle sono lì per dirci che non pensiamo di poter cambiare qualcosa che andrebbe cambiato; probabilmente questo implica che non abbiamo il controllo su quella cosa, oppure che da soli non ce la faremmo. Generalmente, quello è il segnale che dovremmo chiedere aiuto, oppure metterci l'anima in pace.
Insomma, il più delle volte sono le nostre emozioni a pesare le informazioni che vagliamo razionalmente. Imparando ad ascoltare le reazioni emotive, nostre e dei nostri colleghi o persino dei nostri committenti, avremo un ricco campione di informazioni su ciò che c'è da aspettarsi riguardo ad un progetto.
Dopodiché non siamo costretti ad impersonare le nostre emozioni, soprattutto quando si presentano in maniera perentoria e socialmente inaccettabile; invece, possiamo sempre essere i loro lucidi portavoce… magari dopo una telefonata di sfogo.