Per un programmatore, possedere l’abilità del problem solving è fondamentale. Essa è una delle capacità più ricercate dai recruiter di questa professione. Non c’è nulla di più importante di saper riconoscere che c’è un problema, individuarlo e poi trovare la soluzione. Prima della capacità tecnica, occorre possedere prontezza mentale.
Alcuni di noi sono più portati a pensare in maniera “ottimizzata”, ma questo non significa che chiunque non si possa allenare a sviluppare il problem solving.
I 5 fondamenti del problem solving
Il problem solving può essere utilizzato per diversi scopi. Solitamente si deve pensare a un metodo, un algoritmo per ottimizzare un processo, oppure si è alla ricerca della causa di un bug complesso. Il primo, fondamentale requisito è ovviamente quello di capire il problema. Solo una volta che ci si è assicurati di aver compreso l’obiettivo e la situazione di partenza, si può procedere alla risoluzione.
1 – Divide et Impera
Il più importante insegnamento della programmazione. Affrontare un problema complesso nella sua interezza non porta quasi mai a buoni risultati: spesso, anzi, risulta impossibile da risolvere. Un bravo problem solver è in grado di individuare i sotto-problemi o step necessari per raggiungere l’obiettivo. Nel caso di un bug, ad esempio, è buona pratica isolare classi o parti di codice, e valutare un po’ alla volta la logica e l’evoluzione del bug, fino a risalire all’origine.
Da qui poi, nel caso di una risoluzione complessa, che richieda ad esempio un ripensamento della logica del programma, occorre procedere per step risolvendo un sotto-nucleo alla volta, aggiungendo man mano complessità alla soluzione per includere tutto. Lo stesso principio viene applicato al momento della progettazione di un software. Molto utile è stilare una lista di task o sub-goal ordinata, con la descrizione di ciò che serve per raggiungere il singolo obiettivo e le eventuali dipendenze temporali tra i task.
2 – Pensare in parallelo
Dopo aver valutato cosa bisogna fare e le dipendenze esistenti, occorre valutare se ci sono delle operazioni che possono essere eseguite in parallelo. Se due task sono indipendenti tra di loro, è conveniente portarli a termine contemporaneamente. Ottimizzazione significa anche riduzione dei tempi morti, che potranno essere riutilizzati per operazioni più impegnative. Una revisione della lista è a questo punto importante: riorganizzare i task in un diagramma potrebbe facilitare la comprensione sul da farsi.
3 – Astrarre
Quando ci si pone un problema, un errore commesso da molti è trovare una soluzione specifica per esso. Sarebbe conveniente, piuttosto, individuare una soluzione generica che possa adattarsi a tutti i problemi di quel tipo. Fondamentale è quindi cercare di categorizzare l’obiettivo e individuare la “famiglia” di problemi alla quale appartiene, così da trovare un algoritmo generale che possa essere riutilizzato al bisogno.
4 – Riutilizzare soluzioni precedenti
Questo punto è strettamente legato al precedente. Una volta che si è diviso il problema in sotto-problemi e si sono individuate le dipendenze corrette, la prima domanda da porsi è: “Esiste già una soluzione?”. Perché sprecare tempo ed energie se qualcuno ha già trovato la soluzione ai nostri problemi? Ovviamente è necessario, come detto prima, aver compreso bene lo scopo dei nostri sforzi, altrimenti si rischia di applicare la soluzione sbagliata. Non è detto però che si debba trovare l’intero procedimento. In tal caso, si procede nuovamente per sotto-task, cercando prima se qualcuno ha già risolto anche solo parte del nostro problema.
5 – Pensare in termini di data flow
Quest’ultimo concetto è in realtà necessario per poter padroneggiare gli altri. La singola informazione non vive solo nel punto in cui si è presentato il problema, ma ha una sorgente, una destinazione, e attraversa una serie di step e di trasformazioni. Se nel momento di individuare i singoli task non si pensa a questo, si circoscrive la soluzione ad una singola parte, col rischio di non trovare quella ottimale. Occorre sempre tenere a mente il percorso che ha fatto e che farà il dato nel punto in cui lo stiamo maneggiando, in modo da trovare il pezzo perfetto da incastrare in un puzzle più grande.
Visualizza altro – Il world wide web