Programmazione funzionale vs Programmazione ad Oggetti

Programmazione funzionale vs Programmazione ad Oggetti

La programmazione è un mix di creatività e logica, in cui gli sviluppatori modellano i propri stili di programmazione in base alle preferenze personali. Ciò spesso porta a dibattiti su due paradigmi di programmazione comuni: Programmazione funzionale vs Programmazione ad Oggetti (OOP). Quale è migliore? Quale si dovrebbe scegliere?

Ognuno ha i suoi punti di forza unici e la scelta tra programmazione funzionale e OOP dipende dal contesto. Questo articolo fornisce un confronto oggettivo, separando le opinioni dalla realtà. Cerchermo di passare con una migliore comprensione di entrambi gli approcci ed il lettore sarà più preparato a utilizzarli quando ne avrà l’occasione.

Di seguito l’elenco argomenti che tratteremo:

  • Panoramica della programmazione funzionale
  • Panoramica sulla programmazione orientata agli oggetti
  • Programmazione funzionale vs OOP: un confronto
  • Il futuro della programmazione funzionale e OOP
  • Conclusione


Panoramica della programmazione funzionale
La programmazione funzionale (FP) è uno degli approcci più antichi alla programmazione. Definisce un processo di creazione di software che si basa esclusivamente su funzioni pure.

Nella FP, gli sviluppatori compongono funzioni per creare nuove funzioni e scrivono applicazioni per evitare aspetti quali stato condiviso o dati modificabili. Per ottenere ciò, gli sviluppatori spesso usano FP in modo dichiarativo piuttosto che imperativo .

Cosa significa tutto questo?

Concetti chiave nella programmazione funzionale
Come suggerisce il nome, le funzioni sono cittadini di prima classe in FP. Ciò significa che possono essere trattate come qualsiasi altro valore, passate in giro come argomenti o restituite da altre funzioni. Una funzione che restituisce una funzione è chiamata funzione di ordine superiore . Queste funzioni di ordine superiore consentono di comporre nuove funzioni direttamente dagli argomenti.

L’immutabilità è la chiave per FP. Un valore immutabile è un valore primitivo, che non può cambiare. Valori come i numeri sono considerati immutabili. Non possiamo cambiare 42 in 14. Possiamo solo creare un nuovo numero con il valore 14 e assegnarlo alla variabile usata in precedenza. Ma rendere quel nuovo numero 14 non influisce sul numero 42 che abbiamo usato in precedenza.

Mentre questo tipo di trattamento del valore ha senso per primitive come i numeri, potrebbe sembrare strano per valori composti come oggetti o array. Tuttavia, i principi FP trattano tutti i valori come immutabili. L’unico modo per cambiare un valore è crearne uno nuovo, potenzialmente usandone uno vecchio come valore di base o copia.

L’uso di tipi di dati immutabili consente a FP di usare funzioni pure . Queste funzioni sono definite solo dai loro argomenti. Poiché gli argomenti non possono cambiare, è garantito che si comportino in modo prevedibile. Gli stessi argomenti danno gli stessi risultati. Altri approcci di programmazione non garantiscono questo comportamento prevedibile.

Casi d’uso per la programmazione funzionale
Sebbene in origine la programmazione funzionale fosse utilizzata principalmente in applicazioni scientifiche, è diventata sempre più comune in diversi campi.

Ad esempio, nello sviluppo web, la libreria dell’interfaccia utente (UI) di React utilizza i principi FP per diventare dichiarativa e facile da gestire. La libreria sostiene l’utilizzo di oggetti di stato immutabili (valori) per riflettere lo stato corrente dell’applicazione senza cambiare. Quando lo sviluppatore desidera un nuovo stato, deve creare un nuovo oggetto.

La bellezza di questo approccio è che puoi risalire a ogni modifica nell’interfaccia utente. Tutti gli stati precedenti sono ancora intatti e disponibili.

La programmazione funzionale ha avuto origine nell’ambiente accademico dell’informatica, con applicazioni pratiche in linguaggi come Lisp e Scheme. Alcune di queste caratteristiche sono state integrate nel linguaggio JavaScript, motivo per cui gli sviluppatori continuano a fare affidamento sulla FP.

Altri linguaggi si basano sui principi FP: F#, Clojure ed Elixir sono tra i più popolari. In ambito accademico, Haskell è considerato il linguaggio di riferimento da decenni.

Panoramica sulla programmazione orientata agli oggetti
La programmazione funzionale esiste da molto tempo, ma alcuni sviluppatori considerano la programmazione orientata agli oggetti (OOP) ancora più tradizionale. Linguaggi orientati agli oggetti come Smalltalk o Objective-C hanno reso popolare la OOP, inventata alla fine degli anni ’70. In seguito, C++, Java e C# hanno continuato a cablare questo stile di programmazione nelle menti della maggior parte degli sviluppatori.

Di seguito descriviamo i principi più importanti della OOP e di alcuni dei suoi casi d’uso più comuni.

Concetti chiave nella programmazione orientata agli oggetti
In OOP, gli sviluppatori modellano le applicazioni software come raccolte di oggetti che possono comunicare tra loro. L’interfaccia di ogni oggetto è una classe , un modello che indica che funzioni e valori sono accessibili a qualsiasi istanza.

Inizialmente, gli sviluppatori intendevano questa capacità di comunicazione per inviare messaggi per la comunicazione di rete o IO asincrono. In seguito è stata resa popolare come semplici funzioni invocate sull’oggetto corrispondente. Tali funzioni sono chiamate metodi .

Contrariamente agli oggetti immutabili in FP, in OOP la mutazione degli oggetti è parte del gioco. Quindi, chiamare un metodo molto probabilmente cambierà anche un valore dell’oggetto.

Una ragione per cui molti sviluppatori usano ancora la OOP, specialmente quando insegnano programmazione, è che è scritta in modo imperativo. Ciò significa che lo sviluppatore è esplicito su cosa sta succedendo e dove. Tuttavia, anche usando uno stile così imperativo, può essere difficile determinare lo stato attuale dei singoli oggetti. Mutabilità significa che questo può portare rapidamente a conseguenze impreviste.

Casi d’uso per la programmazione orientata agli oggetti
Tradizionalmente, gli sviluppatori hanno creato quasi tutte le interfacce utente con un approccio OOP. Ad esempio, un componente basato su classi può semplicemente ereditare la sua struttura di base (campi e metodi) da un altro componente simile. Ad esempio, un campo di input data può ereditare da un campo di input testo, che eredita da una casella di input, che eredita da un controllo.

Utilizzando questo approccio basato sull’ereditarietà, è sufficiente specificare i metodi aggiuntivi e reimplementare il comportamento su alcuni metodi esistenti. Non è necessario scrivere di nuovo la logica per la gestione della tastiera o del mouse, ad esempio.

Oggi, la OOP è una funzionalità imprescindibile in tutti i linguaggi di programmazione generici. Anche i linguaggi basati su FP come F# supportano direttamente le funzionalità OOP, come classi o ereditarietà. Un buon esempio è JavaScript, che non ha incorporato subito funzionalità standard come classi o ereditarietà, ma le ha aggiunte in revisioni più recenti.

Come abbiamo scoperto, i due approcci di programmazione sono abbastanza diversi da giustificare l’uso di entrambi, quando applicabile. Quindi, come si fa a scegliere tra loro? Diamo un’occhiata ad alcuni degli argomenti.

Programmazione funzionale vs Programmazione ad Oggetti: un confronto
Il professore di informatica Norman Ramsey ha offerto una prospettiva utile sul dibattito programmazione funzionale vs OOP in una nota risposta di Stack Overflow . Ha sostenuto che FP eccelle quando tutti gli oggetti sono noti ma hanno un comportamento che può cambiare. Al contrario, OOP è eccezionale quando i comportamenti sono noti, ma i tipi di dati effettivi possono cambiare.

I fan di entrambe le parti andranno oltre. Ad esempio, i seguaci di FP sostengono che un software progettato in modo pulito e scritto in puro stile FP è facile da debuggare e non si bloccherà mai. Si dirà che FP dà subito alcuni dei vantaggi dello sviluppo basato sui test e che OOP con tutti i principi SOLID applicati rigorosamente è essenzialmente FP.

Sebbene sia vero che SOLID porta a funzioni individuali che assomigliano alla maggior parte di FP, non deve necessariamente essere FP. Ad esempio, nessun principio SOLID proibisce la mutazione dei dati.

Gli sviluppatori che amano la OOP potrebbero ignorare alcuni dei vantaggi della FP per compromessi come prestazioni o semplicità. Perché copiare tutti i campi di un oggetto in un nuovo oggetto quando si desidera modificare solo un singolo campo? Perché un array con un milione di elementi dovrebbe richiedere una copia per impostare un singolo elemento? Il livello di indirezione può essere sconcertante rispetto all’approccio diretto che gli sviluppatori hanno utilizzato indipendentemente dalla OOP.

Sebbene vi siano alcuni contrasti piuttosto netti tra questi approcci, possono anche essere complementari. Non esiste una legge che proibisca l’uso di classi in un’applicazione software. Non esiste nemmeno una legge che dica che lo stato generale dell’applicazione debba essere mutabile.

Il futuro della programmazione funzionale ed OOP
Quasi tutti i linguaggi di programmazione più diffusi sono multiparadigma . Tutti supportano FP consentendo il passaggio di funzioni o l’utilizzo di helper che gestiscono l’immutabilità degli oggetti dati. Sono inoltre dotati di funzionalità OOP, come classi o ereditarietà.

In ogni caso, questo approccio multiparadigma è qui per restare. Dal punto di vista di un utente, è quasi sempre meglio avere più scelte.

In generale, sembra probabile una tendenza verso funzionalità più FP-friendly. Introducendo un supporto aggiuntivo per la clonazione di oggetti dati, riferimenti di funzioni e composizioni di funzioni, un linguaggio diventa un ottimo compagno, anche oltre FP. In linguaggi come C#, le funzionalità FP-friendly forniscono un’eccellente aggiunta alle funzionalità OOP. Questa combinazione risulta utile anche nelle applicazioni sviluppate OOP, come quando si utilizzano determinate funzioni di supporto.

Lo svantaggio di mescolare approcci FP e OOP è la curva di apprendimento. Alcune persone evitano C# per questo motivo. Ciò che è iniziato come un’alternativa incontaminata ed elegantemente progettata a Java può finire per sembrare più un mostro complesso lungo le linee di C++.

La OOP non scomparirà, ma potrebbe invece ritrovarsi a coesistere con la FP. L’ideale di uno sviluppo privo di effetti collaterali è quasi impossibile da implementare nella pratica. Anche scrivere messaggi di log su una console crea un effetto collaterale.

Gli sviluppatori hanno dovuto prima scoprire e sbloccare il lato pratico di FP. Ora che gli sviluppatori hanno iniziato a riconoscere il lato pratico di FP, non c’è quasi più motivo di escludere di nuovo le funzionalità di FP.

Supporto continuo per la programmazione orientata agli oggetti
In questo contesto, perché la OOP dovrebbe essere ancora una scelta praticabile? La OOP ha valore perché è essenzialmente lo strumento ideale. Non c’è quasi nulla che gli sviluppatori non possano modellare tramite pratiche OOP. Gli sviluppatori possono persino modellare la maggior parte delle funzionalità FP tramite OOP.

Ad esempio, consideriamo qualcosa di elementare come il passaggio o la combinazione di funzioni. In poche parole, questo è ciò che fornisce un functor o un delegate . È solo un oggetto corrispondente a una classe con un singolo metodo.

Trovare un terreno comune
Pochissimi team di sviluppo cambieranno il loro software o il loro modo di scrivere applicazioni solo per passare da un approccio all’altro. È più probabile che un team esegua attivamente il refactoring di alcune delle sue applicazioni più essenziali per utilizzare le funzionalità più recenti dei loro linguaggi di programmazione.

In entrambi i casi, il futuro sembra sempre più ibrido. In qualche progetto futuro, probabilmente ci ritroveremo ad usare uno stile più ispirato a FP in applicazioni OOP o alcune funzionalità OOP in applicazioni basate su FP.

Conclusione Programmazione funzionale vs Programmazione ad Oggetti
Quando si tratta del dibattito tra programmazione funzionale e OOP, la realtà è che nessuno dei due approcci è intrinsecamente superiore.

FP viene spesso scelto per la sua semplicità e le eccellenti prestazioni in scenari che richiedono alti livelli di concorrenza o quando è necessaria una forte enfasi sul calcolo stateless. OOP, d’altro canto, è preferito quando il dominio del problema è meglio modellato con strutture dati ricche e comportamenti complessi, o quando l’infrastruttura e le competenze esistenti supportano un approccio orientato agli oggetti.

Entrambi i paradigmi hanno dei vantaggi, quindi comprenderli è fondamentale per fare scelte consapevoli in linea con gli obiettivi del progetto. Bilanciare le preferenze personali con i requisiti del progetto ti guiderà verso la scelta giusta per te e il tuo team.

Consigliamo anche di leggere l’articolo Programmazione procedurale vs ad oggetti.

(fonte)

Innovaformazione, scuola informatica specialistica promuove la cultura della formazione continua per gli sviluppatori delle aziende informatiche. Un esempio di linguaggio funzionale è Elixir e trovate il corrispondente Corso Elixir programmazione (solo per aziende).

INFO: info@innovaformazione.net – tel. 3471012275 (Dario Carrassi)

Ti potrebbe interessare

Articoli correlati