Sei interessato ai nostri servizi di consulenza?

1 Clicca nella sezione contatti
2 Compila il form
3 Ti ricontattiamo

Se hai bisogno urgente del nostro intervento puoi contattarci al numero 370 148 9430

RENOR & Partners

I nostri orari
Lun-Ven 9:00AM - 18:PM

Programmazione: da procedurale verso l’OOP

by Simone Renzi / Agosto 18, 2022
Post Image

Ci sono molte persone a cui piacerebbe imparare a programmare per il Web ma non sanno da dove partire. Alcuni si affidano ai libri, altri a corsi online ma quello che mi capita di sentire è sempre la stessa frase: “ho iniziato a studiare un linguaggio di Backend su un corso online ma la programmazione a oggetti è troppo difficile”.

Effettivamente, quasi tutti i libri di testo che ho letto nella vita sul paradigma OOP complicano un concetto che io definirei come la naturale evoluzione della programmazione procedurale e funzionale.

Perché renderla complicata?

Perché a mio avviso, tutti i libri e tutti i corsi vogliono per forza portare degli esempi paragonando la programmazione a oggetti alla vita reale. In realtà, chi ha imparato a programmare in modo procedurale, fino a quel momento ha visto unicamente esempi nel mondo dello sviluppo: cos’è una variabile, cos’è un array, come si cicla un array, come scrivere una condizione, come fare un diagramma di flusso, come scrivere una funzione; pertanto non ritengo siano abituati a cogliere degli esempi nel mondo reale in questa fase, ma dopo aver compreso cosa implica il paradigma a oggetti in ambito informatico. È un metodo di pensare al codice che diviene quasi necessario quando si passa dal piccolo progetto ad un progetto più grande o che dovrà essere manutenuto ed esteso nel futuro. Solo quando si avranno chiare queste basi, sarà possibile portare degli esempi nella vita reale.

Complicare scoraggia

Complicando in questo modo le cose i nuovi “adepti” del mondo della programmazione si scoraggiano. Il risultato è che alcuni di loro abbandonano l’interesse per la programmazione, altri restano fermi alla programmazione procedurale o funzionale senza sapere che da quella funzionale all’OOP il passo è veramente cortissimo.

Chi sviluppa progetti procedurali può creare grattacapi a chi dovrà rimettere mano sul codice

Il paradigma a oggetti non è solo un “diverso modo di organizzare il codice” ma fornisce delle regole e un modus operandi tale per cui chi dovrà mettere mano su codice sviluppato da qualcun altro lo potrà fare senza spaccarsi per troppo tempo la testa alla ricerca di “cosa fa cosa”.

Inoltre nella programmazione a oggetti non bisognerebbe mai sottovalutare la potenza dell’UML.

In sostanza la programmazione a oggetti fornisce tutte le best practice che un buon sviluppatore dovrebbe mettere in atto per rendere il codice facilmente leggibile, strutturato come si deve, facilmente manutenibile e scalabile.

Parlando di scalabilità

Non solo il paradigma ad oggetti incanala lo sviluppatore in un’ottica di sviluppo virtuosa, ma permette anche di usufruire di tutta una serie di strumenti già pronti e facilmente integrabili. Git Hub pullula di Classi già implementate e facilmente integrabili, per lo più tramite Composer, che danno modo di risparmiare tantissimo tempo in fase di sviluppo. Esistono classi praticamente per qualsiasi cosa: la generazione di un PDF, l’invio delle eMail, l’integrazione con le API di eBay e Amazon per l’automazione di progetti eCommerce, la generazione di QR Code e Bar Code, il confronto tra immagini, il ridimensionamento di immagini, la compressione, ecc. ecc.

Questi strumenti sono sempre scritti con paradigma orientato agli oggetti e per sfruttarli e, in taluni casi, riadattarli alle nostre necessità, è necessario conoscere questa filosofia di scrittura del codice.

Quando è difficile scalare?

Svariate volte mi è capitato di rimettere mano su progetti scritti in ottica procedurale… Ho dovuto perdere letteralmente giorni solo per capire in che modo fosse organizzato il codice, dovendo leggermi file di decine di migliaia di righe di codice. Diviene molto difficile modificare anche una banalissima funzione perché è necessario andare alla ricerca, nelle migliaia di righe, di quella porzione di codice che si occupa di mettere in atto quell’azione, stare lì ore a debuggare… Un inferno.

In progetti orientati agli oggetti la cosa sarebbe stata di una banalità disarmante!

Come funziona la programmazione a oggetti?

Sono minuti che giriamo intorno all’argomento ma ancora non ne abbiamo dato una definizione che sia facilmente comprensibile.

Per imparare a programmare a oggetti non c’è altra strada che imparare prima la programmazione procedurale, poi quella funzionale ed in fine quella ad oggetti, perché una è la naturale evoluzione dell’altra.
Programmare significa saper analizzare un grosso problema, scomporlo in problemi più piccoli e trovare delle soluzioni a ciascuno di questi piccoli problemi per poi ricomporne i pezzi e risolvere il problema principale. Per fare questo ci si avvale di funzioni.
Il passaggio dalla programmazione procedurale alla funzionale è abbastanza semplice: le funzioni sono dei raccoglitori di codice procedurale specializzate nella risoluzione di un piccolo problema. Es. scrivere un programma che si occupi di cercare una stringa all’interno di un’altra stringa; se la trova restituire esito positivo altrimenti negativo. Questo programma posso scriverlo all’interno di una funzione. Le funzioni nella programmazione sono esattamente come le funzioni matematiche: si passano una o più variabili in ingresso dopodiché la funzione le elabora e restituisce un risultato, o se vogliamo dirlo in un modo più correttamente matematico. Data una funzione per ogni elemento del dominio della funzione ne corrisponde uno nel codominio. Nella programmazione le funzioni hanno dei parametri di ingresso che vengono elaborati e viene restituito un valore di uscita.

In questo modo si risolve un piccolo problema derivato dal problema principale e posso continuare a risolvere piccoli problemi con altre funzioni per poi metterle assieme e risolvere il problema principale.

All’atto in cui ho finito di preparare tutte queste funzioni, posso valutare quali siano risolutive di una classe di problemi. Poniamo ad esempio di dover calcolare il totale di n fatture ancora non pagate di un’azienda e di dover successivamente inviare questo totale tramite mail al cliente che ce le deve pagare.

Primo problema: prendere tutti i dati da un database

Secondo problema: esaminare le fatture

Terzo problema: sommare le fatture non pagate

Quarto problema: inviare il totale tramite email al cliente per il pagamento

Come lo risolveremmo con la programmazione funzionale?

Primo problema:

  • scrivo una funzione che effettui la connessione al database
  • scrivo una funzione che faccia una query di SELECT nel database per recuperarne i dati
  • li inserisco in un array

Secondo problema:

  • scrivo una funzione che mi cicli l’array
  • scrivo una funzione che mi scarichi tutte le fatture
  • scrivo una funzione che inserisca le fatture non pagate in un altro array

Terzo problema:

  • scrivo una funzione che mi cicli l’array e mi sommi il totale delle fatture in una variabile di ritorno

Quarto problema:

  • scrivo una funzione che invii una mail al cliente passandogli il valore della variabile contenente il totale fattura
  • verifico il corretto invio della mail

Come è possibile vedere abbiamo risolto il problema principale “Calcolare il totale di n fatture ancora non pagate di un’azienda e inviare il totale tramite mail al cliente per il pagamento” utilizzando delle funzioni che risolvono delle sottocategorie del problema principale semplicemente mettendole assieme in modo ordinato.

Come portare tutto questo in un’ottica OOP?

Si devono scindere gli attori in gioco per comprendere a quali Classi di problemi questi appartengano… Ad esempio la Connessione al database è una Classe di problemi che differisce da quella delle fatture, pertanto fatture potrebbe essere un’altra classe di problemi, così come l’invio della Mail è ulteriormente un’altra Classe di problema rispetto alla connessione al database e all’invio delle Mail.

Abbiamo quindi identificato delle Classi che altro non sono che raccoglitori di funzioni, le quali, al loro interno, assumono il nome di “Metodi”.

Per questo problema avremo la Classe Connection per la connessione al database, la Classe Fatture per tutte le funzioni che soddisfano il requisito di risolvere i sottoproblemi relativi alle fatture e la Classe Mail che contiene i metodi relativi all’invio della posta elettronica. Ogni classe raccoglie i metodi (o se vogliamo ancora utilizzare il termine “funzioni”) relativi alla loro classe risolutiva di problemi.

L’oggetto che viene istanziato (creato) dalla Classe, altro non è che un contenitore dei metodi che implementa la Classe (e di proprietà che altro non sono che le variabili in gioco all’interno della Classe)  che possono essere utilizzati per risolvere il problema principale.

Naturalmente questo è uno degli approcci, ma ognuno potrebbe trarre le sue conclusioni sugli attori come meglio crede che sia giusto e non ci sarebbe una versione corretta e una errata. Ad esempio uno sviluppatore avrebbe potuto integrare i metodi per l’invio delle Mail all’interno della Classe delle fatture visto che si riferiscono all’invio di posta elettronica contenente dati di fatturazione. Sarebbe stato un ragionamento che io non condivido ma non scorretto.

Perché usando il paradigma ad oggetti il codice è più facilmente manutenibile?

Semplice! Perché se domani mi chiedessero di integrare anche la media del totale delle fatture, tutto quello che dovrò fare sarà aggiungere un metodo alla Classe Fatture che si occupi di calcolare il valore medio delle fatture di quel Cliente, senza dover stare a ricercare in un file unico la parte di codice che si occupa della fattura.

La cosa importante da fare quando si programma a oggetti è dunque quella di capire quali sono i problemi in gioco, strutturare un diagramma che si chiama UML e raccogliere dentro ogni classe tutti i metodi risolutivi dei microproblemi adibiti a quella Classe di problemi. Una volta che il discorso filerà liscio su carta si potrà iniziare a scrivere i commenti (una best practice che puoi leggere in questo articolo) e per ultimo stendere il codice. L’operazione diventerà veramente banale perché il grosso del lavoro è stato fatto prima con carta e penna.

Naturalmente questo non è un corso di programmazione OOP, le regole della programmazione a oggetti sono molte e vanno comprese integralmente: ereditarietà di una classe figlia, classi astratte, interfacce, traits, ecc., ma una volta entrati nell’ottica di “Cosa è una Classe” e “Perché passare alla programmazione a oggetti” si tratterà solo di studiare queste regole ed applicarle programmando e continuando a programmare sempre di più. Ti accorgerai, una volta compresa, della facilità concettuale e di come torni veramente utile per organizzare il codice secondo regole facilmente interpretabili anche da un’altra persona che dovrà rimettere mano al tuo codice.

Come hai visto la programmazione a oggetti è molto più semplice di quello che si dice, non è assolutamente un concetto astratto e terribile che crea blocchi a chi vuole imparare a programmare… Tutto sta a prenderla nel modo giusto senza stare lì a parlare di Case, Automobili e Moto (questo è l’esempio più citato), Palazzi, Ricette e chi più ne ha più ne metta.

 

Simone Renzi

Scegli un'area

CONTATTACI

Ti risponderemo entro 24 ore

TORNA SU
Avvia Chat
1
Hai bisogno di aiuto immediato?
Ciao
Come posso aiutarti?