Domanda

L'ingegneria del software come viene insegnata oggi è interamente focalizzata sulla programmazione orientata agli oggetti e sulla visione "naturale" del mondo orientata agli oggetti.Esiste una metodologia dettagliata che descrive come trasformare un modello di dominio in un modello di classe con diversi passaggi e molti artefatti (UML) come diagrammi di casi d'uso o diagrammi di classi.Molti programmatori hanno interiorizzato questo approccio e hanno una buona idea su come progettare da zero un'applicazione orientata agli oggetti.

La nuova moda è la programmazione funzionale, che viene insegnata in molti libri e tutorial.Ma che dire dell’ingegneria del software funzionale?Durante la lettura di Lisp e Clojure, sono arrivato a due affermazioni interessanti:

  1. I programmi funzionali sono spesso sviluppati dal basso verso l'alto anziché dall'alto verso il basso ("On Lisp", Paul Graham)

  2. I programmatori funzionali utilizzano mappe dove i programmatori OO utilizzano oggetti/classi ("Clojure for Java Programmers", discorso di Rich Hickley).

Allora qual è la metodologia per una progettazione sistematica (basata su modello?) di un'applicazione funzionale, ad es.in Lisp o Clojure?Quali sono i passaggi comuni, quali artefatti utilizzo, come posso mapparli dallo spazio del problema allo spazio della soluzione?

È stato utile?

Soluzione

Grazie a Dio che le persone ingegneristica non hanno ancora scoperto la programmazione funzionale. Ecco alcuni parallelismi:

  • Molti "modelli di progettazione" OO vengono catturati come funzioni di ordine superiore. Ad esempio, il modello di visitatore è noto nel mondo funzionale come una "piega" (o se sei un teorico a testa appuntita, un "cataurfismo"). Nei linguaggi funzionali, i tipi di dati sono principalmente alberi o tuple e ogni tipo di albero ha un catamorfismo naturale ad esso associato.

    Queste funzioni di ordine superiore spesso presentano alcune leggi della programmazione, noto anche come "teoremi gratuiti".

  • I programmatori funzionali usano i diagrammi molto meno pesanti rispetto ai programmatori OO. Gran parte di ciò che viene espresso nei diagrammi OO è invece espressa in tipi, o nelle "firme", che dovresti pensare come "tipi di moduli". Haskell ha anche "classi di tipo", che è un po 'come un tipo di interfaccia.

    Quei programmatori funzionali che usano i tipi generalmente pensano che "una volta ottenuti i tipi giusti; il codice praticamente si scrive".

    Non tutti i linguaggi funzionali usano tipi espliciti, ma il Come progettare programmi Libro, un eccellente libro per l'apprendimento/Lisp/Clojure, si basa fortemente su "descrizioni dei dati", che sono strettamente correlate ai tipi.

Allora qual è la metodologia per una progettazione sistematica (basata su modelli?) Di un'applicazione funzionale, cioè in lisp o clojure?

Qualsiasi metodo di progettazione basato sull'astrazione dei dati funziona bene. Mi capita di pensare che questo sia più facile quando la lingua ha tipi espliciti, ma funziona anche senza. Un buon libro sui metodi di progettazione per i tipi di dati astratti, che è facilmente adattato alla programmazione funzionale, è Astrazione e specifiche nello sviluppo del programma di Barbara Liskov e John Guttag, il primo edizione. Liskov ha vinto il Turing Award in parte per quel lavoro.

Un'altra metodologia di progettazione che è unica per LISP è decidere quali estensioni linguistiche sarebbero utili nel dominio problematico in cui stai lavorando e quindi utilizzare le macro igieniche per aggiungere questi costrutti alla tua lingua. Un buon posto per leggere questo tipo di design è l'articolo di Matthew Flatt Creazione di lingue in racchetta. L'articolo potrebbe essere dietro un paywall. Puoi anche trovare materiale più generale su questo tipo di design cercando il termine "linguaggio incorporato specifico del dominio"; Per consigli particolari ed esempi oltre a ciò che Matthew Flatt copre, probabilmente inizierei con Graham Su lisp o forse ANSI Common Lisp.

Quali sono i passaggi comuni, quali artefatti uso?

Passaggi comuni:

  1. Identifica i dati nel programma e le operazioni su di esso e definisci un tipo di dati astratto che rappresenta questi dati.

  2. Identificare azioni o modelli di calcolo comuni ed esprimerle come funzioni o macro di ordine superiore. Aspettatevi di fare questo passo come parte del refactoring.

  3. Se si utilizza un linguaggio funzionale digitato, usa il tipo di controllo in anticipo e spesso. Se stai utilizzando LISP o Clojure, la migliore pratica è prima di scrivere contratti di funzioni, inclusi i test unitari: lo sviluppo basato sul test al massimo. E vorrai usare qualunque versione di QuickCheck sia stata portata sulla tua piattaforma, che nel tuo caso sembra che sia chiamato ClojureCheck. È una libreria estremamente potente per la costruzione di test casuali di codice che utilizza funzioni di ordine superiore.

Altri suggerimenti

Per Clojure, consiglio di tornare alla buona vecchia modellazione relazionale. Fuori dallo è una lettura ispiratrice.

Personalmente trovo che tutte le solite buone pratiche dello sviluppo di OO si applicano anche nella programmazione funzionale - solo con alcune piccole modifiche per tenere conto della visione del mondo funzionale. Dal punto di vista metodologico, non è davvero necessario fare qualcosa di fondamentalmente diverso.

La mia esperienza viene dall'essere trasferito da Java a Clojure negli ultimi anni.

Qualche esempio:

  • Comprendi il tuo dominio / modello di dati aziendali - Altrettanto importante se si progetta un modello a oggetti o crei una struttura di dati funzionale con mappe nidificate. In un certo senso, FP può essere più semplice perché ti incoraggia a pensare al modello di dati separatamente dalle funzioni / processi, ma devi ancora fare entrambe le cose.

  • Orientamento del servizio nella progettazione - In realtà funziona molto bene dal punto di vista FP, poiché un servizio tipico è in realtà solo una funzione con alcuni effetti collaterali. Penso che la visione "bottom up" dello sviluppo del software a volte sposato nel mondo LISP sia in realtà solo buoni principi di progettazione API orientati al servizio in un'altra veste.

  • Sviluppo guidato dal test - Funziona bene nelle lingue FP, in effetti a volte anche meglio perché le funzioni pure si prestano molto bene a scrivere test chiari e ripetibili senza alcuna necessità di impostare un ambiente statale. Potresti anche voler creare test separati per controllare l'integrità dei dati (ad esempio questa mappa ha tutte le chiavi che mi aspetto, per bilanciare il fatto che in una lingua OO la definizione della classe lo farà rispettare questo al momento della compilazione).

  • Prototismo / iterazione - Funziona altrettanto bene con FP. Potresti anche essere in grado di prototipo di vivere con gli utenti se diventi estremamente bravo a costruire strumenti / DSL e utilizzarli al ROSP.

La programmazione OO accoppia strettamente i dati con il comportamento. La programmazione funzionale separa i due. Quindi non hai diagrammi di classe, ma hai strutture di dati e hai in particolare tipi di dati algebrici. Questi tipi possono essere scritti per abbinare molto il tuo dominio, incluso l'eliminazione di valori impossibili per costruzione.

Quindi non ci sono libri e libri, ma c'è un approccio ben consolidato, come dice il proverbio, rendere i valori impossibili non rappresentabili.

In tal modo, puoi fare una serie di scelte su come rappresentare alcuni tipi di dati come funzioni invece e, al contrario, rappresentano invece alcune funzioni come unione di tipi di dati in modo da poter ottenere, ad esempio, serializzazione, specifiche più strette, ottimizzazione, ecc. .

Quindi, dato che scrivi funzioni sui tuoi annunci in modo da stabilire una sorta di algebra - cioè ci sono leggi fisse che valgono per queste funzioni. Alcuni sono forse idempotenti, lo stesso dopo più applicazioni. Alcuni sono associativi. Alcuni sono transitivi, ecc.

Ora hai un dominio sul quale hai funzioni che compongono in base alle leggi ben educate. Un semplice DSL incorporato!

Oh, e date proprietà, ovviamente puoi scrivere test randomizzati automatizzati (Ala Quickcheck) .. e questo è solo l'inizio.

La progettazione orientata agli oggetti non è la stessa cosa dell'ingegneria del software.L'ingegneria del software ha a che fare con l'intero processo di passaggio dai requisiti a un sistema funzionante, in tempo e con un basso tasso di difetti.La programmazione funzionale può essere diversa dall'OO, ma non elimina i requisiti, i progetti dettagliati e di alto livello, la verifica e il test, le metriche del software, la stima e tutto il resto del "materiale di ingegneria del software".

Inoltre, i programmi funzionali mostrano modularità e altre strutture.I tuoi progetti dettagliati devono essere espressi in termini di concetti in quella struttura.

Un approccio è quello di creare un DSL interno all'interno del linguaggio di programmazione funzionale di scelta. Il "modello" è quindi un insieme di regole aziendali espresse nel DSL.

Vedi la mia risposta a un altro post:

In che modo Clojure si avvicina alla separazione delle preoccupazioni?

Sono d'accordo che deve essere scritto di più sull'argomento su come strutturare grandi applicazioni che utilizzano un approccio FP (più devono essere fatti più per documentare le UIS guidate da FP)

Sebbene questo possa essere considerato ingenuo e semplicistico, penso che le "ricette di progettazione" (un approccio sistematico alla risoluzione dei problemi applicati alla programmazione come sostenuto da Felleisen et al. Nel loro libro Htdp) sarebbe vicino a quello che sembri cercare.

Qui, alcuni link:

http://www.northeaster.edu/magazine/0301/programming.html

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.86.8371

Ho scoperto che lo sviluppo basato sul comportamento si adattava naturalmente al codice in rapido sviluppo in Clojure e SBCL. Il vero rialzo di sfruttare BDD con un linguaggio funzionale è che tendo a scrivere test unitari di grano molto più fini di quello che faccio di solito quando uso linguaggi procedurali perché faccio un lavoro molto migliore nel decomprimere il problema in piccoli blocchi di funzionalità.

Di recente ho trovato questo libro:Modellazione del dominio funzionale e reattivo

Penso che sia perfettamente in linea con la tua domanda.

Dalla descrizione del libro:

La modellazione del dominio funzionale e reattivo ti insegna come pensare al modello di dominio in termini di funzioni pure e come comporli per costruire astrazioni maggiori. Inizierai con le basi della programmazione funzionale e progredisce gradualmente verso i concetti e i modelli avanzati che devi sapere per implementare modelli di dominio complessi. Il libro dimostra come i modelli FP avanzati come i tipi di dati algebrici, la progettazione basata su tiplass e l'isolamento degli effetti collaterali possano rendere il modello comporre il modello per la leggibilità e la verificabilità.

Onestamente se vuoi ricette di progettazione per programmi funzionali, dai un'occhiata alle librerie di funzioni standard come Haskell's Prelude. In FP, i modelli vengono generalmente acquisiti da procedure di ordine superiore (funzioni che operano sulle funzioni) stesse. Quindi, se si vede uno schema, spesso viene semplicemente creata una funzione di ordine superiore per catturare quel modello.

Un buon esempio è FMAP. Questa funzione prende una funzione come argomento e la applica a tutti gli "elementi" del secondo argomento. Poiché fa parte della classe di tipo funttore, qualsiasi istanza di un functor (come un elenco, grafico, ecc ...) può essere approvata come secondo argomento a questa funzione. Cattura il comportamento generale dell'applicazione di una funzione a ogni elemento del suo secondo argomento.

Esiste lo stile "Calcolo del programma" / "Design per calcolo" associato al Prof. Richard Bird e all'algebra del gruppo di programmazione presso l'Università di Oxford (Regno Unito), non credo che sia troppo inverosimile per considerare questa metodologia.

Personalmente mentre mi piace il lavoro prodotto dal gruppo AOP, non ho la disciplina per praticare il design in questo modo. Tuttavia è il mio difetto, e non un calcolo del programma.

Bene,

Generalmente molti linguaggi di programmazione funzionali vengono utilizzati nelle università per molto tempo per "piccoli problemi di giocattoli".

Stanno diventando più popolari ora poiché OOP ha difficoltà con la "programmazione del Paralel" a causa dello "stato". E a volte lo stile funzionale è migliore per i problemi a portata di mano come Google MapReduce.

Sono sicuro che, quando i ragazzi di Functioanl colpiscono il muro [provano ad implementare sistemi più grandi di 1.000.000 righe di codice], alcune di esse verranno fornite con nuove metodologie di ingegneria del software con parole buzz :-). Dovrebbero rispondere alla vecchia domanda: come dividere il sistema in pezzi in modo che possiamo "mordere" ogni pezzi alla volta? [Work Iterativo, in modo evolutivo in modo evolutivo] usando lo stile funzionale.

È sicuro che lo stile funzionale influirà sul nostro stile orientato agli oggetti. "Ancora" molti concetti da sistemi funzionali e adattati ai nostri linguaggi OOP.

Ma i programmi funzionali verranno utilizzati per un sistema così grande? Diventeranno il flusso principale? Questa è la domanda.

E nessuno può venire con metodologia realistica senza implementare un sistema così grande, facendo sporca le mani. Prima dovresti sporcarti le mani, quindi suggerire la soluzione. Le soluzioni-voci senza "dolori reali e sporcizia" saranno "fantasia".

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top