Programmazione funzionale vs programmazione orientata agli oggetti [chiuso]


784

Finora sono stato principalmente esposto alla programmazione OO e non vedo l'ora di imparare un linguaggio funzionale. Le mie domande sono:

  • Quando scegli la programmazione funzionale piuttosto che orientata agli oggetti?
  • Quali sono le definizioni tipiche dei problemi in cui la programmazione funzionale è una scelta migliore?



1
domanda simile cs.se ha anche chiuso l'esempio in cui la programmazione funzionale fornisce risultati migliori dello stile imperativo . la saggezza convenzionale sembra essere che l'uno non sia superiore all'altro, o che non siano comparabili su criteri semplici, o che siano utilizzati per scopi diversi ... la programmazione funzionale ha più origini e usi scientifici / accademici ed è meno comune nell'industria , quindi la domanda crea anche un pov / conflitto irrisolvibile "industria vs mondo accademico". un riferimento classico che mostra il programma OOP nella programmazione funzionale, libro SICP / MIT
vzn

" OO rende comprensibile il codice incapsulando le parti in movimento. FP rende il codice comprensibile minimizzando le parti in movimento. " --Micheal Feathers, 2010
jaco0646

Risposte:


1193

Quando scegli la programmazione funzionale piuttosto che orientata agli oggetti?

Quando prevedi un diverso tipo di evoluzione del software:

  • I linguaggi orientati agli oggetti sono utili quando hai un set fisso di operazioni sulle cose e man mano che il tuo codice si evolve, aggiungi principalmente nuove cose. Ciò può essere ottenuto aggiungendo nuove classi che implementano metodi esistenti e le classi esistenti vengono lasciate sole.

  • I linguaggi funzionali sono buoni quando hai un set fisso di cose e man mano che il tuo codice si evolve, aggiungi principalmente nuove operazioni su cose esistenti. Ciò può essere ottenuto aggiungendo nuove funzioni che calcolano con tipi di dati esistenti e le funzioni esistenti vengono lasciate sole.

Quando l'evoluzione va nella direzione sbagliata, hai problemi:

  • L'aggiunta di una nuova operazione a un programma orientato agli oggetti potrebbe richiedere la modifica di molte definizioni di classe per aggiungere un nuovo metodo.

  • L'aggiunta di un nuovo tipo di cose a un programma funzionale potrebbe richiedere la modifica di molte definizioni di funzioni per aggiungere un nuovo caso.

Questo problema è noto da molti anni; nel 1998, Phil Wadler lo ha definito il "problema dell'espressione" . Sebbene alcuni ricercatori ritengano che il problema dell'espressione possa essere affrontato con funzionalità linguistiche come i mixin, una soluzione ampiamente accettata deve ancora raggiungere il mainstream.

Quali sono le definizioni tipiche dei problemi in cui la programmazione funzionale è una scelta migliore?

I linguaggi funzionali eccellono nel manipolare i dati simbolici in forma di albero. Un esempio preferito sono i compilatori, in cui le lingue di origine e intermedie cambiano di rado (principalmente le stesse cose ), ma gli autori di compilatori aggiungono sempre nuove traduzioni e miglioramenti o ottimizzazioni del codice (nuove operazioni sulle cose). Compilazione e traduzione più in generale sono "app killer" per linguaggi funzionali.


119
C'è uno zen serio dietro questa risposta. Penso che chiarisca il fatto che alcuni modelli di progettazione OOP (Visitatore) sono in realtà hack che tentano di superare il problema dell'aggiunta di nuove operazioni.
Jacobs Data Solutions,

54
In JavaScript, puoi avere tutte le cose.
Erik Reppen,

61
@ErikReppen a che punto sorge la domanda, quando scegli di utilizzare le funzionalità funzionali e quando scegli di utilizzare le funzionalità orientate agli oggetti?
Norman Ramsey,

7
@NormanRamsey Non è affatto insolito mescolarlo in JS e le funzioni di prima classe sono legate a molte funzionalità relative a JS OOP. L'ordinamento di array di JS assume funzioni come arg che possono produrre alcune potenti strutture di dati. Chiusure + una funzione passata viene utilizzata per mantenere gli oggetti jquery molto leggeri in termini di memoria poiché la maggior parte dei metodi sono solo riferimenti. Ecc ...
Erik Reppen il

9
@NormanRamsey: un'ottima risposta, sulla falsariga di SICP. Secondo questa classificazione, la programmazione funzionale e procedurale sono raggruppate sul lato opposto della programmazione orientata agli oggetti. Questo potrebbe spiegare il boom di OOP alla fine degli anni '80 all'inizio degli anni '90: quando le GUI divennero mainstream, OOP si dimostrò un buon approccio per modellarle perché normalmente si ha un insieme fisso di operazioni (dipingere, aprire, chiudere, ridimensionare) e un numero crescente di widget. Ovviamente, ciò non significa che OOP sia meglio di procedurale per qualsiasi applicazione, come hai illustrato.
Giorgio,

177

Non devi necessariamente scegliere tra i due paradigmi. È possibile scrivere software con un'architettura OO utilizzando molti concetti funzionali. FP e OOP sono di natura ortogonale .

Prendiamo ad esempio C #. Si potrebbe dire che è principalmente OOP, ma ci sono molti concetti e costrutti FP. Se consideri Linq , i costrutti più importanti che consentono a Linq di esistere sono di natura funzionale: espressioni lambda .

Un altro esempio, F #. Si potrebbe dire che è principalmente FP, ma ci sono molti concetti e costrutti OOP disponibili. Puoi definire classi, classi astratte, interfacce, gestire l'ereditarietà. Puoi persino usare la mutabilità quando rende il codice più chiaro o quando aumenta notevolmente le prestazioni.

Molte lingue moderne sono multi-paradigma.

Letture consigliate

Dato che sono nella stessa barca (sfondo OOP, apprendimento FP), ti suggerirei alcune letture che ho davvero apprezzato:


8
@duffymo: il tuo commento, per come lo metti, è per lo più inutile. Nessuno vuole un confronto tra lingue, macchine virtuali o piattaforme, grazie.
Bruno Reis,

6
@Bruno - una risposta a "potenza di .NET". Rilassare.
duffymo,

6
Divertente, non ti vedo mentre rimproveri Dykam per il suo inutile commento. Sei stato nominato moderatore mentre non stavo guardando? Nessuno è in fiamme qui tranne te. Lo dirò di nuovo: rilassati.
duffymo,

4
Heh, scusa se ho iniziato a prendere fuoco. Non intendevo dire che altre piattaforme sono meno potenti, solo che .NET non supporta solo OOP. Ad esempio, ha l'ottimizzazione delle chiamate di coda.
Dykam,

5
@nawfal, finché non puoi indicare alcune caratteristiche intrinseche nei due paradigmi e dire che sono incompatibili, sono ortogonali: questo è il cuore della discussione. FP è incompatibile con la programmazione imperativa per definizione, ma OOP non si limita alla programmazione imperativa. Il motivo per cui abbiamo parole diverse per questi concetti è che possiamo parlarne: quando li aggreghi insieme, ci costringi a trovare inutilmente nuove parole.
David

31

La programmazione orientata agli oggetti offre:

  1. Incapsulamento, a
    • controllare la mutazione dello stato interno
    • limitare l'accoppiamento alla rappresentazione interna
  2. Sottotipizzazione, che consente:
    • sostituzione di tipi compatibili (polimorfismo)
    • un mezzo grezzo per condividere l'implementazione tra le classi (ereditarietà dell'implementazione)

La programmazione funzionale, in Haskell o persino in Scala, può consentire la sostituzione attraverso un meccanismo più generale di classi di tipi. Lo stato interno mutevole è scoraggiato o proibito. L'incapsulamento della rappresentazione interna può anche essere raggiunto. Vedi Haskell vs OOP per un buon confronto.

L'affermazione di Norman secondo cui "L'aggiunta di un nuovo tipo di cose a un programma funzionale può richiedere la modifica di molte definizioni di funzioni per aggiungere un nuovo caso". dipende da quanto bene il codice funzionale ha impiegato classi di tipi. Se la corrispondenza dei modelli su un particolare tipo di dati astratti è diffusa in una base di codice, si risentirà effettivamente di questo problema, ma forse è un progetto scadente per cominciare.

EDITED Rimosso il riferimento alle conversioni implicite quando si discutono le classi di tipi. In Scala, le classi di tipi sono codificate con parametri impliciti, non conversioni, sebbene le conversioni implicite siano un altro modo per ottenere la sostituzione di tipi compatibili.


3
Le typeclass non sono un meccanismo per la conversione implicita in altri tipi. Sono una descrizione di un insieme di funzioni definite per un tipo in modo da fornire una forma di polimorfismo. La cosa più vicina all'OOP in stile Java sarebbero le interfacce, anche se i caratteri tipografici Haskell presentano alcune differenze importanti.
Zak,

25
  1. Se ti trovi in ​​un ambiente fortemente concorrenziale, è utile la pura programmazione funzionale. La mancanza di uno stato mutevole rende la concorrenza quasi banale. Vedi Erlang.

  2. In un linguaggio multiparadigm, potresti voler modellare alcune cose funzionalmente se l'esistenza di uno stato mutabile è un dettaglio di implementazione, e quindi FP è un buon modello per il dominio problematico. Ad esempio, vedi la comprensione delle liste in Python o std.range nel linguaggio di programmazione D. Questi sono ispirati dalla programmazione funzionale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.