Ich vermute, das hängt von der Sprache ab. Was die funktionale Programmierung anbelangt, habe ich mich hauptsächlich mit Haskell beschäftigt, daher werde ich erklären, wie es dort funktioniert.
Haskell-Code ist in "Module" unterteilt, bei denen es sich im Grunde nur um Sammlungen von Funktionen und Datentypen handelt. Jedes Modul ist eine einzelne Datei. Ein Modul ist eine Mischung aus einer Java-Klasse und einem Java-Paket - der genaue Umfang der Funktionen eines Moduls variiert. Ein Modul hat auch die Kontrolle darüber, welche Funktionen und Typkonstruktoren exportiert und welche ausgeblendet werden sollen. Dies ist ähnlich private
und public
in Java.
In meinen eigenen Programmen möchte ich, dass Module eine Sache semantisch erledigen . Dies macht sie wie eine Java-Klasse, abgesehen davon, dass sie möglicherweise mehrere Datentypen definieren. Die Module, die ich aus der Standardbibliothek verwende, Data.List
ähneln eher Paketen - sie bieten eine Reihe ähnlicher Dienstprogrammfunktionen. Dies ist auch sehr ähnlich zu statischen Java-Klassen wie java.util.Arrays
.
Die Module ähneln auch Java-Paketen, da sie der Übersichtlichkeit halber verschachtelt werden können (ich glaube, dies hat keine Auswirkungen auf den Code selbst). Im Allgemeinen gebe ich einem einzelnen Projekt einen Namen (etwa Project
) und lasse alle meine Module Teil davon sein (z . B. Project.Parse
und Project.Run
). Wenn ich Code schreiben würde, der eher einer Bibliothek als einer Anwendung ähnelt, würde ich ihn auf der Grundlage dessen organisieren, was er tut, wie Data.List
oder Control.Monad
. Ein wesentlicher Unterschied zu anderen Sprachen besteht darin, dass Haskell dazu ermutigt, E / A zu begrenzen und alles an einem Ort zu platzieren. Eine große Anzahl von Modulen hat überhaupt keine E / A-Funktion, und für ein bestimmtes Projekt möchte ich, dass so viele Module wie möglich rein sind.
Als Beispiel arbeite ich an einer einfachen Programmiersprache, die ich TPL nenne (ohne guten Grund). Dafür habe ich zwei einfache Module erstellt: Diese TPL.Parse
definieren die interne Darstellung der Sprache und wie sie analysiert wird, und TPL.Run
welche den Interpreter ausführen und sich mit Variablen und IO befassen. Um den Code tatsächlich zu kompilieren und auszuführen, gibt es im Allgemeinen ein Main
Modul, das den Einstiegspunkt des Programms darstellt.
Die Funktionen in einer Datei können sehr frei organisiert werden. das ist genau das, was ich gerne mache. Ich definiere meine Datentypen nach oben, bevor sie woanders verwendet werden. Gleich nach dem Definieren der Datentypen implementiere ich alles, was ich brauche, um sie in die entsprechenden Typklassen aufzunehmen - das ist wie das Implementieren einer Schnittstelle. Dann folge ich mit Logik und verschiedenen Hilfsfunktionen, je nach Bedarf. Schließlich möchte ich alle meine E / A-Funktionen ganz unten mit enden lassen main
. Dies macht deutlich, was genau ein IO tut und wo das Programm startet.
Zusammenfassend: Funktionen sind in Modulen enthalten, von denen jedes aus einer einzelnen Datei besteht. Mehrere Module können ein Programm oder eine Bibliothek bilden. Ersteres enthält im Allgemeinen ein Main
Modul, das sein Einstiegspunkt ist. Innerhalb einer Datei gibt es verschiedene Optionen für die Organisation, aber ich bevorzuge es, Datentypen oben, E / A unten und Logik in der Mitte zu gruppieren.
What's stopping you from...
Jahrelange Programmierung mit einer völlig anderen Denkweise, bis zu dem Punkt, an dem Haskell-Code nicht mehr mental rechnet. Und Sie gehen natürlich davon aus, dass echte Projekte immer korrekt und ordentlich organisiert sind (vielleicht sind sie es aber, wie kann ein Noob wie ich das wissen?)