Я подозреваю, что это зависит от языка. Что касается функционального программирования, я в основном баловался с Haskell, поэтому я собираюсь объяснить, как он там работает.
Код на Haskell организован в «модули», которые представляют собой просто наборы функций и типов данных. Каждый модуль представляет собой один файл. Модуль - это что-то вроде смеси между классом Java и пакетом Java - точная область действия модуля варьируется. Модуль также имеет контроль над тем, какие функции и конструкторы типов экспортировать, а какие скрыть; это похоже на private
и public
в Java.
В моих собственных программах я хочу, чтобы модули делали одну вещь, семантически; это делает их похожими на класс Java, за исключением того, что они могут определять несколько типов данных. Модули, которые я использую из стандартной библиотеки, например Data.List
, больше похожи на пакеты - они предоставляют набор похожих утилит. Это также очень похоже на статические классы Java, такие как java.util.Arrays
.
Модули также похожи на пакеты Java в том смысле, что они могут быть вложенными для ясности (я не думаю, что это влияет на сам код). В общем, для одного проекта я даю ему имя (скажем Project
), и все мои модули должны быть частью этого (например, Project.Parse
и Project.Run
). Если бы я писал код, который больше походил на библиотеку, чем на приложение, я бы организовал его на основе того, что он делал, например Data.List
или Control.Monad
. Одним из основных отличий от других языков является то, что Haskell поощряет ограничение ввода-вывода и размещение всего этого в одном месте. Большое количество модулей вообще не выполняет ввод-вывод, и для любого конкретного проекта мне бы хотелось, чтобы как можно больше модулей было чистым.
Например, я работаю над простым языком программирования, который я называю TPL (без веской причины). Для этого я создал два простых модуля: TPL.Parse
который определяет внутреннее представление языка и как его анализировать, и TPL.Run
который запускает интерпретатор и имеет дело с переменными и IO. Для фактической компиляции и запуска кода, как правило, существует Main
модуль, который в конечном итоге является точкой входа в программу.
Существует значительная свобода в организации функций в файле; это именно то, что мне нравится делать. Я определяю свои типы данных в верхней части, прежде чем они будут использованы в другом месте. Сразу после определения типов данных я реализую все, что мне нужно, чтобы сделать их частью соответствующих им классов типов - это похоже на реализацию интерфейса. Затем я следую логике и различным вспомогательным функциям, в зависимости от ситуации. Наконец, мне нравится, когда все мои функции ввода-вывода находятся в самом низу и заканчиваются на main
. Это проясняет, что именно делает любой ввод-вывод и где запускается программа.
Итак, в заключение: функции содержатся в модулях, каждый из которых состоит из одного файла. Несколько модулей могут составлять программу или библиотеку; первый обычно включает в себя Main
модуль, который является его точкой входа. Внутри файла есть разные варианты организации, но я предпочитаю группировать типы данных вверху, ввод-вывод внизу и логику посередине.
What's stopping you from...
Годы и годы программирования с совершенно другим мышлением, в том смысле, что код на Haskell не вычисляется мысленно. И, конечно, вы предполагаете, что реальные проекты всегда правильно и аккуратно организованы (может быть, они есть, но как нуб, как я, должен знать?)