Podejrzewam, że to zależy od języka. Jeśli chodzi o programowanie funkcjonalne, głównie zajmowałem się Haskellem, więc wyjaśnię, jak tam działa.
Kod Haskell jest zorganizowany w „moduły”, które są w zasadzie tylko zbiorami funkcji i typów danych. Każdy moduł jest jednym plikiem. Moduł jest mieszanką klasy Java i pakietu Java - dokładny zakres działania modułu jest różny. Moduł ma również kontrolę nad tym, które funkcje i typy konstruktorów należy wyeksportować, a które ukryć; ten jest podobny do private
i public
w Javie.
W moich własnych programach lubię, gdy moduły robią jedną rzecz, semantycznie; dzięki temu są jak klasa Java, z tym wyjątkiem, że mogą definiować wiele typów danych. Moduły, których używam ze standardowej biblioteki, Data.List
są bardziej podobne do pakietów - zapewniają zestaw podobnych funkcji narzędziowych. Jest to również bardzo podobne do statycznych klas Java, takich jak java.util.Arrays
.
Moduły są również podobne do pakietów Java, ponieważ można je zagnieżdżać dla zachowania przejrzystości (nie sądzę, aby miało to jakikolwiek wpływ na sam kod). Ogólnie rzecz biorąc, dla jednego projektu nadaję mu nazwę (powiedzmy Project
) i chcę, aby wszystkie moje moduły były tego częścią (np. Project.Parse
I Project.Run
). Gdybym pisał kod, który byłby bardziej biblioteką niż aplikacją, zorganizowałbym go na podstawie tego, co robi, jak Data.List
lub Control.Monad
. Jedną z głównych różnic w stosunku do innych języków jest to, że Haskell zachęca do ograniczania IO i umieszczania tego wszystkiego w jednym miejscu. Duża liczba modułów w ogóle nie ma IO, a dla każdego projektu lubię mieć jak najwięcej modułów czystych, jak to możliwe.
Jako przykład pracuję nad prostym językiem programowania, który nazywam TPL (bez powodu). W tym celu stworzyłem dwa proste moduły: TPL.Parse
które definiują wewnętrzną reprezentację języka i jak go parsować, i TPL.Run
które uruchamiają interpreter i zajmują się zmiennymi i IO. Do faktycznego kompilowania i uruchamiania kodu jest na ogół Main
moduł, który ostatecznie stanowi punkt wejścia programu.
Istnieje znaczna swoboda w organizowaniu funkcji w pliku; to właśnie lubię robić. Typy danych określam u góry, zanim zostaną użyte w innym miejscu. Zaraz po zdefiniowaniu typów danych wdrażam wszystko, czego potrzebuję, aby uczynić je częścią odpowiednich klas typów - to coś w rodzaju implementacji interfejsu. Następnie stosuję logikę i różne funkcje pomocnicze, odpowiednio. Na koniec chciałbym mieć wszystkie moje funkcje IO na samym dole main
. Wyjaśnia to dokładnie, co robi dowolne IO i gdzie zaczyna się program.
Podsumowując: funkcje są zawarte w modułach, z których każdy składa się z jednego pliku. Kilka modułów może tworzyć program lub bibliotekę; ten pierwszy ogólnie obejmuje Main
moduł, który jest jego punktem wejścia. W pliku istnieją różne opcje organizacji, ale wolę grupować typy danych u góry, IO u dołu i logikę pośrodku.
What's stopping you from...
Lata programowania z zupełnie innym nastawieniem, do tego stopnia, że kod Haskell nie oblicza się mentalnie. I oczywiście zakładasz, że prawdziwe projekty są zawsze poprawnie i starannie zorganizowane (może są, ale skąd taki noob, jak ja?)