Perché la programmazione imperativa è preferita alla programmazione funzionale? [chiuso]


13

Background: sono un sostenitore della programmazione funzionale che lavora in un negozio VB.NET dove il modello mentale prevalente è la programmazione imperativa. Essendo la base del nostro sistema sono WinForms, posso capire che non ci allontaneremo completamente dalla programmazione imperativa, ma cerco comunque di usare FP (principalmente via Linq) dove possibile perché credo nei suoi meriti.

Argomenti e controargomentazioni contro FP

  1. Si potrebbe notare che Linq fluente è meno efficiente della sua controparte imperativa in quanto questo stile elabora una sequenza fino a un'altra sequenza e la ripete. In generale, richiederà alcuni passaggi in più rispetto all'approccio imperativo che può essere ottimizzato meglio per evitare passaggi ripetuti su una sequenza. Per questo motivo, il lead non riusciva a capire perché avrei scelto un approccio funzionale chiaramente "meno efficiente".

    • Contro-argomento : ho sostenuto che mentre a volte è meno efficiente in termini di cicli della CPU, ho sentito che è più umanamente comprensibile e facile da seguire poiché ogni linea fa solo una cosa sul suo passaggio sulla sequenza. Per me è come avere una catena di montaggio in cui ogni persona nella sua stazione ha un solo lavoro da svolgere. Sento che il trascurabile compromesso dell'efficienza è compensato da un codice le cui preoccupazioni sono nettamente separate.
  2. Il prossimo argomento contro FP che sento nel mio negozio è che è più difficile eseguire il debug - il che è vero. Non è facile scavalcare il codice Linq. E a volte devo svelare una catena di metodi per seguire meglio e analizzare i problemi che non riesco a individuare immediatamente.

    • _Counter-argomento: per la maggior parte anche se non ho problemi con questo perché penso che lo stile funzionale sia più dichiarativo nel modo in cui legge e quando viene generato un errore all'interno di una catena funzionale, di solito posso individuare immediatamente il problema.

La mia domanda

Ho cercato di promuovere lo stile funzionale nel nostro negozio e non mi sento di fare progressi. Ho fatto entrambi gli stili di programmazione e solo recentemente mi sono dilettato in Haskell. Nonostante anni di esperienza imperativa, ora che uso abitualmente FP in JavaScript, è cresciuto su di me. Suona una nota di correttezza nel mio nucleo quando lo paragono a quello che avrei potuto fare se mi fossi bloccato in uno stile imperativo. Ho riqualificato il mio cervello verso il pensiero funzionale, verso la composizione funzionale.

Quello che non riesco a capire è quanto sia stato difficile convincere gli altri dei meriti di FP.

Ad esempio, gli sviluppatori nel mio negozio usano Linq, ma penso che generalmente lo utilizzino nel contesto della gestione dei dati di dominio. Lo uso in un senso più generale e lo preferisco ogni volta che ho a che fare con sequenze / elenchi o strutture di dati persistenti. Non sono stato in grado di convincere i miei compagni di squadra ad espandere il loro uso di Linq.

Quello che sto cercando di capire è ciò che impedisce a uno sviluppatore di non apprezzare FP.

Mi piacerebbe vedere una risposta da qualcuno che ha una buona esperienza con FP ma ha deciso a favore dello stile imperativo. Cosa ha spinto la decisione di rimanere con l'imperativo invece di usare funzionale?


Ecco un ulteriore esempio che evidenzia le differenze tra programmazione imperativa e funzionale.

Ho scritto il SelectedRowsmetodo della nostra griglia in Linq come tale:

Public Property SelectedRows() As DataRow() Implements IDataSourceControl.SelectedRows
    Get
        Return Me.ugrBase.Selected.Rows.
            OfType(Of Infragistics.Win.UltraWinGrid.UltraGridRow)().
            Select(Function(ugr) ugr.ListObject).
            OfType(Of DataRowView)().
            Select(Function(drv) drv.Row).
            ToArray
    End Get

Tuttavia, questo stile di codice mette a disagio alcuni dei nostri sviluppatori e quindi il nostro lead lo ha riscritto per i più familiari:

Public Property SelectedRows() As DataRow() Implements IDataSourceControl.SelectedRows
    Get
        Dim plstRows As New List(Of DataRow)
        For Each bugrLoop As Infragistics.Win.UltraWinGrid.UltraGridRow In Me.ugrBase.Selected.Rows
            If bugrLoop.ListObject IsNot Nothing Then
                plstRows.Add(CType(bugrLoop.ListObject, DataRowView).Row)
            End If
        Next
        Return plstRows.ToArray()
    End Get

Mi piace la programmazione funzionale, ma da una rapida occhiata al codice preferirei l' approccio "imperativo" (che chiamo dichiarativo ). È molto più facile da leggere per me, dato che questa potrebbe essere la mia esperienza ed essere un prodotto del mio ambiente. Detto questo, in soli 5 secondi posso vedere i passaggi di preparazione e cosa viene restituito. Vedo che esiste un ciclo e so che è più che probabile che si verifichino modifiche a tali dati al suo interno. Non devo rintracciare le definizioni delle funzioni; è lì, è semplice. Ma FP è più pulito e una volta superata la curva di apprendimento, probabilmente sarebbe altrettanto veloce da programmare.
vol7ron,

È la curva di apprendimento che è il problema, soprattutto quando si lavora con persone che conoscono solo "quanto basta" di molte lingue. Se sei specializzato in una lingua particolare, sono sicuro che FP sarebbe un primo tentativo migliore. Quindi se ci fossero inefficienze (prestazioni unit test), si potrebbe essere più espliciti nelle loro implementazioni.
vol7ron,

Risposte:


11

La programmazione funzionale è troppo complicata per i programmatori inesperti . Una delle illustrazioni è questa , in cui gli studenti hanno dichiarato che il disordine di 30-LOC era più facile e più intuitivo da comprendere rispetto all'analogo FP a quattro righe.

(Questa è la versione originale dell'esempio FP, poiché la risposta nel collegamento è stata modificata più di recente per renderla leggermente più facile da leggere.)

return this.Data.Products
    .Where(c => c.IsEnabled)
    .GroupBy(c => c.Category)
    .Select(c => new PricesPerCategory(category: c.Key, minimum: c.Min(d => d.Price), maximum: c.Max(d => d.Price)));

La programmazione funzionale richiede un modo diverso di pensare al modo in cui codifichiamo e al modo in cui questo codice viene eseguito. Questo è raramente il modo in cui gli studenti vengono informati al college e , una volta prese le cattive abitudini, è difficile cambiarle.

La programmazione funzionale ha anche le sue caratteristiche specifiche che possono apparire rischiose nelle mani dei principianti . La valutazione pigra è una di queste e potrebbero volerci mesi prima che si inizi a capire perché la valutazione pigra è una caratteristica eccellente e non un fastidio.

Questo è anche il motivo per cui così tanti principianti iniziano a programmare con linguaggi come PHP e non linguaggi come Haskell.


8
Ho avuto l'esperienza opposta in un'università in cui Scheme viene utilizzato per il corso introduttivo. Quando gli studenti hanno dovuto imparare Java o C #, molti si sono lamentati del fatto che Scheme fosse più leggibile
Daniel Gratzer,

2
Questo dimostra il mio punto. Gli studenti che hanno imparato la programmazione imperativa e OOP per anni lo troveranno più leggibile. Le persone che hanno iniziato con FP lo troveranno più leggibile rispetto alla programmazione imperativa. Sarebbe interessante sapere cosa succede agli studenti che conoscono ugualmente bene i paradigmi FP e non FP.
Arseni Mourzenko,

1
Il problema principale è che i linguaggi funzionali si astraggono molto. Quando un Haskeller ti dice che hai esaurito la memoria perché hai accumulato thunk non valutati, allora c'è sicuramente qualcosa che non va. Molti algoritmi non sono efficienti quando sono scritti in uno stile funzionale. Non è possibile implementare un impl veloce Quicksort. in idiomatico Haskell. Ogni algoritmo sul posto finisce nel fare array IO per ottenere buone prestazioni. I linguaggi funzionali sono per i puristi delle lingue, i linguaggi imperativi sono per le persone che vogliono farsi pensare in tempo.
Kr0e

3
@ Kr0e: l'argomento "riassume troppo" contro una lingua o un paradigma mi sembra sempre strano. Lo stesso argomento è stato usato contro tutte (o la maggior parte) lingue; si spera che oggi la maggior parte dei software non sia scritta in Assembler.
Arseni Mourzenko,

6
"I linguaggi funzionali sono per i puristi delle lingue, i linguaggi imperativi sono per le persone che vogliono farsi pensare in tempo.": Secondo la mia esperienza questo non è vero. Posso fare le cose più rapidamente usando linguaggi funzionali. Lo stile imperativo è molto più dettagliato e meno dichiarativo e quando devo usare un linguaggio imperativo ho sicuramente bisogno di più iterazioni prima di ottenere le cose giuste.
Giorgio,
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.