Jak organizować programy funkcjonalne [zamknięte]

41

Możliwa duplikat:
programowanie funkcjonalne a OOP
Jak pisać zarządzalny kod za pomocą programowania funkcjonalnego?

W OOP podstawową jednostką organizacyjną kodu jest klasa. Często stosowaną metodologią w Javie, C # i podobnych językach jest uporządkowanie kodu wokół jednego pliku dla każdej klasy z nazwą pliku po nazwie klasy.

Możesz rozważyć każdą z tych klas jako jednostkę organizacji, aby zgrupować jedną koncepcję.

Klasy te znajdują się w przestrzeniach nazw, które często podążają za strukturą katalogów plików w rozwiązaniu / projekcie. Przestrzenie nazw to kolejny poziom organizacji.

Jak zazwyczaj organizowane są duże projekty w językach funkcjonalnych?

Jak określić, jak podzielić funkcje na różne pliki?

Czy używane są inne jednostki grupowania obok plików?

Jak zwykle kod jest zorganizowany w jednym pliku?

Gilles
źródło
18
@ S.Lott 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?)
yannis
13
@ S.Lott: Zawsze programowałem w OOP. Z ciekawości zacząłem ostatnio interesować się językami funkcjonalnymi. Mówicie: „Po co pytać tutaj?”. Odp .: Aby uzyskać mentoring i wiedzę od osób z doświadczeniem (lub ekspertów, jak to ujęła strona), którzy mogliby mnie oświecić na ten temat. Czy to nie jest celem tej strony? Czy na wszystkie programiści lub pytania SO nie można odpowiedzieć: „dlaczego nie dowiesz się sam”? Odpowiedź brzmi: tak, możesz. Ale powodem do zadania pytania jest uzyskanie lepszych / szybszych wyników od kogoś, kto jest ekspertem w tej dziedzinie.
Gilles
5
@ S.Lott: jeśli po prostu odczytuje losowy kod, skąd będzie wiedział, czy podjęte przez nich decyzje organizacyjne są dobre, czy złe? A dlaczego są dobre czy złe?
Carson63000,
4
@ S.Lott Podsumowując, posiadanie eksperta w dziedzinie języka lub paradygmatu identyfikuje dobrze zorganizowany projekt, identyfikuje wszelkie słabości / niedociągnięcia, które mogą występować w organizacji, i wyjaśnia, dlaczego jest o wiele cenniejszy niż tylko czytanie kodu i patrzenie na organizację , przy założeniu, że ma dobrą strukturę.
Thomas Owens

Odpowiedzi:

32

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 privatei publicw 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.Listsą 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.ParseI Project.Run). Gdybym pisał kod, który byłby bardziej biblioteką niż aplikacją, zorganizowałbym go na podstawie tego, co robi, jak Data.Listlub 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.Parsektóre definiują wewnętrzną reprezentację języka i jak go parsować, i TPL.Runktóre uruchamiają interpreter i zajmują się zmiennymi i IO. Do faktycznego kompilowania i uruchamiania kodu jest na ogół Mainmoduł, 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 Mainmoduł, 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.

Tikhon Jelvis
źródło