Il post sul blog che hai citato sopravvaluta un po 'la sua affermazione. FP non elimina la necessità di modelli di progettazione. Il termine "modelli di progettazione" non è ampiamente utilizzato per descrivere la stessa cosa nei linguaggi FP. Ma esistono. I linguaggi funzionali hanno molte regole di buone pratiche del modulo "quando incontri il problema X, usa un codice che assomiglia a Y", che è fondamentalmente quello che è un modello di progettazione.
Tuttavia, è corretto che la maggior parte dei modelli di progettazione specifici di OOP siano praticamente irrilevanti nei linguaggi funzionali.
Non penso che dovrebbe essere particolarmente controverso affermare che i modelli di progettazione in generale esistono solo per rimediare alle carenze del linguaggio. E se un'altra lingua può risolvere lo stesso problema in modo banale, quell'altra lingua non avrà bisogno di un modello di progettazione per questo. Gli utenti di quella lingua potrebbero non essere nemmeno consapevoli che il problema esiste , perché, beh, non è un problema in quella lingua.
Ecco cosa ha da dire la banda di quattro su questo problema:
La scelta del linguaggio di programmazione è importante perché influenza il proprio punto di vista. I nostri modelli assumono funzionalità linguistiche di livello Smalltalk / C ++ e tale scelta determina cosa può e non può essere implementato facilmente. Se avessimo assunto linguaggi procedurali, avremmo potuto includere modelli di progettazione chiamati "Ereditarietà", "Incapsulamento" e "Polimorfismo". Allo stesso modo, alcuni dei nostri modelli sono supportati direttamente dai linguaggi orientati agli oggetti meno comuni. CLOS ha diversi metodi, ad esempio, che riducono la necessità di un modello come Visitatore. In effetti, ci sono abbastanza differenze tra Smalltalk e C ++ per indicare che alcuni schemi possono essere espressi più facilmente in una lingua rispetto all'altra. (Vedi Iterator per esempio.)
(Quanto sopra è una citazione dall'Introduzione al libro Patterns Design, pagina 4, paragrafo 3)
Le caratteristiche principali della programmazione funzionale includono funzioni come valori di prima classe, curry, valori immutabili, ecc. Non mi sembra ovvio che i modelli di progettazione OO stiano approssimando una di queste caratteristiche.
Qual è il modello di comando, se non un'approssimazione di funzioni di prima classe? :) In un linguaggio FP, passeresti semplicemente una funzione come argomento a un'altra funzione. In un linguaggio OOP, devi racchiudere la funzione in una classe, che puoi creare un'istanza e quindi passare quell'oggetto all'altra funzione. L'effetto è lo stesso, ma in OOP si chiama modello di progettazione e richiede molto più codice. E qual è il modello astratto di fabbrica, se non il curry? Passa i parametri a una funzione un po 'alla volta, per configurare il tipo di valore che sputa quando finalmente la chiami.
Quindi sì, molti modelli di progettazione GoF sono resi ridondanti nei linguaggi FP, perché esistono alternative più potenti e più facili da usare.
Ma ovviamente ci sono ancora modelli di progettazione che non sono risolti dai linguaggi FP. Qual è l'equivalente in FP di un singleton? (Trascurando per un momento che i singoli sono generalmente un modello terribile da usare.)
E funziona anche in entrambi i modi. Come ho detto, FP ha anche i suoi schemi di progettazione; la gente di solito non la pensa come tale.
Ma potresti esserti imbattuto in monadi. Cosa sono, se non un modello di progettazione per "trattare con lo stato globale"? Questo è un problema così semplice nei linguaggi OOP che non esiste un modello di progettazione equivalente.
Non abbiamo bisogno di un modello di progettazione per "incrementare una variabile statica" o "leggere da quel socket", perché è proprio quello che fai .
Dire che una monade è uno schema di progettazione è assurdo come dire gli Integer con le loro solite operazioni e l'elemento zero è uno schema di progettazione. No, una monade è un modello matematico , non un modello di progettazione.
In linguaggi (puri) funzionali, gli effetti collaterali e lo stato mutevole sono impossibili, a meno che non ci si aggiri con il "modello di progettazione" della monade o con uno qualsiasi degli altri metodi per consentire la stessa cosa.
Inoltre, nei linguaggi funzionali che supportano OOP (come F # e OCaml), mi sembra ovvio che i programmatori che usano questi linguaggi utilizzino gli stessi schemi di progettazione disponibili per tutti gli altri linguaggi OOP. In effetti, in questo momento uso F # e OCaml ogni giorno, e non ci sono differenze sorprendenti tra i pattern che uso in questi linguaggi rispetto ai pattern che uso quando scrivo in Java.
Forse perché stai ancora pensando imperativamente? Molte persone, dopo aver affrontato le lingue imperative per tutta la vita, hanno difficoltà a rinunciare a quell'abitudine quando provano un linguaggio funzionale. (Ho visto alcuni tentativi piuttosto divertenti in F #, dove letteralmente ogni funzione era solo una serie di istruzioni 'let', praticamente come se avessi preso un programma C e sostituito tutti i punti e virgola con 'let'. :))
Ma un'altra possibilità potrebbe essere che non ti sei reso conto che stai risolvendo banalmente problemi che richiederebbero schemi di progettazione in un linguaggio OOP.
Quando usi il curry o passi una funzione come argomento a un'altra, fermati e pensa a come lo faresti in una lingua OOP.
C'è qualche verità nell'affermazione che la programmazione funzionale elimina la necessità di modelli di progettazione OOP?
Sì. :) Quando lavori in un linguaggio FP, non hai più bisogno dei modelli di progettazione specifici di OOP. Ma hai ancora bisogno di alcuni schemi di progettazione generali, come MVC o altri elementi non OOP specifici, e invece hai bisogno di un paio di nuovi "schemi di progettazione" specifici per FP. Tutte le lingue hanno i loro difetti e i modelli di progettazione sono di solito il modo in cui lavoriamo intorno a loro.
Ad ogni modo, potresti trovare interessante cimentarti in linguaggi FP "più puliti", come ML (il mio preferito, almeno a fini di apprendimento) o Haskell , dove non hai la stampella OOP su cui ripiegarti quando hai di fronte qualcosa di nuovo.
Come previsto, alcune persone hanno obiettato alla mia definizione di modelli di design come "correggendo le carenze in una lingua", quindi ecco la mia giustificazione:
Come già detto, la maggior parte dei modelli di progettazione sono specifici di un paradigma di programmazione, o talvolta anche di un linguaggio specifico. Spesso risolvono problemi che esistono solo in quel paradigma (vedi monadi per FP o fabbriche astratte per OOP).
Perché il modello astratto di fabbrica non esiste in FP? Perché il problema che tenta di risolvere non esiste qui.
Quindi, se esiste un problema nelle lingue OOP, che non esiste nelle lingue FP, è evidente che si tratta di un difetto delle lingue OOP. Il problema può essere risolto, ma la tua lingua non lo fa, ma richiede un sacco di codice boilerplate per aggirare il problema. Idealmente, vorremmo che il nostro linguaggio di programmazione magicamente facesse scomparire tutti i problemi. Qualunque problema ancora presente è in linea di principio un difetto della lingua. ;)