Non sono sicuro che questo soddisferà interamente la tua domanda, ma si spera che si avvicini.
Requisiti / casi d'uso / specifiche funzionali / qualunque sia la tua chiamata, sono ancora ottimi strumenti per comunicare il design di un programma FP. Ma un modello di visual design per i programmi FP è un po 'meno interessante. Si tratta di definire input e output per ogni caso d'uso e una funzione che mappa l'input in output. Noioso vero? Ok, qualche spiegazione ...
Le responsabilità differiscono
Una classe OO è spesso proprietaria di 3 concetti diversi: stato attuale dei dati (un concetto implicito), struttura dei dati (proprietà o getter) e comportamento sui dati (metodi).
FP - come in: programmazione con funzioni pure - generalmente si occupa solo di 2 di queste cose. Struttura e comportamento. Lo stato attuale è spinto al limite del sistema come preoccupazione per la persistenza. Quindi, ad esempio, un modulo responsabile del prodotto dovrebbe sapere quali proprietà ha (struttura) e quali operazioni è possibile eseguire (comportamento). Ma devi dire alle operazioni lo stato corrente di un Prodotto prima che possa eseguire l'operazione. Restituirà quindi una nuova copia del Prodotto con le modifiche applicate.
Si potrebbe modellare questo in UML come una classe con solo metodi statici per il comportamento. E una classe dati in cui tutte le proprietà sono di sola lettura per la struttura. La classe data verrebbe utilizzata come parte dell'input / output sui metodi di comportamento. Ma collegarli ad altri moduli è il punto in cui il design del tipo UML si interromperà, perché ...
L'organizzazione è diversa
Con OO, spesso ci sono molte classi interconnesse che comunicano tra loro. Ognuno di loro possiede una parte dello stato che il sistema deve operare. Ma con FP, moduli come il Prodotto sopra descritto sono generalmente autonomi e indipendenti dal momento che non hanno uno stato. Sono "connessi" solo in quelle funzioni di livello superiore (cioè usano funzioni di caso come placeOrder
) chiameremo le funzioni più specializzate (come Order.validate
e Product.canBeOrdered
) per aiutare a convertire l'input in un valore di ritorno.
Questo è il caso in cui strumenti come UML si riducono a FP perché essenzialmente modellano i diagrammi di stato, ma i programmi funzionali sono più simili a gerarchie di chiamate di funzioni. Un modo probabilmente più utile per modellare i programmi funzionali è con i diagrammi del flusso di dati come menzionato nei commenti di questa domanda . Puoi anche utilizzare un diagramma di flusso annidato in cui ogni passaggio decisionale ha il proprio diagramma di flusso separato per descrivere il suo flusso interno.
Direi che modellare le funzioni specializzate è una perdita di tempo. Queste sono spesso piccole e le pure funzioni sono facili da refactoring, quindi potrebbero essere aggiornate frequentemente. Potresti ottenere un sacco di tempo per aggiornare il tuo modello di progettazione se si scende a quel livello. Probabilmente il livello più basso per cui vuoi creare un modello di design sono le funzioni del caso d'uso.
Tuttavia, non ho osservato i modelli di progettazione del programma come pratica comune in FP (non che UML sia comune ... non lo ho mai usato professionalmente). L'estensione della maggior parte dei metodi di progettazione FP che ho visto sta solo definendo le firme delle funzioni dall'alto verso il basso nel codice. Quindi, mentre si completa l'implementazione, creare firme fn per le funzioni più specializzate. Organizzali in moduli e poi inizia a lavorare sulle loro implementazioni. Continua a seguire questa procedura ricorsiva fino a quando non colpisci le tartarughe.
Bordi
I bordi di un sistema sono dove le cose iniziano a diventare più compatibili con UML. Poiché i programmi, infatti, hanno bisogno di conoscere lo stato corrente per essere utili. Qui è dove si collegano le varie tecnologie come database, chiamate API esterne, ecc. Questa progettazione a livello di sistema è l'unico tipo di diagramma che io abbia mai fatto.
Altrimenti, definire i casi d'uso con i loro input e output (visivamente se lo si desidera) è il livello a cui si dovrebbe fare un modello di progetto di un programma funzionale. Definisci la struttura di input, la struttura di output e una funzione che mappa l'input in output.