Sospetto che ciò dipenda dalla lingua. Per quanto riguarda la programmazione funzionale, mi sono principalmente dilettato in Haskell, quindi ho intenzione di spiegare come funziona lì.
Il codice Haskell è organizzato in "moduli" che sono fondamentalmente solo raccolte di funzioni e tipi di dati. Ogni modulo è un singolo file. Un modulo è una sorta di mix tra una classe Java e un pacchetto Java: lo scopo esatto di ciò che varia un modulo. Un modulo ha anche il controllo su quali funzioni e costruttori di tipi da esportare e quali nascondere; questo è simile a private
e public
in Java.
Nei miei programmi, mi piace avere moduli una cosa, semanticamente; questo li rende come una classe Java, tranne per il fatto che potrebbero definire più tipi di dati. I moduli che uso dalla libreria standard, come Data.List
, sono più simili ai pacchetti: forniscono un insieme di funzioni di utilità simili. Questo è anche molto simile alle classi Java statiche come java.util.Arrays
.
I moduli sono anche come pacchetti Java in quanto possono essere annidati per chiarezza (non penso che questo abbia alcun effetto sul codice stesso). In generale, per un singolo progetto, gli do un nome (ad esempio Project
) e tutti i miei moduli fanno parte di questo (ad esempio Project.Parse
e Project.Run
). Se scrivessi codice che fosse più simile a una libreria che a un'applicazione, lo organizzerei in base a ciò che stava facendo, ad esempio Data.List
o Control.Monad
. Una delle principali differenze rispetto ad altre lingue è che Haskell incoraggia limitare l'IO e mettere tutto in un unico posto. Un gran numero di moduli non ha alcun IO e, per qualsiasi progetto, mi piace avere il maggior numero possibile di moduli.
Ad esempio, sto lavorando su un semplice linguaggio di programmazione che sto chiamando TPL (senza una buona ragione). Per questo ho creato due moduli semplici: TPL.Parse
che definisce la rappresentazione interna del linguaggio e come analizzarlo, e TPL.Run
che esegue l'interprete e si occupa di variabili e IO. Per la compilazione e l'esecuzione del codice, generalmente c'è un modulo Main
che è quello che finisce per essere il punto di ingresso del programma.
Esiste una notevole libertà nell'organizzazione delle funzioni all'interno di un file; questo è proprio quello che mi piace fare. Definisco i miei tipi di dati verso l'alto, prima che vengano utilizzati altrove. Subito dopo aver definito i tipi di dati, implemento tutto ciò di cui ho bisogno per renderli parte dei loro typeclass appropriati: è come implementare un'interfaccia. Quindi seguo con logica e varie funzioni di supporto, a seconda dei casi. Infine, mi piace avere tutte le mie funzioni di I / O in fondo alla fine con main
. Questo chiarisce esattamente cosa sta facendo ogni IO e dove inizia il programma.
Quindi, in sintesi: le funzioni sono contenute in moduli, ognuno dei quali è costituito da un singolo file. Diversi moduli possono costituire un programma o una libreria; il primo include generalmente un modulo Main
che è il suo punto di ingresso. All'interno di un file ci sono diverse opzioni per l'organizzazione, ma preferisco raggruppare i tipi di dati nella parte superiore, IO nella parte inferiore e la logica nel mezzo.