[Design-Patterns] La programmazione funzionale sostituisce i modelli di progettazione GoF?


Answers

C'è qualche verità nell'affermazione che la programmazione funzionale elimina la necessità di schemi di progettazione OOP?

La programmazione funzionale non è la stessa della programmazione orientata agli oggetti. I modelli di progettazione orientati agli oggetti non si applicano alla programmazione funzionale. Invece, hai schemi di progettazione della programmazione funzionale.

Per la programmazione funzionale, non leggerete i libri di modelli di progettazione OO, leggerete altri libri su modelli di progettazione FP.

linguaggio agnostico

Non totalmente Solo linguaggio indipendente rispetto alle lingue OO. I modelli di progettazione non si applicano affatto ai linguaggi procedurali. Hanno appena senso in un contesto di progettazione di database relazionale. Non si applicano quando si progetta un foglio di calcolo.

un tipico schema di progettazione OOP e il suo equivalente funzionale?

Quanto sopra non dovrebbe esistere. È come chiedere un pezzo di codice procedurale riscritto come codice OO. Ummm ... Se traduco il Fortran originale (o C) in Java, non ho fatto altro che tradurlo. Se lo riscrivo totalmente in un paradigma OO, non assomiglierà più a Fortran o C originali, sarà irriconoscibile.

Non esiste una semplice mappatura da OO Design a Functional Design. Sono modi molto diversi di guardare al problema.

La programmazione funzionale (come tutti gli stili di programmazione) ha schemi di progettazione. I database relazionali hanno schemi di progettazione, OO ha schemi di progettazione, la programmazione procedurale ha schemi di progettazione. Tutto ha schemi di design, persino l'architettura degli edifici.

I modelli di progettazione - come concetto - sono un modo di costruire senza tempo, indipendentemente dalla tecnologia o dal dominio del problema. Tuttavia, schemi di progettazione specifici si applicano a specifici domini e tecnologie problematiche.

Tutti quelli che pensano a quello che stanno facendo scopriranno modelli di design.

Question

Da quando ho iniziato a studiare F # e OCaml l'anno scorso, ho letto un numero enorme di articoli che insistono sul fatto che i modelli di progettazione (specialmente in Java) sono soluzioni alternative per le funzionalità mancanti nelle lingue imperative. Un articolo che ho trovato fa una richiesta abbastanza forte :

La maggior parte delle persone che ho incontrato hanno letto il libro dei Pattern Design della Gang of Four. Qualsiasi programmatore che si rispetti da solo ti dirà che il libro è indipendente dal linguaggio e gli schemi si applicano all'ingegneria del software in generale, indipendentemente dalla lingua che usi. Questa è una richiesta nobile. Sfortunatamente è molto lontano dalla verità.

I linguaggi funzionali sono estremamente espressivi. In un linguaggio funzionale non ci sono schemi di progettazione perché il linguaggio è probabilmente così di alto livello, finisci per programmare in concetti che eliminano tutti i modelli di progettazione.

Le caratteristiche principali della programmazione funzionale includono funzioni come valori di prima classe, currying, valori immutabili, ecc. Non mi sembra ovvio che gli schemi di progettazione OO si avvicinino a queste caratteristiche.

Inoltre, nei linguaggi funzionali che supportano OOP (come F # e OCaml), mi sembra ovvio che i programmatori che utilizzano questi linguaggi utilizzino gli stessi schemi di progettazione disponibili per ogni altro linguaggio OOP. Infatti, in questo momento uso F # e OCaml ogni giorno, e non ci sono differenze sorprendenti tra i pattern che uso in queste lingue rispetto ai pattern che uso quando scrivo in Java.

C'è qualche verità nell'affermazione che la programmazione funzionale elimina la necessità di schemi di progettazione OOP? In tal caso, potresti pubblicare o collegare un esempio di un modello di progettazione OOP tipico e il suo equivalente funzionale?







Il libro GOF si lega esplicitamente a OOP - il titolo è Design Patterns - Elements of Reusable Object-Oriented Software (enfasi sul mio).




In sostanza, !

  • Quando un modello elude le caratteristiche mancanti (funzioni di ordine elevato, gestione del flusso ...) che l' ultimalty facilita la composition .
  • La necessità di ri-scrivere l'implementazione dei pattern ancora e ancora può essere vista come un odore del linguaggio .

Inoltre, questa pagina (AreDesignPatternsMissingLanguageFeatures) fornisce una tabella di conversione "pattern / feature" e alcune belle discussioni, se sei disposto a scavare.




OOP e FP hanno obiettivi diversi, OOP mira a incapsulare le complessità / parti in movimento di componenti software e FP mira a ridurre al minimo la complessità e le dipendenze dei componenti software, tuttavia questi 2 paradigmi non sono necessariamente contraddittori al 100% e potrebbero essere applicati insieme per ottenere il beneficio da entrambi i mondi. Anche con un linguaggio che non supporta nativamente la programmazione funzionale come C #, è possibile scrivere codice funzionale se si comprendono i principi FP, allo stesso modo si potrebbero applicare i principi OOP usando F # se si comprendono i principi OOP, i modelli e le migliori pratiche. Faresti la scelta giusta in base alla situazione e al problema che cerchi di risolvere, indipendentemente dal linguaggio di programmazione che usi.




Come altri hanno già detto, esistono schemi specifici di programmazione funzionale. Penso che il problema di eliminare gli schemi di progettazione non sia tanto il passaggio al funzionale, quanto una questione di caratteristiche linguistiche .

Dai un'occhiata a come Scala elimina il "modello singleton": dichiari semplicemente un oggetto invece di una classe. Un'altra caratteristica, la corrispondenza dei modelli, aiuta a evitare il clunkiness del pattern del visitatore. Vedi il confronto qui: http://andymaleh.blogspot.com/2008/04/scalas-pattern-matching-visitor-pattern.html

E Scala, come F #, è una fusione di OO-funzionale. Non conosco F # ma probabilmente ha questo tipo di funzionalità.

Le chiusure sono presenti in un linguaggio funzionale, ma non devono essere limitate a loro. Aiutano con il modello del delegato.

Un'altra osservazione. Questo pezzo di codice implementa uno schema: è così classico ed è così elementare che di solito non lo consideriamo un "pattern", ma è sicuro che sia:

for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); }

Linguaggi imperativi come Java e C # hanno adottato ciò che è essenzialmente un costrutto funzionale per affrontare questo: "foreach".




Nel nuovo libro del 2013 intitolato "Modelli di programmazione funzionale - in Scala e Clojure" l'autore Michael.B. Linn fa un lavoro decente comparando e fornendo sostituzioni in molti casi per i modelli GoF e discute anche i nuovi modelli funzionali come "ricorsione della coda", "memoizzazione", "sequenza pigra", ecc.

Questo libro è disponibile su Amazon. L'ho trovato molto istruttivo e incoraggiante quando proveniva da un passato OO di un paio di decenni.




E anche le soluzioni OO Design Pattern sono specifiche per la lingua. I modelli di progettazione sono soluzioni a problemi comuni che il tuo linguaggio di programmazione non risolve per te. In Java, il modello Singleton risolve il problema one-of-something (semplificato). In Scala, hai un costrutto di livello superiore chiamato Oggetto oltre a Class. È pigramente istanziato e ce n'è solo uno. Non è necessario utilizzare il modello Singleton per ottenere un Singleton. Fa parte della lingua.




Penso che solo due modelli di GoF Design siano progettati per introdurre la logica di programmazione funzionale in un linguaggio OO naturale. Penso a Strategia e Comando. Alcuni degli altri modelli di progettazione GoF possono essere modificati dalla programmazione funzionale per semplificare la progettazione e mantenere lo scopo.




Mi piacerebbe collegare un paio di carte eccellenti ma piuttosto dense di Jeremy Gibbons: "Modelli di design come programmi generici di tipo più alto ordine" e "L'essenza del pattern di Iterator" (entrambi disponibili qui: http://www.comlab.ox.ac.uk/jeremy.gibbons/publications/ ).

Entrambi descrivono come i costrutti funzionali idiomatici coprano il terreno coperto da specifici schemi di progettazione in altre impostazioni (orientate agli oggetti).




La presentazione di Norvig allude a un'analisi che hanno fatto di tutti i modelli GoF, e affermano che 16 dei 23 modelli avevano implementazioni più semplici in linguaggi funzionali o erano semplicemente parte del linguaggio. Quindi presumibilmente almeno sette di loro erano a) ugualmente complicati o b) non presenti nella lingua. Sfortunatamente per noi, non sono elencati!

Penso che sia chiaro che la maggior parte dei modelli "creazionali" o "strutturali" in GoF sono solo trucchi per ottenere i primitivi sistemi di tipi in Java o C ++ per fare ciò che vuoi. Ma il resto è degno di considerazione, non importa in che lingua si programma.

Uno potrebbe essere il prototipo; mentre è una nozione fondamentale di JavaScript, deve essere implementata da zero in altre lingue.

Uno dei miei pattern preferiti è il pattern Null Object: rappresenta l'assenza di qualcosa come un oggetto che fa un tipo appropriato di nulla. Questo potrebbe essere più facile da modellare in un linguaggio funzionale. Tuttavia, il vero risultato è il cambiamento di prospettiva.




Links