2009-09-22 15 views
6

Ho usato f # e Haskell per imparare la programmazione funzionale per un po 'di tempo. Fino a quando non posso ottenere l'approvazione f # nella nostra azienda, devo ancora usare C#. Sto ancora cercando comunque di rimanere nello stile funzionale, come ho notato diversi vantaggi.Da OO alla programmazione funzionale a 10.000 piedi

Ecco un problema tipico.

  1. V'è una tabella di chiavi set nel database con 3 chiavi (6,5 milioni righe)
  2. Ci sono altre 4 supportano tavoli di piccole e medie dimensioni.
  3. Esistono formule complesse basate su diversi input.

Devo utilizzare i dati di tutti i precedenti per calcolare un valore e associarlo a ciascuna riga dell'insieme di tasti e inviarlo al database. Ci sono molte ricerche sugli altri 4 tavoli. Per motivi di prestazioni è tutto fatto in memoria.

So esattamente come farei l'in OO con dizionari statici, modelli di oggetti, modelli di strategia e così via, ma in un modo funzionale non riesco a liberarmi del cattivo odore dell'utilizzo di alcuni di questi costrutti.

Attualmente sto facendo le seguenti ipotesi per una soluzione funzionale.

  1. I dizionari statici sono negativi. Sembra che la funzione possa avere effetti collaterali.

  2. Ho bisogno di una funzione Calcola, accetta un oggetto immutabile e restituisce un oggetto immutabile con le tre chiavi e il valore calcolato. All'interno di questa funzione potrebbe esserci un'altra funzione nello stesso stile.

  3. I modelli OO tradizionali probabilmente non funzioneranno.

Come progettare questo ad alto livello?

Mi sbaglio? Ho perso qualcosa?

risposta

6

No, non sei sbagliato. Sia l'OOP che la programmazione funzionale hanno i loro vantaggi e i loro inconvenienti.

Uno sviluppatore ha bisogno di sapere come e quando utilizzare ogni stile di sviluppo. È una fortuna che C# supporti in entrambi gli stili di sviluppo.

A mio parere, e uso entrambi gli stili di programmazione funzionale e oop su basi giornaliere, oop è la soluzione migliore quando si ha a che fare con interazioni complesse e interdipendenze tra vari artefatti astratti (entità, nomi ecc.). La programmazione funzionale viene utilizzata al meglio quando si tratta di algoritmi, trasformazioni di dati, ecc. Ad es. situazioni in cui la complessità delle affermazioni necessarie per risolvere un dato problema è grande.

Generalmente utilizzo la programmazione orientata agli oggetti sul mio dominio (entità, aggregati, oggetti valore, archivi ed eventi) e riservo la programmazione funzionale per i miei oggetti di servizio.

Il più delle volte si tratta di un odore, o sensazione che è il migliore, dal momento che nello sviluppo del software non sono casi ben definiti, e l'esperienza e la pratica spesso è il miglior giudice per una determinata scelta.

0

La programmazione funzionale in un linguaggio OO tende a essere errata. Produce codice eccessivamente verbose che non esegue bene ed è più soggetto a errori (come scrivere funzioni ricorsive profondamente in una lingua che non supporta le chiamate di coda.)

Blockquote 1. dizionari statici sono cattivi. Sembra che la funzione possa avere effetti collaterali.

O ha o non ha effetti collaterali. Un dizionario statico può essere un buon modo per implementare la memoizzazione in un linguaggio OO.

Blockquote 3. I modelli OO tradizionali probabilmente non funzioneranno.

I modelli OO funzionano bene in un linguaggio OO cercando di calzare le tecniche di corno FP in un linguaggio OO produrranno un codice prolisso e prolisso. È piuttosto come cercare di usare un cacciavite con tecniche di martello che sicuramente produce un risultato, ma ci sono modi migliori. Cerca di usare i tuoi strumenti nel miglior modo possibile. Alcune tecniche FP possono essere utili ma ignorare completamente la lingua non è un codice di buona qualità.

+0

Dipende dalla lingua OO in questione. C# svolge un ottimo lavoro con tecniche funzionali. E alcune cose possono essere fatte in modo abbastanza funzionale in linguaggi OO più dolorosamente inflessibili come Java, ma in questo caso c'è sicuramente una buona dose di attrito cognitivo. – JasonTrue

+1

Se si finisce per provare a fare qualcosa di funzionale e si trova nell'ambiente Java, probabilmente è meglio farlo in Clojure. Sebbene tecnicamente sia un linguaggio Lisp e non un linguaggio ML, può essere fatto per funzionare con applicazioni Java (genera un bytecode JVM) e supportare lo sviluppo di stili funzionali. –

+0

C# cade piatto su molte tecniche funzionali.Inferenza di tipo estremamente limitata è solo un rompicapo. Prova a scrivere il tipo di una funzione che utilizza diversi parametri generici, come un dizionario di funzioni. Ahia. – MichaelGG

2

Se cerchi velocità, potresti prendere in considerazione le strutture di dati sottostanti utilizzate. Dizionario <> in C# è una tabella hash mentre SortedDictionary <> in C# è un albero di ricerca binario.

F # e Haskell fanno entrambi un buon lavoro di rappresentazione delle strutture di dati dell'albero. Potresti considerare di utilizzare una struttura dati più specifica rispetto a quelle predefinite fornite da C#.

Ad un livello elevato vorrei capire quali sono le caratteristiche delle prestazioni visualizzate e confrontarle con le diverse strutture dati (wikipedia è una buona fonte se è necessario un aggiornamento). Una volta individuate le strutture dati da utilizzare, mi preoccuperei di quali implementazioni utilizzare.

+1

Non so su C#, ma una tabella di hash correttamente implementata non ha ricerche lente. Per mantenere la velocità di ricerca, gli inserimenti devono occasionalmente eseguire nuovamente l'intera tabella. (Ma questo non è un grosso problema, anche BerkeleyDB fa questo per i suoi hash su disco.) Il vantaggio di un albero su una tabella hash è la località di riferimento; se si sta iterando su un blocco della tabella "in ordine", è facile precaricare i nodi "successivi". – jrockway

+0

Ho rimosso i miei commenti su cosa è più veloce o più lento. Ci sono molti vantaggi e svantaggi per le tabelle hash e gli alberi binari a seconda di come li usi. C# Dictionary <> ha davvero un tempo di ricerca veloce. "Il tempo medio di esecuzione asintotica per aggiungere, rimuovere e cercare l'hashtable utilizzando il probe è il tempo costante, O (1)" http://msdn.microsoft.com/en-us/library/ms379571(VS.80).aspx – gradbot

1

Come progettare questo ad alto livello?

Fondamentalmente, si utilizzano le funzioni di ordine superiore per ridurre il lavoro in componenti riutilizzabili con basso sovraccarico sintattico. Quindi ti piacerebbe migrare da strutture dati imperative a strutture dati puramente funzionali (calcolo puramente funzionale avvolto in effetti collaterali per IO come scritture di database). Infine, potresti anche monitorare gli effetti collaterali (completamente puramente funzionali).

Come una guida approssimativa, queste tre gradazioni per completare la purezza sono viste in primo luogo in Lisp (in gran parte impuro), Standard ML (molto più pesante uso di strutture dati puramente funzionali) e Haskell (completa purezza).

Non posso dare ulteriori dettagli senza conoscere il problema esatto, ma potete stare tranquilli che molte persone lo fanno quotidianamente e funziona perfettamente.

Problemi correlati